diff options
Diffstat (limited to 'source4/libnet')
-rw-r--r-- | source4/libnet/config.mk | 1 | ||||
-rw-r--r-- | source4/libnet/groupman.c | 138 | ||||
-rw-r--r-- | source4/libnet/groupman.h | 35 | ||||
-rw-r--r-- | source4/libnet/libnet.c | 3 | ||||
-rw-r--r-- | source4/libnet/libnet.h | 3 | ||||
-rw-r--r-- | source4/libnet/libnet_become_dc.c | 7 | ||||
-rw-r--r-- | source4/libnet/libnet_group.c | 2 | ||||
-rw-r--r-- | source4/libnet/libnet_join.c | 12 | ||||
-rw-r--r-- | source4/libnet/libnet_lookup.c | 7 | ||||
-rw-r--r-- | source4/libnet/libnet_samdump.c | 7 | ||||
-rw-r--r-- | source4/libnet/libnet_samdump_keytab.c | 3 | ||||
-rw-r--r-- | source4/libnet/libnet_samsync_ldb.c | 39 | ||||
-rw-r--r-- | source4/libnet/libnet_unbecome_dc.c | 5 | ||||
-rw-r--r-- | source4/libnet/libnet_user.c | 17 | ||||
-rw-r--r-- | source4/libnet/libnet_user.h | 6 | ||||
-rw-r--r-- | source4/libnet/libnet_vampire.c | 7 | ||||
-rw-r--r-- | source4/libnet/prereq_domain.c | 24 | ||||
-rw-r--r-- | source4/libnet/userman.c | 579 | ||||
-rw-r--r-- | source4/libnet/userman.h | 2 |
19 files changed, 504 insertions, 393 deletions
diff --git a/source4/libnet/config.mk b/source4/libnet/config.mk index a4cbedb515..ef0c7ff6ca 100644 --- a/source4/libnet/config.mk +++ b/source4/libnet/config.mk @@ -28,6 +28,7 @@ OBJ_FILES = \ userinfo.o \ groupinfo.o \ userman.o \ + groupman.o \ prereq_domain.o PUBLIC_DEPENDENCIES = CREDENTIALS dcerpc dcerpc_samr RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBCLI_FINDDCS LIBSAMBA3 LIBCLI_CLDAP LIBCLI_FINDDCS gensec_schannel PRIVATE_DEPENDENCIES = CREDENTIALS_KRB5 diff --git a/source4/libnet/groupman.c b/source4/libnet/groupman.c new file mode 100644 index 0000000000..de0ae0af94 --- /dev/null +++ b/source4/libnet/groupman.c @@ -0,0 +1,138 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Rafal Szczesniak 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + a composite function for manipulating (add/edit/del) groups via samr pipe +*/ + +#include "includes.h" +#include "libcli/composite/composite.h" +#include "libnet/composite.h" +#include "libnet/groupman.h" +#include "librpc/gen_ndr/ndr_samr_c.h" + + +struct groupadd_state { + struct dcerpc_pipe *pipe; + struct policy_handle domain_handle; + struct samr_CreateDomainGroup creategroup; + struct policy_handle group_handle; + uint32_t group_rid; + + void (*monitor_fn)(struct monitor_msg*); +}; + + +static void continue_groupadd_created(struct rpc_request *req); + + +struct composite_context* libnet_rpc_groupadd_send(struct dcerpc_pipe *p, + struct libnet_rpc_groupadd *io, + void (*monitor)(struct monitor_msg*)) +{ + struct composite_context *c; + struct groupadd_state *s; + struct rpc_request *create_req; + + if (!p || !io) return NULL; + + c = composite_create(p, dcerpc_event_context(p)); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct groupadd_state); + if (composite_nomem(s, c)) return c; + + c->private_data = s; + + s->domain_handle = io->in.domain_handle; + s->pipe = p; + s->monitor_fn = monitor; + + s->creategroup.in.domain_handle = &s->domain_handle; + + s->creategroup.in.name = talloc_zero(c, struct lsa_String); + if (composite_nomem(s->creategroup.in.name, c)) return c; + + s->creategroup.in.name->string = talloc_strdup(c, io->in.groupname); + if (composite_nomem(s->creategroup.in.name->string, c)) return c; + + s->creategroup.in.access_mask = 0; + + s->creategroup.out.group_handle = &s->group_handle; + s->creategroup.out.rid = &s->group_rid; + + create_req = dcerpc_samr_CreateDomainGroup_send(s->pipe, c, &s->creategroup); + if (composite_nomem(create_req, c)) return c; + + composite_continue_rpc(c, create_req, continue_groupadd_created, c); + return c; +} + + +NTSTATUS libnet_rpc_groupadd_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, + struct libnet_rpc_groupadd *io) +{ + NTSTATUS status; + struct groupadd_state *s; + + status = composite_wait(c); + if (NT_STATUS_IS_OK(status)) { + s = talloc_get_type(c, struct groupadd_state); + } + + return status; +} + + +static void continue_groupadd_created(struct rpc_request *req) +{ + struct composite_context *c; + struct groupadd_state *s; + + c = talloc_get_type(req->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct groupadd_state); + + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + + c->status = s->creategroup.out.result; + if (!composite_is_ok(c)) return; + + if (s->monitor_fn) { + struct monitor_msg msg; + + msg.type = mon_SamrCreateUser; + msg.data = NULL; + msg.data_size = 0; + + s->monitor_fn(&msg); + } + + composite_done(c); +} + + +NTSTATUS libnet_rpc_groupadd(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct libnet_rpc_groupadd *io) +{ + struct composite_context *c; + + c = libnet_rpc_groupadd_send(p, io, NULL); + return libnet_rpc_groupadd_recv(c, mem_ctx, io); +} diff --git a/source4/libnet/groupman.h b/source4/libnet/groupman.h new file mode 100644 index 0000000000..0acb02de5a --- /dev/null +++ b/source4/libnet/groupman.h @@ -0,0 +1,35 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Rafal Szczesniak 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "librpc/gen_ndr/misc.h" + + +/* + * IO structures for groupman.c functions + */ + +struct libnet_rpc_groupadd { + struct { + struct policy_handle domain_handle; + const char *groupname; + } in; + struct { + struct policy_handle group_handle; + } out; +}; diff --git a/source4/libnet/libnet.c b/source4/libnet/libnet.c index a628a07a99..86804df1ea 100644 --- a/source4/libnet/libnet.c +++ b/source4/libnet/libnet.c @@ -20,6 +20,7 @@ #include "includes.h" #include "libnet/libnet.h" #include "lib/events/events.h" +#include "param/param.h" struct libnet_context *libnet_context_init(struct event_context *ev) { @@ -42,7 +43,7 @@ struct libnet_context *libnet_context_init(struct event_context *ev) ctx->event_ctx = ev; /* name resolution methods */ - ctx->name_res_methods = str_list_copy(ctx, lp_name_resolve_order()); + ctx->name_res_methods = str_list_copy(ctx, lp_name_resolve_order(global_loadparm)); /* connected services' params */ ZERO_STRUCT(ctx->samr); diff --git a/source4/libnet/libnet.h b/source4/libnet/libnet.h index a51fa613a8..56a7d0ba20 100644 --- a/source4/libnet/libnet.h +++ b/source4/libnet/libnet.h @@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "librpc/gen_ndr/misc.h" + struct libnet_context { /* here we need: * a client env context @@ -56,6 +58,7 @@ struct libnet_context { #include "libnet/userman.h" #include "libnet/userinfo.h" #include "libnet/groupinfo.h" +#include "libnet/groupman.h" #include "libnet/libnet_passwd.h" #include "libnet/libnet_time.h" #include "libnet/libnet_rpc.h" diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index e2f4f03c60..cd782066db 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -32,6 +32,7 @@ #include "librpc/gen_ndr/ndr_security.h" #include "librpc/gen_ndr/ndr_drsuapi.h" #include "auth/gensec/gensec.h" +#include "param/param.h" /***************************************************************************** * Windows 2003 (w2k3) does the following steps when changing the server role @@ -789,7 +790,7 @@ static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct be url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name); NT_STATUS_HAVE_NO_MEMORY(url); - ldap->ldb = ldb_wrap_connect(s, url, + ldap->ldb = ldb_wrap_connect(s, global_loadparm, url, NULL, s->libnet->cred, 0, NULL); @@ -1510,7 +1511,7 @@ static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s, drsuapi->s = s; if (!drsuapi->binding) { - if (lp_parm_bool(-1, "become_dc", "print", False)) { + if (lp_parm_bool(global_loadparm, NULL, "become_dc", "print", false)) { binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,print,seal]", s->source_dsa.dns_name); if (composite_nomem(binding_str, c)) return; } else { @@ -2909,7 +2910,7 @@ struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLO /* Destination DSA dns_name construction */ tmp_name = strlower_talloc(s, s->dest_dsa.netbios_name); if (composite_nomem(tmp_name, c)) return c; - tmp_name = talloc_asprintf_append(tmp_name, ".%s",s->domain.dns_name); + tmp_name = talloc_asprintf_append_buffer(tmp_name, ".%s",s->domain.dns_name); if (composite_nomem(tmp_name, c)) return c; s->dest_dsa.dns_name = tmp_name; diff --git a/source4/libnet/libnet_group.c b/source4/libnet/libnet_group.c index 50615f3946..39e5e7a4f9 100644 --- a/source4/libnet/libnet_group.c +++ b/source4/libnet/libnet_group.c @@ -57,7 +57,7 @@ struct composite_context* libnet_GroupInfo_send(struct libnet_context *ctx, { struct composite_context *c; struct group_info_state *s; - BOOL prereq_met = False; + bool prereq_met = false; struct composite_context *lookup_req; /* composite context allocation and setup */ diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c index 40debc63dc..4abd2954f8 100644 --- a/source4/libnet/libnet_join.c +++ b/source4/libnet/libnet_join.c @@ -31,6 +31,7 @@ #include "auth/credentials/credentials.h" #include "auth/credentials/credentials_krb5.h" #include "librpc/gen_ndr/ndr_samr_c.h" +#include "param/param.h" /* * complete a domain join, when joining to a AD domain: @@ -227,7 +228,8 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J return NT_STATUS_NO_MEMORY; } - remote_ldb = ldb_wrap_connect(tmp_ctx, remote_ldb_url, + remote_ldb = ldb_wrap_connect(tmp_ctx, global_loadparm, + remote_ldb_url, NULL, ctx->cred, 0, NULL); if (!remote_ldb) { r->out.error_string = NULL; @@ -534,8 +536,8 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, r->in.domain_name); } else { /* Bugger, we just lost our way to automaticly find the domain name */ - connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lp_workgroup()); - connect_with_info->out.realm = talloc_strdup(tmp_ctx, lp_realm()); + connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lp_workgroup(global_loadparm)); + connect_with_info->out.realm = talloc_strdup(tmp_ctx, lp_realm(global_loadparm)); } } @@ -887,7 +889,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, if (r->in.netbios_name != NULL) { netbios_name = r->in.netbios_name; } else { - netbios_name = talloc_reference(tmp_mem, lp_netbios_name()); + netbios_name = talloc_reference(tmp_mem, lp_netbios_name(global_loadparm)); if (!netbios_name) { r->out.error_string = NULL; talloc_free(tmp_mem); @@ -924,7 +926,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, r2->in.netbios_name = netbios_name; r2->in.level = LIBNET_JOINDOMAIN_AUTOMATIC; r2->in.acct_type = acct_type; - r2->in.recreate_account = False; + r2->in.recreate_account = false; status = libnet_JoinDomain(ctx, r2, r2); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_steal(mem_ctx, r2->out.error_string); diff --git a/source4/libnet/libnet_lookup.c b/source4/libnet/libnet_lookup.c index 6856156734..459e5b1985 100644 --- a/source4/libnet/libnet_lookup.c +++ b/source4/libnet/libnet_lookup.c @@ -34,6 +34,8 @@ #include "librpc/gen_ndr/lsa.h" #include "librpc/gen_ndr/ndr_lsa_c.h" +#include "param/param.h" + struct lookup_state { struct nbt_name hostname; const char *address; @@ -189,7 +191,8 @@ struct composite_context* libnet_LookupDCs_send(struct libnet_context *ctx, struct libnet_LookupDCs *io) { struct composite_context *c; - struct messaging_context *msg_ctx = messaging_client_init(mem_ctx, ctx->event_ctx); + struct messaging_context *msg_ctx = + messaging_client_init(mem_ctx, lp_messaging_path(mem_ctx, global_loadparm), ctx->event_ctx); c = finddcs_send(mem_ctx, io->in.domain_name, io->in.name_type, NULL, ctx->name_res_methods, ctx->event_ctx, msg_ctx); @@ -257,7 +260,7 @@ struct composite_context* libnet_LookupName_send(struct libnet_context *ctx, struct composite_context *c; struct lookup_name_state *s; struct rpc_request *lookup_req; - BOOL prereq_met = False; + bool prereq_met = false; c = composite_create(mem_ctx, ctx->event_ctx); if (c == NULL) return NULL; diff --git a/source4/libnet/libnet_samdump.c b/source4/libnet/libnet_samdump.c index fb4267748a..5c7266d7a8 100644 --- a/source4/libnet/libnet_samdump.c +++ b/source4/libnet/libnet_samdump.c @@ -110,7 +110,7 @@ static NTSTATUS libnet_samdump_fn(TALLOC_CTX *mem_ctx, char **error_string) { NTSTATUS nt_status = NT_STATUS_OK; - struct samdump_state *samdump_state = private; + struct samdump_state *samdump_state = (struct samdump_state *)private; *error_string = NULL; switch (delta->delta_type) { @@ -144,7 +144,8 @@ static NTSTATUS libnet_samdump_fn(TALLOC_CTX *mem_ctx, return nt_status; } -NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamDump *r) +NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, + struct libnet_SamDump *r) { NTSTATUS nt_status; struct libnet_SamSync r2; @@ -162,7 +163,7 @@ NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct r2.out.error_string = NULL; r2.in.binding_string = r->in.binding_string; - r2.in.rid_crypt = lp_parm_bool(-1, "vampire", "rid decrypt", True); + r2.in.rid_crypt = lp_parm_bool(global_loadparm, NULL, "vampire", "rid decrypt", true); r2.in.init_fn = NULL; r2.in.delta_fn = libnet_samdump_fn; r2.in.fn_ctx = samdump_state; diff --git a/source4/libnet/libnet_samdump_keytab.c b/source4/libnet/libnet_samdump_keytab.c index 0eae9de039..c235df6d25 100644 --- a/source4/libnet/libnet_samdump_keytab.c +++ b/source4/libnet/libnet_samdump_keytab.c @@ -25,6 +25,7 @@ #include "system/kerberos.h" #include "auth/credentials/credentials.h" #include "auth/credentials/credentials_krb5.h" +#include "param/param.h" static NTSTATUS samdump_keytab_handle_user(TALLOC_CTX *mem_ctx, const char *keytab_name, @@ -44,7 +45,7 @@ static NTSTATUS samdump_keytab_handle_user(TALLOC_CTX *mem_ctx, if (!credentials) { return NT_STATUS_NO_MEMORY; } - cli_credentials_set_conf(credentials); + cli_credentials_set_conf(credentials, global_loadparm); cli_credentials_set_username(credentials, username, CRED_SPECIFIED); /* We really should consult ldap in the main SamSync code, and diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c index 338b15d6d7..bdc3341aa6 100644 --- a/source4/libnet/libnet_samsync_ldb.c +++ b/source4/libnet/libnet_samsync_ldb.c @@ -31,6 +31,7 @@ #include "db_wrap.h" #include "libcli/security/security.h" #include "librpc/rpc/dcerpc.h" +#include "param/param.h" struct samsync_ldb_secret { struct samsync_ldb_secret *prev, *next; @@ -246,7 +247,7 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, struct ldb_message **remote_msgs = NULL; int ret, i; uint32_t acb; - BOOL add = False; + bool add = false; const char *attrs[] = { NULL }; /* we may change this to a global search, then fill in only the things not in ldap later */ const char *remote_attrs[] = { "userPrincipalName", "servicePrincipalName", @@ -274,7 +275,7 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } else if (ret == 0) { - add = True; + add = true; } else if (ret > 1) { *error_string = talloc_asprintf(mem_ctx, "More than one user with SID: %s in local LDB", dom_sid_string(mem_ctx, user_sid)); @@ -431,14 +432,21 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, if (ret != 0) { struct ldb_dn *first_try_dn = msg->dn; /* Try again with the default DN */ - msg->dn = talloc_steal(msg, msgs[0]->dn); - ret = samdb_add(state->sam_ldb, mem_ctx, msg); - if (ret != 0) { - *error_string = talloc_asprintf(mem_ctx, "Failed to create user record. Tried both %s and %s: %s", + if (!remote_msgs) { + *error_string = talloc_asprintf(mem_ctx, "Failed to create user record. Tried %s: %s", ldb_dn_get_linearized(first_try_dn), - ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; + } else { + msg->dn = talloc_steal(msg, remote_msgs[0]->dn); + ret = samdb_add(state->sam_ldb, mem_ctx, msg); + if (ret != 0) { + *error_string = talloc_asprintf(mem_ctx, "Failed to create user record. Tried both %s and %s: %s", + ldb_dn_get_linearized(first_try_dn), + ldb_dn_get_linearized(msg->dn), + ldb_errstring(state->sam_ldb)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } } } } else { @@ -509,7 +517,7 @@ static NTSTATUS samsync_ldb_handle_group(TALLOC_CTX *mem_ctx, struct ldb_message *msg; struct ldb_message **msgs; int ret; - BOOL add = False; + bool add = false; const char *attrs[] = { NULL }; msg = ldb_msg_new(mem_ctx); @@ -526,7 +534,7 @@ static NTSTATUS samsync_ldb_handle_group(TALLOC_CTX *mem_ctx, *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } else if (ret == 0) { - add = True; + add = true; } else if (ret > 1) { *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s", dom_sid_string(mem_ctx, @@ -721,7 +729,7 @@ static NTSTATUS samsync_ldb_handle_alias(TALLOC_CTX *mem_ctx, struct ldb_message *msg; struct ldb_message **msgs; int ret; - BOOL add = False; + bool add = false; const char *attrs[] = { NULL }; msg = ldb_msg_new(mem_ctx); @@ -738,7 +746,7 @@ static NTSTATUS samsync_ldb_handle_alias(TALLOC_CTX *mem_ctx, *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } else if (ret == 0) { - add = True; + add = true; } else if (ret > 1) { *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s", dom_sid_string(mem_ctx, @@ -1183,7 +1191,9 @@ static NTSTATUS libnet_samsync_ldb_init(TALLOC_CTX *mem_ctx, } ldap_url = talloc_asprintf(state, "ldap://%s", server); - state->remote_ldb = ldb_wrap_connect(mem_ctx, ldap_url, + state->remote_ldb = ldb_wrap_connect(mem_ctx, + global_loadparm, + ldap_url, NULL, state->samsync_state->machine_net_ctx->cred, 0, NULL); if (!state->remote_ldb) { @@ -1209,7 +1219,10 @@ NTSTATUS libnet_samsync_ldb(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, str state->secrets = NULL; state->trusted_domains = NULL; - state->sam_ldb = ldb_wrap_connect(mem_ctx, lp_sam_url(), r->in.session_info, + state->sam_ldb = ldb_wrap_connect(mem_ctx, + global_loadparm, + lp_sam_url(global_loadparm), + r->in.session_info, ctx->cred, 0, NULL); r2.out.error_string = NULL; diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c index 6b63ebc839..40b1aab215 100644 --- a/source4/libnet/libnet_unbecome_dc.c +++ b/source4/libnet/libnet_unbecome_dc.c @@ -27,6 +27,7 @@ #include "dsdb/samdb/samdb.h" #include "dsdb/common/flags.h" #include "librpc/gen_ndr/ndr_drsuapi_c.h" +#include "param/param.h" /***************************************************************************** * Windows 2003 (w2k3) does the following steps when changing the server role @@ -307,7 +308,7 @@ static NTSTATUS unbecomeDC_ldap_connect(struct libnet_UnbecomeDC_state *s) url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name); NT_STATUS_HAVE_NO_MEMORY(url); - s->ldap.ldb = ldb_wrap_connect(s, url, + s->ldap.ldb = ldb_wrap_connect(s, global_loadparm, url, NULL, s->libnet->cred, 0, NULL); @@ -698,7 +699,7 @@ struct composite_context *libnet_UnbecomeDC_send(struct libnet_context *ctx, TAL /* Destination DSA dns_name construction */ tmp_name = strlower_talloc(s, s->dest_dsa.netbios_name); if (composite_nomem(tmp_name, c)) return c; - s->dest_dsa.dns_name = talloc_asprintf_append(tmp_name, ".%s", + s->dest_dsa.dns_name = talloc_asprintf_append_buffer(tmp_name, ".%s", s->domain.dns_name); if (composite_nomem(s->dest_dsa.dns_name, c)) return c; diff --git a/source4/libnet/libnet_user.c b/source4/libnet/libnet_user.c index fe303620fe..75fd8f2000 100644 --- a/source4/libnet/libnet_user.c +++ b/source4/libnet/libnet_user.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. - Copyright (C) Rafal Szczesniak <mimir@samba.org> 2005 + Copyright (C) Rafal Szczesniak 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -62,7 +62,7 @@ struct composite_context* libnet_CreateUser_send(struct libnet_context *ctx, struct composite_context *c; struct create_user_state *s; struct composite_context *create_req; - BOOL prereq_met = False; + bool prereq_met = false; /* composite context allocation and setup */ c = composite_create(mem_ctx, ctx->event_ctx); @@ -231,7 +231,7 @@ struct composite_context *libnet_DeleteUser_send(struct libnet_context *ctx, struct composite_context *c; struct delete_user_state *s; struct composite_context *delete_req; - BOOL prereq_met = False; + bool prereq_met = false; /* composite context allocation and setup */ c = composite_create(mem_ctx, ctx->event_ctx); @@ -402,7 +402,7 @@ struct composite_context *libnet_ModifyUser_send(struct libnet_context *ctx, struct composite_context *c; struct modify_user_state *s; struct composite_context *userinfo_req; - BOOL prereq_met = False; + bool prereq_met = false; c = composite_create(mem_ctx, ctx->event_ctx); if (c == NULL) return NULL; @@ -533,6 +533,9 @@ static NTSTATUS set_user_changes(TALLOC_CTX *mem_ctx, struct usermod_change *mod /* account expiry change */ SET_FIELD_NTTIME(r->in, user, mod, acct_expiry, USERMOD_FIELD_ACCT_EXPIRY); + /* account flags change */ + SET_FIELD_UINT32(r->in, user, mod, acct_flags, USERMOD_FIELD_ACCT_FLAGS); + return NT_STATUS_OK; } @@ -626,7 +629,7 @@ struct composite_context* libnet_UserInfo_send(struct libnet_context *ctx, struct composite_context *c; struct user_info_state *s; struct composite_context *lookup_req; - BOOL prereq_met = False; + bool prereq_met = false; /* composite context allocation and setup */ c = composite_create(mem_ctx, ctx->event_ctx); @@ -875,7 +878,7 @@ struct composite_context* libnet_UserList_send(struct libnet_context *ctx, struct composite_context *c; struct userlist_state *s; struct rpc_request *query_req; - BOOL prereq_met = False; + bool prereq_met = false; /* composite context allocation and setup */ c = composite_create(mem_ctx, ctx->event_ctx); @@ -949,7 +952,7 @@ static void continue_domain_queried(struct rpc_request *req) struct composite_context *c; struct userlist_state *s; struct rpc_request *enum_req; - BOOL prereq_met = False; + bool prereq_met = false; c = talloc_get_type(req->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct userlist_state); diff --git a/source4/libnet/libnet_user.h b/source4/libnet/libnet_user.h index 3bbe1cc65e..ece06f08fc 100644 --- a/source4/libnet/libnet_user.h +++ b/source4/libnet/libnet_user.h @@ -85,6 +85,12 @@ struct libnet_ModifyUser { } \ } +#define SET_FIELD_UINT32(new, current, mod, field, flag) \ + if (current->field != new.field) { \ + mod->field = new.field; \ + mod->fields |= flag; \ + } + struct libnet_UserInfo { struct { diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c index e21976cb02..dff915df71 100644 --- a/source4/libnet/libnet_vampire.c +++ b/source4/libnet/libnet_vampire.c @@ -28,6 +28,7 @@ #include "auth/gensec/schannel_proto.h" #include "librpc/gen_ndr/ndr_netlogon.h" #include "librpc/gen_ndr/ndr_netlogon_c.h" +#include "param/param.h" /** @@ -80,7 +81,7 @@ static NTSTATUS fix_user(TALLOC_CTX *mem_ctx, } else { user->lmpassword = keys.keys.keys2.lmpassword.pwd; } - user->lm_password_present = True; + user->lm_password_present = true; } if (keys.keys.keys2.ntpassword.length == 16) { if (rid_crypt) { @@ -89,7 +90,7 @@ static NTSTATUS fix_user(TALLOC_CTX *mem_ctx, } else { user->ntpassword = keys.keys.keys2.ntpassword.pwd; } - user->nt_password_present = True; + user->nt_password_present = true; } /* TODO: rid decrypt history fields */ } else { @@ -184,7 +185,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx talloc_free(samsync_ctx); return NT_STATUS_NO_MEMORY; } - cli_credentials_set_conf(machine_account); + cli_credentials_set_conf(machine_account, global_loadparm); nt_status = cli_credentials_set_machine_account(machine_account); if (!NT_STATUS_IS_OK(nt_status)) { r->out.error_string = talloc_strdup(mem_ctx, "Could not obtain machine account password - are we joined to the domain?"); diff --git a/source4/libnet/prereq_domain.c b/source4/libnet/prereq_domain.c index 52f8dcf112..e10e550585 100644 --- a/source4/libnet/prereq_domain.c +++ b/source4/libnet/prereq_domain.c @@ -29,7 +29,7 @@ #include "librpc/gen_ndr/ndr_lsa.h" -BOOL samr_domain_opened(struct libnet_context *ctx, const char *domain_name, +bool samr_domain_opened(struct libnet_context *ctx, const char *domain_name, struct composite_context **parent_ctx, struct libnet_DomainOpen *domain_open, void (*continue_fn)(struct composite_context*), @@ -37,7 +37,7 @@ BOOL samr_domain_opened(struct libnet_context *ctx, const char *domain_name, { struct composite_context *domopen_req; - if (parent_ctx == NULL || *parent_ctx == NULL) return False; + if (parent_ctx == NULL || *parent_ctx == NULL) return false; if (domain_name == NULL) { /* @@ -52,7 +52,7 @@ BOOL samr_domain_opened(struct libnet_context *ctx, const char *domain_name, } else { composite_error(*parent_ctx, NT_STATUS_INVALID_PARAMETER); - return True; + return true; } } else { @@ -71,20 +71,20 @@ BOOL samr_domain_opened(struct libnet_context *ctx, const char *domain_name, } else { /* domain has already been opened and it's the same domain as requested */ - return True; + return true; } } /* send request to open the domain */ domopen_req = libnet_DomainOpen_send(ctx, domain_open, monitor); - if (composite_nomem(domopen_req, *parent_ctx)) return False; + if (composite_nomem(domopen_req, *parent_ctx)) return false; composite_continue(*parent_ctx, domopen_req, continue_fn, *parent_ctx); - return False; + return false; } -BOOL lsa_domain_opened(struct libnet_context *ctx, const char *domain_name, +bool lsa_domain_opened(struct libnet_context *ctx, const char *domain_name, struct composite_context **parent_ctx, struct libnet_DomainOpen *domain_open, void (*continue_fn)(struct composite_context*), @@ -92,7 +92,7 @@ BOOL lsa_domain_opened(struct libnet_context *ctx, const char *domain_name, { struct composite_context *domopen_req; - if (parent_ctx == NULL || *parent_ctx == NULL) return False; + if (parent_ctx == NULL || *parent_ctx == NULL) return false; if (domain_name == NULL) { /* @@ -109,7 +109,7 @@ BOOL lsa_domain_opened(struct libnet_context *ctx, const char *domain_name, composite_error(*parent_ctx, NT_STATUS_INVALID_PARAMETER); /* this ensures the calling function exits and composite function error gets noticed quickly */ - return True; + return true; } } else { @@ -128,15 +128,15 @@ BOOL lsa_domain_opened(struct libnet_context *ctx, const char *domain_name, } else { /* domain has already been opened and it's the same domain as requested */ - return True; + return true; } } /* send request to open the domain */ domopen_req = libnet_DomainOpen_send(ctx, domain_open, monitor); /* see the comment above to find out why true is returned here */ - if (composite_nomem(domopen_req, *parent_ctx)) return True; + if (composite_nomem(domopen_req, *parent_ctx)) return true; composite_continue(*parent_ctx, domopen_req, continue_fn, *parent_ctx); - return False; + return false; } diff --git a/source4/libnet/userman.c b/source4/libnet/userman.c index 2efb892155..25ed4775cb 100644 --- a/source4/libnet/userman.c +++ b/source4/libnet/userman.c @@ -32,12 +32,7 @@ * Composite USER ADD functionality */ -static void useradd_handler(struct rpc_request*); - -enum useradd_stage { USERADD_CREATE }; - struct useradd_state { - enum useradd_stage stage; struct dcerpc_pipe *pipe; struct rpc_request *req; struct policy_handle domain_handle; @@ -50,64 +45,46 @@ struct useradd_state { }; +static void continue_useradd_create(struct rpc_request *req); + + /** * Stage 1 (and the only one for now): Create user account. */ -static NTSTATUS useradd_create(struct composite_context *c, - struct useradd_state *s) +static void continue_useradd_create(struct rpc_request *req) { + struct composite_context *c; + struct useradd_state *s; + + c = talloc_get_type(req->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct useradd_state); + + /* check rpc layer status code */ c->status = dcerpc_ndr_request_recv(s->req); - NT_STATUS_NOT_OK_RETURN(c->status); + if (!composite_is_ok(c)) return; - /* return the actual function call status */ + /* check create user call status code */ c->status = s->createuser.out.result; - - c->state = COMPOSITE_STATE_DONE; - return c->status; -} + /* get created user account data */ + s->user_handle = *s->createuser.out.user_handle; + s->user_rid = *s->createuser.out.rid; -/** - * Event handler for asynchronous request. Handles transition through - * intermediate stages of the call. - * - * @param req rpc call context - */ -static void useradd_handler(struct rpc_request *req) -{ - struct composite_context *c = req->async.private_data; - struct useradd_state *s = talloc_get_type(c->private_data, struct useradd_state); - struct monitor_msg msg; - struct msg_rpc_create_user *rpc_create; - - switch (s->stage) { - case USERADD_CREATE: - c->status = useradd_create(c, s); - - /* prepare a message to pass to monitor function */ - msg.type = mon_SamrCreateUser; - rpc_create = talloc(s, struct msg_rpc_create_user); - rpc_create->rid = *s->createuser.out.rid; - msg.data = (void*)rpc_create; - msg.data_size = sizeof(*rpc_create); - break; - } + /* issue a monitor message */ + if (s->monitor_fn) { + struct monitor_msg msg; + struct msg_rpc_create_user rpc_create; - /* are we ok so far ? */ - if (!NT_STATUS_IS_OK(c->status)) { - c->state = COMPOSITE_STATE_ERROR; - } + rpc_create.rid = *s->createuser.out.rid; - /* call monitor function provided the pointer has been passed */ - if (s->monitor_fn) { + msg.type = mon_SamrCreateUser; + msg.data = (void*)&rpc_create; + msg.data_size = sizeof(rpc_create); + s->monitor_fn(&msg); } - - /* are we done yet ? */ - if (c->state >= COMPOSITE_STATE_DONE && - c->async.fn) { - c->async.fn(c); - } + + composite_done(c); } @@ -158,11 +135,7 @@ struct composite_context *libnet_rpc_useradd_send(struct dcerpc_pipe *p, s->req = dcerpc_samr_CreateUser_send(p, c, &s->createuser); if (composite_nomem(s->req, c)) return c; - /* callback handler for continuation */ - s->req->async.callback = useradd_handler; - s->req->async.private_data = c; - s->stage = USERADD_CREATE; - + composite_continue_rpc(c, s->req, continue_useradd_create, c); return c; } @@ -218,14 +191,9 @@ NTSTATUS libnet_rpc_useradd(struct dcerpc_pipe *p, * Composite USER DELETE functionality */ -static void userdel_handler(struct rpc_request*); - -enum userdel_stage { USERDEL_LOOKUP, USERDEL_OPEN, USERDEL_DELETE }; struct userdel_state { - enum userdel_stage stage; struct dcerpc_pipe *pipe; - struct rpc_request *req; struct policy_handle domain_handle; struct policy_handle user_handle; struct samr_LookupNames lookupname; @@ -237,166 +205,155 @@ struct userdel_state { }; +static void continue_userdel_name_found(struct rpc_request *req); +static void continue_userdel_user_opened(struct rpc_request* req); +static void continue_userdel_deleted(struct rpc_request *req); + + /** * Stage 1: Lookup the user name and resolve it to rid */ -static NTSTATUS userdel_lookup(struct composite_context *c, - struct userdel_state *s) +static void continue_userdel_name_found(struct rpc_request *req) { - /* receive samr_LookupNames result */ - c->status = dcerpc_ndr_request_recv(s->req); + struct composite_context *c; + struct userdel_state *s; + struct rpc_request *openuser_req; + struct monitor_msg msg; - /* check rpc layer status */ - NT_STATUS_NOT_OK_RETURN(c->status); + c = talloc_get_type(req->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct userdel_state); - /* check the call itself status */ - NT_STATUS_NOT_OK_RETURN(s->lookupname.out.result); + /* receive samr_LookupNames result */ + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + + c->status = s->lookupname.out.result; + if (!NT_STATUS_IS_OK(c->status)) { + composite_error(c, c->status); + return; + } /* what to do when there's no user account to delete and what if there's more than one rid resolved */ if (!s->lookupname.out.rids.count) { c->status = NT_STATUS_NO_SUCH_USER; composite_error(c, c->status); + return; } else if (!s->lookupname.out.rids.count > 1) { c->status = NT_STATUS_INVALID_ACCOUNT_NAME; composite_error(c, c->status); + return; } - /* prepare the next rpc call arguments */ + /* issue a monitor message */ + if (s->monitor_fn) { + struct msg_rpc_lookup_name msg_lookup; + + msg_lookup.rid = s->lookupname.out.rids.ids; + msg_lookup.count = s->lookupname.out.rids.count; + + msg.type = mon_SamrLookupName; + msg.data = (void*)&msg_lookup; + msg.data_size = sizeof(msg_lookup); + s->monitor_fn(&msg); + } + + /* prepare the arguments for rpc call */ s->openuser.in.domain_handle = &s->domain_handle; s->openuser.in.rid = s->lookupname.out.rids.ids[0]; s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; s->openuser.out.user_handle = &s->user_handle; /* send rpc request */ - s->req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser); - if (s->req == NULL) return NT_STATUS_NO_MEMORY; + openuser_req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser); + if (composite_nomem(openuser_req, c)) return; - /* callback handler setup */ - s->req->async.callback = userdel_handler; - s->req->async.private_data = c; - s->stage = USERDEL_OPEN; - - return NT_STATUS_OK; + composite_continue_rpc(c, openuser_req, continue_userdel_user_opened, c); } /** * Stage 2: Open user account. */ -static NTSTATUS userdel_open(struct composite_context *c, - struct userdel_state *s) +static void continue_userdel_user_opened(struct rpc_request* req) { + struct composite_context *c; + struct userdel_state *s; + struct rpc_request *deluser_req; + struct monitor_msg msg; + + c = talloc_get_type(req->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct userdel_state); + /* receive samr_OpenUser result */ - c->status = dcerpc_ndr_request_recv(s->req); - NT_STATUS_NOT_OK_RETURN(c->status); + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + + c->status = s->openuser.out.result; + if (!NT_STATUS_IS_OK(c->status)) { + composite_error(c, c->status); + return; + } + + /* issue a monitor message */ + if (s->monitor_fn) { + struct msg_rpc_open_user msg_open; + + msg_open.rid = s->openuser.in.rid; + msg_open.access_mask = s->openuser.in.access_mask; + + msg.type = mon_SamrOpenUser; + msg.data = (void*)&msg_open; + msg.data_size = sizeof(msg_open); + s->monitor_fn(&msg); + } /* prepare the final rpc call arguments */ s->deleteuser.in.user_handle = &s->user_handle; s->deleteuser.out.user_handle = &s->user_handle; /* send rpc request */ - s->req = dcerpc_samr_DeleteUser_send(s->pipe, c, &s->deleteuser); - if (s->req == NULL) return NT_STATUS_NO_MEMORY; + deluser_req = dcerpc_samr_DeleteUser_send(s->pipe, c, &s->deleteuser); + if (composite_nomem(deluser_req, c)) return; /* callback handler setup */ - s->req->async.callback = userdel_handler; - s->req->async.private_data = c; - s->stage = USERDEL_DELETE; - - return NT_STATUS_OK; + composite_continue_rpc(c, deluser_req, continue_userdel_deleted, c); } /** * Stage 3: Delete user account */ -static NTSTATUS userdel_delete(struct composite_context *c, - struct userdel_state *s) -{ - /* receive samr_DeleteUser result */ - c->status = dcerpc_ndr_request_recv(s->req); - NT_STATUS_NOT_OK_RETURN(c->status); - - /* return the actual function call status */ - c->status = s->deleteuser.out.result; - - c->state = COMPOSITE_STATE_DONE; - - return c->status; -} - - -/** - * Event handler for asynchronous request. Handles transition through - * intermediate stages of the call. - * - * @param req rpc call context - */ -static void userdel_handler(struct rpc_request *req) +static void continue_userdel_deleted(struct rpc_request *req) { struct composite_context *c; struct userdel_state *s; struct monitor_msg msg; - struct msg_rpc_lookup_name *msg_lookup; - struct msg_rpc_open_user *msg_open; c = talloc_get_type(req->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct userdel_state); - - switch (s->stage) { - case USERDEL_LOOKUP: - c->status = userdel_lookup(c, s); - - /* monitor message */ - msg.type = mon_SamrLookupName; - msg_lookup = talloc(s, struct msg_rpc_lookup_name); - - msg_lookup->rid = s->lookupname.out.rids.ids; - msg_lookup->count = s->lookupname.out.rids.count; - msg.data = (void*)msg_lookup; - msg.data_size = sizeof(*msg_lookup); - break; - - case USERDEL_OPEN: - c->status = userdel_open(c, s); - - /* monitor message */ - msg.type = mon_SamrOpenUser; - msg_open = talloc(s, struct msg_rpc_open_user); - - msg_open->rid = s->openuser.in.rid; - msg_open->access_mask = s->openuser.in.rid; - msg.data = (void*)msg_open; - msg.data_size = sizeof(*msg_open); - break; - - case USERDEL_DELETE: - c->status = userdel_delete(c, s); - - /* monitor message */ - msg.type = mon_SamrDeleteUser; - msg.data = NULL; - msg.data_size = 0; - break; - } - /* are we ok, so far ? */ + /* receive samr_DeleteUser result */ + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + + /* return the actual function call status */ + c->status = s->deleteuser.out.result; if (!NT_STATUS_IS_OK(c->status)) { - c->state = COMPOSITE_STATE_ERROR; + composite_error(c, c->status); + return; } - - /* call monitor function provided the pointer has been passed */ + + /* issue a monitor message */ if (s->monitor_fn) { + msg.type = mon_SamrDeleteUser; + msg.data = NULL; + msg.data_size = 0; s->monitor_fn(&msg); } - /* are we done yet */ - if (c->state >= COMPOSITE_STATE_DONE && - c->async.fn) { - c->async.fn(c); - } + composite_done(c); } @@ -414,17 +371,16 @@ struct composite_context *libnet_rpc_userdel_send(struct dcerpc_pipe *p, { struct composite_context *c; struct userdel_state *s; + struct rpc_request *lookup_req; /* composite context allocation and setup */ - c = talloc_zero(p, struct composite_context); + c = composite_create(p, dcerpc_event_context(p)); if (c == NULL) return NULL; s = talloc_zero(c, struct userdel_state); if (composite_nomem(s, c)) return c; - c->state = COMPOSITE_STATE_IN_PROGRESS; c->private_data = s; - c->event_ctx = dcerpc_event_context(p); /* store function parameters in the state structure */ s->pipe = p; @@ -438,13 +394,11 @@ struct composite_context *libnet_rpc_userdel_send(struct dcerpc_pipe *p, s->lookupname.in.names->string = io->in.username; /* send the request */ - s->req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname); - - /* callback handler setup */ - s->req->async.callback = userdel_handler; - s->req->async.private_data = c; - s->stage = USERDEL_LOOKUP; + lookup_req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname); + if (composite_nomem(lookup_req, c)) return c; + /* set the next stage */ + composite_continue_rpc(c, lookup_req, continue_userdel_name_found, c); return c; } @@ -498,14 +452,14 @@ NTSTATUS libnet_rpc_userdel(struct dcerpc_pipe *p, * USER MODIFY functionality */ -static void usermod_handler(struct rpc_request*); +static void continue_usermod_name_found(struct rpc_request *req); +static void continue_usermod_user_opened(struct rpc_request *req); +static void continue_usermod_user_queried(struct rpc_request *req); +static void continue_usermod_user_changed(struct rpc_request *req); -enum usermod_stage { USERMOD_LOOKUP, USERMOD_OPEN, USERMOD_QUERY, USERMOD_MODIFY }; struct usermod_state { - enum usermod_stage stage; struct dcerpc_pipe *pipe; - struct rpc_request *req; struct policy_handle domain_handle; struct policy_handle user_handle; struct usermod_change change; @@ -523,24 +477,50 @@ struct usermod_state { /** * Step 1: Lookup user name */ -static NTSTATUS usermod_lookup(struct composite_context *c, - struct usermod_state *s) +static void continue_usermod_name_found(struct rpc_request *req) { + struct composite_context *c; + struct usermod_state *s; + struct rpc_request *openuser_req; + struct monitor_msg msg; + + c = talloc_get_type(req->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct usermod_state); + /* receive samr_LookupNames result */ - c->status = dcerpc_ndr_request_recv(s->req); - NT_STATUS_NOT_OK_RETURN(c->status); + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + + c->status = s->lookupname.out.result; + if (!NT_STATUS_IS_OK(c->status)) { + composite_error(c, c->status); + return; + } /* what to do when there's no user account to delete and what if there's more than one rid resolved */ if (!s->lookupname.out.rids.count) { c->status = NT_STATUS_NO_SUCH_USER; - c->state = COMPOSITE_STATE_ERROR; - return c->status; + composite_error(c, c->status); + return; } else if (!s->lookupname.out.rids.count > 1) { c->status = NT_STATUS_INVALID_ACCOUNT_NAME; - c->state = COMPOSITE_STATE_ERROR; - return c->status; + composite_error(c, c->status); + return; + } + + /* issue a monitor message */ + if (s->monitor_fn) { + struct msg_rpc_lookup_name msg_lookup; + + msg_lookup.rid = s->lookupname.out.rids.ids; + msg_lookup.count = s->lookupname.out.rids.count; + + msg.type = mon_SamrLookupName; + msg.data = (void*)&msg_lookup; + msg.data_size = sizeof(msg_lookup); + s->monitor_fn(&msg); } /* prepare the next rpc call */ @@ -550,14 +530,10 @@ static NTSTATUS usermod_lookup(struct composite_context *c, s->openuser.out.user_handle = &s->user_handle; /* send the rpc request */ - s->req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser); + openuser_req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser); + if (composite_nomem(openuser_req, c)) return; - /* callback handler setup */ - s->req->async.callback = usermod_handler; - s->req->async.private_data = c; - s->stage = USERMOD_OPEN; - - return NT_STATUS_OK; + composite_continue_rpc(c, openuser_req, continue_usermod_user_opened, c); } @@ -567,8 +543,8 @@ static NTSTATUS usermod_lookup(struct composite_context *c, * function are made until there's no flags set meaning that all of the * changes have been made. */ -static uint32_t usermod_setfields(struct usermod_state *s, uint16_t *level, - union samr_UserInfo *i) +static bool usermod_setfields(struct usermod_state *s, uint16_t *level, + union samr_UserInfo *i, bool queried) { if (s->change.fields == 0) return s->change.fields; @@ -602,15 +578,14 @@ static uint32_t usermod_setfields(struct usermod_state *s, uint16_t *level, (*level == 0 || *level == 2)) { *level = 2; - if (s->stage == USERMOD_QUERY) { + if (queried) { /* the user info is obtained, so now set the required field */ i->info2.comment.string = s->change.comment; s->change.fields ^= USERMOD_FIELD_COMMENT; } else { /* we need to query the user info before setting one field in it */ - s->stage = USERMOD_QUERY; - return s->change.fields; + return false; } } @@ -634,12 +609,11 @@ static uint32_t usermod_setfields(struct usermod_state *s, uint16_t *level, (*level == 0 || *level == 10)) { *level = 10; - if (s->stage == USERMOD_QUERY) { + if (queried) { i->info10.home_directory.string = s->change.home_directory; s->change.fields ^= USERMOD_FIELD_HOME_DIRECTORY; } else { - s->stage = USERMOD_QUERY; - return s->change.fields; + return false; } } @@ -647,12 +621,11 @@ static uint32_t usermod_setfields(struct usermod_state *s, uint16_t *level, (*level == 0 || *level == 10)) { *level = 10; - if (s->stage == USERMOD_QUERY) { + if (queried) { i->info10.home_drive.string = s->change.home_drive; s->change.fields ^= USERMOD_FIELD_HOME_DRIVE; } else { - s->stage = USERMOD_QUERY; - return s->change.fields; + return false; } } @@ -673,19 +646,15 @@ static uint32_t usermod_setfields(struct usermod_state *s, uint16_t *level, } /* We're going to be here back again soon unless all fields have been set */ - if (s->change.fields) { - s->stage = USERMOD_OPEN; - } else { - s->stage = USERMOD_MODIFY; - } - - return s->change.fields; + return true; } static NTSTATUS usermod_change(struct composite_context *c, struct usermod_state *s) { + struct rpc_request *query_req, *setuser_req; + bool do_set; union samr_UserInfo *i = &s->info; /* set the level to invalid value, so that unless setfields routine @@ -693,12 +662,11 @@ static NTSTATUS usermod_change(struct composite_context *c, uint16_t level = 27; /* prepare UserInfo level and data based on bitmask field */ - s->change.fields = usermod_setfields(s, &level, i); + do_set = usermod_setfields(s, &level, i, false); if (level < 1 || level > 26) { /* apparently there's a field that the setfields routine does not know how to set */ - c->state = COMPOSITE_STATE_ERROR; return NT_STATUS_INVALID_PARAMETER; } @@ -707,13 +675,14 @@ static NTSTATUS usermod_change(struct composite_context *c, first, right before changing the data. Otherwise we could set required fields and accidentally reset the others. */ - if (s->stage == USERMOD_QUERY) { + if (!do_set) { s->queryuser.in.user_handle = &s->user_handle; s->queryuser.in.level = level; /* send query user info request to retrieve complete data of a particular info level */ - s->req = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &s->queryuser); + query_req = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &s->queryuser); + composite_continue_rpc(c, query_req, continue_usermod_user_queried, c); } else { s->setuser.in.user_handle = &s->user_handle; @@ -721,13 +690,10 @@ static NTSTATUS usermod_change(struct composite_context *c, s->setuser.in.info = i; /* send set user info request after making required change */ - s->req = dcerpc_samr_SetUserInfo_send(s->pipe, c, &s->setuser); + setuser_req = dcerpc_samr_SetUserInfo_send(s->pipe, c, &s->setuser); + composite_continue_rpc(c, setuser_req, continue_usermod_user_changed, c); } - - /* callback handler setup */ - s->req->async.callback = usermod_handler; - s->req->async.private_data = c; - + return NT_STATUS_OK; } @@ -735,34 +701,58 @@ static NTSTATUS usermod_change(struct composite_context *c, /** * Stage 2: Open user account */ -static NTSTATUS usermod_open(struct composite_context *c, - struct usermod_state *s) +static void continue_usermod_user_opened(struct rpc_request *req) { - c->status = dcerpc_ndr_request_recv(s->req); - NT_STATUS_NOT_OK_RETURN(c->status); - - return usermod_change(c, s); + struct composite_context *c; + struct usermod_state *s; + + c = talloc_get_type(req->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct usermod_state); + + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + + c->status = s->openuser.out.result; + if (!NT_STATUS_IS_OK(c->status)) { + composite_error(c, c->status); + return; + } + + c->status = usermod_change(c, s); } /** * Stage 2a (optional): Query the user information */ -static NTSTATUS usermod_query(struct composite_context *c, - struct usermod_state *s) +static void continue_usermod_user_queried(struct rpc_request *req) { - union samr_UserInfo *i = &s->info; + struct composite_context *c; + struct usermod_state *s; + union samr_UserInfo *i; uint16_t level; + struct rpc_request *setuser_req; + + c = talloc_get_type(req->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct usermod_state); + + i = &s->info; /* receive samr_QueryUserInfo result */ - c->status = dcerpc_ndr_request_recv(s->req); - NT_STATUS_NOT_OK_RETURN(c->status); + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + + c->status = s->queryuser.out.result; + if (!NT_STATUS_IS_OK(c->status)) { + composite_error(c, c->status); + return; + } /* get returned user data and make a change (potentially one of many) */ s->info = *s->queryuser.out.info; - s->change.fields = usermod_setfields(s, &level, i); + usermod_setfields(s, &level, i, true); /* prepare rpc call arguments */ s->setuser.in.user_handle = &s->user_handle; @@ -770,127 +760,40 @@ static NTSTATUS usermod_query(struct composite_context *c, s->setuser.in.info = i; /* send the rpc request */ - s->req = dcerpc_samr_SetUserInfo_send(s->pipe, c, &s->setuser); - - /* callback handler setup */ - s->req->async.callback = usermod_handler; - s->req->async.private_data = c; - - return NT_STATUS_OK; + setuser_req = dcerpc_samr_SetUserInfo_send(s->pipe, c, &s->setuser); + composite_continue_rpc(c, setuser_req, continue_usermod_user_changed, c); } /** * Stage 3: Set new user account data */ -static NTSTATUS usermod_modify(struct composite_context *c, - struct usermod_state *s) -{ - /* receive samr_SetUserInfo result */ - c->status = dcerpc_ndr_request_recv(s->req); - NT_STATUS_NOT_OK_RETURN(c->status); - - /* return the actual function call status */ - c->status = s->setuser.out.result; - - if (s->change.fields == 0) { - /* all fields have been set - we're done */ - c->state = COMPOSITE_STATE_DONE; - } else { - /* something's still not changed - repeat the procedure */ - return usermod_change(c, s); - } - - return c->status; -} - - -/** - * Event handler for asynchronous request. Handles transition through - * intermediate stages of the call. - * - * @param req rpc call context - */ - -static void usermod_handler(struct rpc_request *req) +static void continue_usermod_user_changed(struct rpc_request *req) { struct composite_context *c; struct usermod_state *s; - struct monitor_msg msg; - struct msg_rpc_lookup_name *msg_lookup; - struct msg_rpc_open_user *msg_open; - + c = talloc_get_type(req->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct usermod_state); - switch (s->stage) { - case USERMOD_LOOKUP: - c->status = usermod_lookup(c, s); - - if (NT_STATUS_IS_OK(c->status)) { - /* monitor message */ - msg.type = mon_SamrLookupName; - msg_lookup = talloc(s, struct msg_rpc_lookup_name); - - msg_lookup->rid = s->lookupname.out.rids.ids; - msg_lookup->count = s->lookupname.out.rids.count; - msg.data = (void*)msg_lookup; - msg.data_size = sizeof(*msg_lookup); - } - break; - - case USERMOD_OPEN: - c->status = usermod_open(c, s); - - if (NT_STATUS_IS_OK(c->status)) { - /* monitor message */ - msg.type = mon_SamrOpenUser; - msg_open = talloc(s, struct msg_rpc_open_user); - - msg_open->rid = s->openuser.in.rid; - msg_open->access_mask = s->openuser.in.rid; - msg.data = (void*)msg_open; - msg.data_size = sizeof(*msg_open); - } - break; - - case USERMOD_QUERY: - c->status = usermod_query(c, s); - - if (NT_STATUS_IS_OK(c->status)) { - /* monitor message */ - msg.type = mon_SamrQueryUser; - msg.data = NULL; - msg.data_size = 0; - } - break; - - case USERMOD_MODIFY: - c->status = usermod_modify(c, s); - - if (NT_STATUS_IS_OK(c->status)) { - /* monitor message */ - msg.type = mon_SamrSetUser; - msg.data = NULL; - msg.data_size = 0; - } - break; - } + /* receive samr_SetUserInfo result */ + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; - /* are we ok, so far ? */ + /* return the actual function call status */ + c->status = s->setuser.out.result; if (!NT_STATUS_IS_OK(c->status)) { - c->state = COMPOSITE_STATE_ERROR; + composite_error(c, c->status); + return; } - /* call monitor function provided the pointer has been passed */ - if (s->monitor_fn) { - s->monitor_fn(&msg); - } + if (s->change.fields == 0) { + /* all fields have been set - we're done */ + composite_done(c); - /* are we done yet ? */ - if (c->state >= COMPOSITE_STATE_DONE && - c->async.fn) { - c->async.fn(c); + } else { + /* something's still not changed - repeat the procedure */ + c->status = usermod_change(c, s); } } @@ -909,17 +812,15 @@ struct composite_context *libnet_rpc_usermod_send(struct dcerpc_pipe *p, { struct composite_context *c; struct usermod_state *s; + struct rpc_request *lookup_req; /* composite context allocation and setup */ - c = talloc_zero(p, struct composite_context); + c = composite_create(p, dcerpc_event_context(p)); if (c == NULL) return NULL; - s = talloc_zero(c, struct usermod_state); if (composite_nomem(s, c)) return c; - c->state = COMPOSITE_STATE_IN_PROGRESS; c->private_data = s; - c->event_ctx = dcerpc_event_context(p); /* store parameters in the call structure */ s->pipe = p; @@ -934,13 +835,11 @@ struct composite_context *libnet_rpc_usermod_send(struct dcerpc_pipe *p, s->lookupname.in.names->string = io->in.username; /* send the rpc request */ - s->req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname); + lookup_req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname); + if (composite_nomem(lookup_req, c)) return c; /* callback handler setup */ - s->req->async.callback = usermod_handler; - s->req->async.private_data = c; - s->stage = USERMOD_LOOKUP; - + composite_continue_rpc(c, lookup_req, continue_usermod_name_found, c); return c; } diff --git a/source4/libnet/userman.h b/source4/libnet/userman.h index b6302fe4ad..b681c25a16 100644 --- a/source4/libnet/userman.h +++ b/source4/libnet/userman.h @@ -17,6 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "librpc/gen_ndr/misc.h" + /* * IO structures for userman.c functions |