r17856: The two new functions - libnet_LookupName and libnet_UserInfo.
authorRafal Szczesniak <mimir@samba.org>
Sun, 27 Aug 2006 20:37:23 +0000 (20:37 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:16:48 +0000 (14:16 -0500)
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)

source4/libnet/libnet_domain.c
source4/libnet/libnet_lookup.c
source4/libnet/libnet_lookup.h
source4/libnet/libnet_user.c
source4/libnet/libnet_user.h

index ca9ed85227e714608dad41b398c44b6047788587..9462cbe93d42a62158665812a6c73eb473be73fc 100644 (file)
@@ -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)) {
index be669ca2e2e8e1683bd7b503e3cece27b8f0f399..c12606977cbaa996e126569d6b161c3ca55f7a96 100644 (file)
 #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);
+}
index ca2c50615917993486d2dff71dd0c9143356391f..52af03bf276ce4680d03c52621c94cdff744c9a5 100644 (file)
@@ -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;
+};
index 0bf324e19b5fff292045269b4c3e5f078ec08e7d..bbc553973a864851d7beb6d2b14c4fd07cc0f5dc 100644 (file)
@@ -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);
+}
index 2bea398b65c00e8f2370593a6e4b4813ca27bbfd..bd2944feb67a57bd5314a4aee5a68cd1680d45b8 100644 (file)
@@ -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;
+};