diff options
author | Rafal Szczesniak <mimir@samba.org> | 2006-08-27 20:37:23 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:16:48 -0500 |
commit | 1e46d3a46a2556eb3c8704d344f51a013059ba97 (patch) | |
tree | 0a1d4c08c6f36e454557d7c1cff418a94db48ff9 | |
parent | 1bdf6692092f84aa28fc237a89c14d836b2cde87 (diff) | |
download | samba-1e46d3a46a2556eb3c8704d344f51a013059ba97.tar.gz samba-1e46d3a46a2556eb3c8704d344f51a013059ba97.tar.bz2 samba-1e46d3a46a2556eb3c8704d344f51a013059ba97.zip |
r17856: The two new functions - libnet_LookupName and libnet_UserInfo.
These two perform name resolving in SAM database and fetching
user account information, respectively. The code is quite rough
yet, but it builds and basic tests work. Now, I'm working on
cleaning it up...
rafal
(This used to be commit 4a932255a01d9f1ac91feb9e371494933f1ae74e)
-rw-r--r-- | source4/libnet/libnet_domain.c | 1 | ||||
-rw-r--r-- | source4/libnet/libnet_lookup.c | 215 | ||||
-rw-r--r-- | source4/libnet/libnet_lookup.h | 16 | ||||
-rw-r--r-- | source4/libnet/libnet_user.c | 157 | ||||
-rw-r--r-- | source4/libnet/libnet_user.h | 27 |
5 files changed, 416 insertions, 0 deletions
diff --git a/source4/libnet/libnet_domain.c b/source4/libnet/libnet_domain.c index ca9ed85227..9462cbe93d 100644 --- a/source4/libnet/libnet_domain.c +++ b/source4/libnet/libnet_domain.c @@ -645,6 +645,7 @@ NTSTATUS libnet_DomainCloseLsa_recv(struct composite_context *c, struct libnet_c if (NT_STATUS_IS_OK(status) && io) { ctx->lsa.name = NULL; ZERO_STRUCT(ctx->lsa.handle); + io->out.error_string = talloc_asprintf(mem_ctx, "Success"); } else if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/libnet/libnet_lookup.c b/source4/libnet/libnet_lookup.c index be669ca2e2..c12606977c 100644 --- a/source4/libnet/libnet_lookup.c +++ b/source4/libnet/libnet_lookup.c @@ -26,10 +26,14 @@ #include "lib/events/events.h" #include "libnet/libnet.h" #include "libcli/composite/composite.h" +#include "auth/credentials/credentials.h" #include "lib/messaging/messaging.h" #include "lib/messaging/irpc.h" #include "libcli/resolve/resolve.h" #include "libcli/finddcs.h" +#include "libcli/security/security.h" +#include "librpc/gen_ndr/lsa.h" +#include "librpc/gen_ndr/ndr_lsa_c.h" struct lookup_state { struct nbt_name hostname; @@ -222,6 +226,46 @@ NTSTATUS libnet_LookupDCs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, return status; } + +static struct composite_context* lsa_policy_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*), + void (*monitor)(struct monitor_msg*)) +{ + struct composite_context *domopen_req; + + if (domain_name == NULL) { + if (policy_handle_empty(&ctx->lsa.handle)) { + domain_open->in.type = DOMAIN_LSA; + domain_open->in.domain_name = cli_credentials_get_domain(ctx->cred); + domain_open->in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + + } else { + composite_error(parent_ctx, NT_STATUS_INVALID_PARAMETER); + return parent_ctx; + } + } else { + if (policy_handle_empty(&ctx->lsa.handle) || + !strequal(domain_name, ctx->lsa.name)) { + domain_open->in.type = DOMAIN_LSA; + domain_open->in.domain_name = domain_name; + domain_open->in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + + } else { + return NULL; + } + } + + domopen_req = libnet_DomainOpen_send(ctx, domain_open, monitor); + if (composite_nomem(domopen_req, parent_ctx)) return parent_ctx; + + composite_continue(parent_ctx, domopen_req, continue_fn, parent_ctx); + return parent_ctx; +} + + /** * Synchronous version of LookupDCs */ @@ -231,3 +275,174 @@ NTSTATUS libnet_LookupDCs(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct composite_context *c = libnet_LookupDCs_send(ctx, mem_ctx, io); return libnet_LookupDCs_recv(c, mem_ctx, io); } + + +struct lookup_name_state { + struct libnet_context *ctx; + const char *name; + uint32_t count; + struct libnet_DomainOpen domopen; + struct lsa_LookupNames lookup; + struct lsa_TransSidArray sids; + struct lsa_String *names; + + /* information about the progress */ + void (*monitor_fn)(struct monitor_msg *); +}; + + +static bool prepare_lookup_params(struct libnet_context *ctx, + struct composite_context *c, + struct lookup_name_state *s); +static void continue_lookup_name(struct composite_context *ctx); +static void continue_name_found(struct rpc_request *req); + + +struct composite_context* libnet_LookupName_send(struct libnet_context *ctx, + TALLOC_CTX *mem_ctx, + struct libnet_LookupName *io, + void (*monitor)(struct monitor_msg*)) +{ + struct composite_context *c; + struct lookup_name_state *s; + struct composite_context *prereq_ctx; + struct rpc_request *lookup_req; + + c = composite_create(mem_ctx, ctx->event_ctx); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct lookup_name_state); + if (composite_nomem(s, c)) return c; + + c->private_data = s; + + s->name = talloc_strdup(c, io->in.name); + s->monitor_fn = monitor; + s->ctx = ctx; + + prereq_ctx = lsa_policy_opened(ctx, io->in.domain_name, c, &s->domopen, + continue_lookup_name, monitor); + if (prereq_ctx) return prereq_ctx; + + if (!prepare_lookup_params(ctx, c, s)) return c; + + lookup_req = dcerpc_lsa_LookupNames_send(ctx->lsa.pipe, c, &s->lookup); + if (composite_nomem(lookup_req, c)) return c; + + composite_continue_rpc(c, lookup_req, continue_name_found, c); + return c; +} + + +static bool prepare_lookup_params(struct libnet_context *ctx, + struct composite_context *c, + struct lookup_name_state *s) +{ + const int single_name = 1; + + s->sids.count = 0; + s->sids.sids = NULL; + + s->names = talloc_array(ctx, struct lsa_String, single_name); + if (composite_nomem(s->names, c)) return false; + s->names[0].string = s->name; + + s->lookup.in.handle = &ctx->lsa.handle; + s->lookup.in.num_names = single_name; + s->lookup.in.names = s->names; + s->lookup.in.sids = &s->sids; + s->lookup.in.level = 1; + s->lookup.in.count = &s->count; + s->lookup.out.count = &s->count; + s->lookup.out.sids = &s->sids; + + return true; +} + + +static void continue_lookup_name(struct composite_context *ctx) +{ + struct composite_context *c; + struct lookup_name_state *s; + struct rpc_request *lookup_req; + + c = talloc_get_type(ctx->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct lookup_name_state); + + c->status = libnet_DomainOpen_recv(ctx, s->ctx, c, &s->domopen); + if (!composite_is_ok(c)) return; + + if (!prepare_lookup_params(s->ctx, c, s)) return; + + lookup_req = dcerpc_lsa_LookupNames_send(s->ctx->lsa.pipe, c, &s->lookup); + if (composite_nomem(lookup_req, c)) return; + + composite_continue_rpc(c, lookup_req, continue_name_found, c); +} + + +static void continue_name_found(struct rpc_request *req) +{ + struct composite_context *c; + struct lookup_name_state *s; + + c = talloc_get_type(req->async.private, struct composite_context); + s = talloc_get_type(c->private_data, struct lookup_name_state); + + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + + composite_done(c); +} + + +NTSTATUS libnet_LookupName_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, + struct libnet_LookupName *io) +{ + NTSTATUS status; + struct lookup_name_state *s; + + status = composite_wait(c); + + if (NT_STATUS_IS_OK(status)) { + s = talloc_get_type(c->private_data, struct lookup_name_state); + + ZERO_STRUCT(io->out.domain_sid); + io->out.rid = 0; + io->out.sidstr = NULL; + + if (*s->lookup.out.count > 0) { + int num_auths; + struct lsa_RefDomainList *domains = s->lookup.out.domains; + struct lsa_TransSidArray *sids = s->lookup.out.sids; + + /* TODO: verify if returned pointers are non-null */ + + io->out.domain_sid = *domains->domains[0].sid; + io->out.rid = sids->sids[0].rid; + io->out.sid_type = sids->sids[0].sid_type; + + num_auths = io->out.domain_sid.num_auths++; + io->out.domain_sid.sub_auths[num_auths] = io->out.rid; + + io->out.sidstr = dom_sid_string(mem_ctx, &io->out.domain_sid); + } + + io->out.error_string = talloc_strdup(mem_ctx, "Success"); + + } else if (!NT_STATUS_IS_OK(status)) { + io->out.error_string = talloc_asprintf(mem_ctx, "Error: %s", nt_errstr(status)); + } + + return status; +} + + +NTSTATUS libnet_LookupName(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, + struct libnet_LookupName *io) +{ + struct composite_context *c; + + c = libnet_LookupName_send(ctx, mem_ctx, io, NULL); + return libnet_LookupName_recv(c, mem_ctx, io); +} diff --git a/source4/libnet/libnet_lookup.h b/source4/libnet/libnet_lookup.h index ca2c506159..52af03bf27 100644 --- a/source4/libnet/libnet_lookup.h +++ b/source4/libnet/libnet_lookup.h @@ -30,6 +30,7 @@ struct libnet_Lookup { } out; }; + struct libnet_LookupDCs { struct { const char *domain_name; @@ -40,3 +41,18 @@ struct libnet_LookupDCs { struct nbt_dc_name *dcs; } out; }; + + +struct libnet_LookupName { + struct { + const char *name; + const char *domain_name; + } in; + struct { + struct dom_sid domain_sid; + int rid; + enum lsa_SidType sid_type; + const char *sidstr; + const char *error_string; + } out; +}; diff --git a/source4/libnet/libnet_user.c b/source4/libnet/libnet_user.c index 0bf324e19b..bbc553973a 100644 --- a/source4/libnet/libnet_user.c +++ b/source4/libnet/libnet_user.c @@ -613,3 +613,160 @@ NTSTATUS libnet_ModifyUser(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, c = libnet_ModifyUser_send(ctx, mem_ctx, r, NULL); return libnet_ModifyUser_recv(c, mem_ctx, r); } + + +struct user_info_state { + struct libnet_context *ctx; + const char *domain_name; + struct libnet_LookupName lookup; + struct libnet_DomainOpen domopen; + struct libnet_rpc_userinfo userinfo; + + /* information about the progress */ + void (*monitor_fn)(struct monitor_msg *); +}; + + +static void continue_name_found(struct composite_context *ctx); +static void continue_domain_opened(struct composite_context *ctx); +static void continue_info_received(struct composite_context *ctx); + + +struct composite_context* libnet_UserInfo_send(struct libnet_context *ctx, + TALLOC_CTX *mem_ctx, + struct libnet_UserInfo *r, + void (*monitor)(struct monitor_msg*)) +{ + struct composite_context *c; + struct user_info_state *s; + struct composite_context *lookup_req; + + c = composite_create(mem_ctx, ctx->event_ctx); + if (c == NULL) return NULL; + + s = talloc_zero(c, struct user_info_state); + if (composite_nomem(s, c)) return c; + + c->private_data = s; + + s->monitor_fn = monitor; + s->ctx = ctx; + s->domain_name = talloc_strdup(c, r->in.domain_name); + + s->lookup.in.domain_name = s->domain_name; + s->lookup.in.name = talloc_strdup(c, r->in.user_name); + + lookup_req = libnet_LookupName_send(ctx, c, &s->lookup, s->monitor_fn); + if (composite_nomem(lookup_req, c)) return c; + + composite_continue(c, lookup_req, continue_name_found, c); + return c; +} + + +static void continue_name_found(struct composite_context *ctx) +{ + struct composite_context *c; + struct user_info_state *s; + struct composite_context *domopen_req; + + c = talloc_get_type(ctx->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct user_info_state); + + c->status = libnet_LookupName_recv(ctx, c, &s->lookup); + if (!composite_is_ok(c)) return; + + if (s->lookup.out.sid_type != SID_NAME_USER) { + composite_error(c, NT_STATUS_NO_SUCH_USER); + return; + } + + s->domopen.in.type = DOMAIN_SAMR; + s->domopen.in.domain_name = s->domain_name; + s->domopen.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + + domopen_req = libnet_DomainOpen_send(s->ctx, &s->domopen, s->monitor_fn); + if (composite_nomem(domopen_req, c)) return; + + composite_continue(c, domopen_req, continue_domain_opened, c); +} + + +static void continue_domain_opened(struct composite_context *ctx) +{ + struct composite_context *c; + struct user_info_state *s; + struct composite_context *info_req; + + c = talloc_get_type(ctx->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct user_info_state); + + c->status = libnet_DomainOpen_recv(ctx, s->ctx, c, &s->domopen); + if (!composite_is_ok(c)) return; + + s->userinfo.in.domain_handle = s->ctx->samr.handle; + s->userinfo.in.sid = s->lookup.out.sidstr; + s->userinfo.in.level = 21; + + info_req = libnet_rpc_userinfo_send(s->ctx->samr.pipe, &s->userinfo, s->monitor_fn); + if (composite_nomem(info_req, c)) return; + + composite_continue(c, info_req, continue_info_received, c); +} + + +static void continue_info_received(struct composite_context *ctx) +{ + struct composite_context *c; + struct user_info_state *s; + + c = talloc_get_type(ctx->async.private_data, struct composite_context); + s = talloc_get_type(c->private_data, struct user_info_state); + + c->status = libnet_rpc_userinfo_recv(ctx, c, &s->userinfo); + if (!composite_is_ok(c)) return; + + composite_done(c); +} + + +NTSTATUS libnet_UserInfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, + struct libnet_UserInfo *r) +{ + NTSTATUS status; + struct user_info_state *s; + + status = composite_wait(c); + + if (NT_STATUS_IS_OK(status) && r != NULL) { + struct samr_UserInfo21 *info; + + s = talloc_get_type(c->private_data, struct user_info_state); + info = &s->userinfo.out.info.info21; + + r->out.account_name = talloc_steal(mem_ctx, info->account_name.string); + r->out.full_name = talloc_steal(mem_ctx, info->full_name.string); + r->out.description = talloc_steal(mem_ctx, info->description.string); + r->out.home_directory = talloc_steal(mem_ctx, info->home_directory.string); + r->out.home_drive = talloc_steal(mem_ctx, info->home_drive.string); + r->out.comment = talloc_steal(mem_ctx, info->comment.string); + r->out.logon_script = talloc_steal(mem_ctx, info->logon_script.string); + r->out.profile_path = talloc_steal(mem_ctx, info->profile_path.string); + + r->out.error_string = talloc_strdup(mem_ctx, "Success"); + } + + talloc_free(c); + + return status; +} + + +NTSTATUS libnet_UserInfo(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, + struct libnet_UserInfo *r) +{ + struct composite_context *c; + + c = libnet_UserInfo_send(ctx, mem_ctx, r, NULL); + return libnet_UserInfo_recv(c, mem_ctx, r); +} diff --git a/source4/libnet/libnet_user.h b/source4/libnet/libnet_user.h index 2bea398b65..bd2944feb6 100644 --- a/source4/libnet/libnet_user.h +++ b/source4/libnet/libnet_user.h @@ -87,3 +87,30 @@ struct libnet_ModifyUser { mod->fields |= flag; \ } \ } + + +struct libnet_UserInfo { + struct { + const char *user_name; + const char *domain_name; + } in; + struct { + const char *account_name; + const char *full_name; + const char *description; + const char *home_directory; + const char *home_drive; + const char *comment; + const char *logon_script; + const char *profile_path; + struct timeval *acct_expiry; + struct timeval *allow_password_change; + struct timeval *force_password_change; + struct timeval *last_logon; + struct timeval *last_logoff; + struct timeval *last_password_change; + uint32_t acct_flags; + + const char *error_string; + } out; +}; |