static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct security_token *token, struct ldb_context *ldb) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); const struct dom_sid *domain_sid = samdb_domain_sid(ldb); struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS); struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS); struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS); struct dom_sid *dag_sid; struct ldb_dn *nc_root; int ret; ret = dsdb_find_nc_root(ldb, tmp_ctx, dn, &nc_root); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return NULL; } if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) { if (security_token_has_sid(token, sa_sid)) { dag_sid = dom_sid_dup(mem_ctx, sa_sid); } else if (security_token_has_sid(token, ea_sid)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else if (security_token_has_sid(token, da_sid)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); } else if (security_token_is_system(token)) { dag_sid = dom_sid_dup(mem_ctx, sa_sid); } else { dag_sid = NULL; } } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) { if (security_token_has_sid(token, ea_sid)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else if (security_token_has_sid(token, da_sid)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); } else if (security_token_is_system(token)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else { dag_sid = NULL; } } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) { if (security_token_has_sid(token, da_sid)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); } else if (security_token_has_sid(token, ea_sid)) { dag_sid = dom_sid_dup(mem_ctx, ea_sid); } else if (security_token_is_system(token)) { dag_sid = dom_sid_dup(mem_ctx, da_sid); } else { dag_sid = NULL; } } else { dag_sid = NULL; } talloc_free(tmp_ctx); return dag_sid; }
/* allocate a new rpc handle */ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection_context *context, uint8_t handle_type) { struct dcesrv_handle *h; struct dom_sid *sid; sid = context->conn->auth_state.session_info->security_token->user_sid; h = talloc(context->assoc_group, struct dcesrv_handle); if (!h) { return NULL; } h->data = NULL; h->sid = dom_sid_dup(h, sid); if (h->sid == NULL) { talloc_free(h); return NULL; } h->assoc_group = context->assoc_group; h->iface = context->iface; h->wire_handle.handle_type = handle_type; h->wire_handle.uuid = GUID_random(); DLIST_ADD(context->assoc_group->handles, h); talloc_set_destructor(h, dcesrv_handle_destructor); return h; }
struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, struct netr_SamInfo3 *orig) { struct netr_SamInfo3 *info3; unsigned int i; NTSTATUS status; info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); if (!info3) return NULL; status = copy_netr_SamBaseInfo(info3, &orig->base, &info3->base); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return NULL; } if (orig->sidcount) { info3->sidcount = orig->sidcount; info3->sids = talloc_array(info3, struct netr_SidAttr, orig->sidcount); RET_NOMEM(info3->sids); for (i = 0; i < orig->sidcount; i++) { info3->sids[i].sid = dom_sid_dup(info3->sids, orig->sids[i].sid); RET_NOMEM(info3->sids[i].sid); info3->sids[i].attributes = orig->sids[i].attributes; } }
NTSTATUS copy_netr_SamBaseInfo(TALLOC_CTX *mem_ctx, const struct netr_SamBaseInfo *in, struct netr_SamBaseInfo *out) { /* first copy all, then realloc pointers */ *out = *in; COPY_LSA_STRING(mem_ctx, in, out, account_name); COPY_LSA_STRING(mem_ctx, in, out, full_name); COPY_LSA_STRING(mem_ctx, in, out, logon_script); COPY_LSA_STRING(mem_ctx, in, out, profile_path); COPY_LSA_STRING(mem_ctx, in, out, home_directory); COPY_LSA_STRING(mem_ctx, in, out, home_drive); if (in->groups.count) { out->groups.rids = (struct samr_RidWithAttribute *) talloc_memdup(mem_ctx, in->groups.rids, (sizeof(struct samr_RidWithAttribute) * in->groups.count)); NT_STATUS_HAVE_NO_MEMORY(out->groups.rids); } COPY_LSA_STRING(mem_ctx, in, out, logon_server); COPY_LSA_STRING(mem_ctx, in, out, logon_domain); if (in->domain_sid) { out->domain_sid = dom_sid_dup(mem_ctx, in->domain_sid); NT_STATUS_HAVE_NO_MEMORY(out->domain_sid); } return NT_STATUS_OK; }
static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx, struct netr_SamInfo3 *info3) { const char *guest_account = lp_guestaccount(); struct dom_sid domain_sid; struct passwd *pwd; const char *tmp; pwd = Get_Pwnam_alloc(mem_ctx, guest_account); if (pwd == NULL) { DEBUG(0,("SamInfo3_for_guest: Unable to locate guest " "account [%s]!\n", guest_account)); return NT_STATUS_NO_SUCH_USER; } /* Set account name */ tmp = talloc_strdup(mem_ctx, pwd->pw_name); if (tmp == NULL) { return NT_STATUS_NO_MEMORY; } init_lsa_String(&info3->base.account_name, tmp); /* Set domain name */ tmp = talloc_strdup(mem_ctx, get_global_sam_name()); if (tmp == NULL) { return NT_STATUS_NO_MEMORY; } init_lsa_StringLarge(&info3->base.logon_domain, tmp); /* Domain sid */ sid_copy(&domain_sid, get_global_sam_sid()); info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid); if (info3->base.domain_sid == NULL) { return NT_STATUS_NO_MEMORY; } /* Guest rid */ info3->base.rid = DOMAIN_RID_GUEST; /* Primary gid */ info3->base.primary_gid = DOMAIN_RID_GUESTS; /* Set as guest */ info3->base.user_flags = NETLOGON_GUEST; TALLOC_FREE(pwd); return NT_STATUS_OK; }
/* add a rid to a domain dom_sid to make a full dom_sid. This function returns a new sid in the supplied memory context */ struct dom_sid *dom_sid_add_rid(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid, uint32_t rid) { struct dom_sid *sid; sid = dom_sid_dup(mem_ctx, domain_sid); if (!sid) return NULL; if (!sid_append_rid(sid, rid)) { talloc_free(sid); return NULL; } return sid; }
/* add to the lsa_RefDomainList for LookupSids and LookupNames */ static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, enum lsa_SidType rtype, const char *authority_name, struct dom_sid *sid, struct lsa_RefDomainList *domains, uint32_t *sid_index) { struct dom_sid *authority_sid; int i; if (rtype != SID_NAME_DOMAIN) { authority_sid = dom_sid_dup(mem_ctx, sid); if (authority_sid == NULL) { return NT_STATUS_NO_MEMORY; } authority_sid->num_auths--; } else { authority_sid = sid; } /* see if we've already done this authority name */ for (i=0; i<domains->count; i++) { if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) { *sid_index = i; return NT_STATUS_OK; } } domains->domains = talloc_realloc(domains, domains->domains, struct lsa_DomainInfo, domains->count+1); if (domains->domains == NULL) { return NT_STATUS_NO_MEMORY; } domains->domains[i].name.string = authority_name; domains->domains[i].sid = authority_sid; domains->count++; domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count; *sid_index = i; return NT_STATUS_OK; }
static NTSTATUS get_domain_info(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *bind_hdn, struct policy_handle *pol_hnd, struct dom_data *dom_data) { NTSTATUS status; struct lsa_QueryInfoPolicy2 qr; qr.in.handle = pol_hnd; qr.in.level = LSA_POLICY_INFO_DNS; status = dcerpc_lsa_QueryInfoPolicy2_r(bind_hdn, mem_ctx, &qr); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dcerpc_lsa_QueryInfoPolicy2_r failed " "with error [%s].\n", nt_errstr(status))); return status; } if (!NT_STATUS_IS_OK(qr.out.result)) { DEBUG(0, ("QueryInfoPolicy2 returned [%s].\n", nt_errstr(qr.out.result))); return qr.out.result; } dom_data->domain_name = talloc_strdup(mem_ctx, (*qr.out.info)->dns.name.string); dom_data->dns_domain_name = talloc_strdup(mem_ctx, (*qr.out.info)->dns.dns_domain.string); dom_data->domsid = dom_sid_dup(mem_ctx, (*qr.out.info)->dns.sid); if (dom_data->domain_name == NULL || dom_data->dns_domain_name == NULL || dom_data->domsid == NULL) { DEBUG(0, ("Copying domain data failed.\n")); return NT_STATUS_NO_MEMORY; } DEBUG(0, ("Got the following domain info [%s][%s][%s].\n", dom_data->domain_name, dom_data->dns_domain_name, sid_string_talloc(mem_ctx, dom_data->domsid))); return NT_STATUS_OK; }
static NTSTATUS wbcsids_to_netr_SidAttrArray( const struct dom_sid *domain_sid, const struct wbcSidWithAttr *sids, size_t num_sids, TALLOC_CTX *mem_ctx, struct netr_SidAttr **_info3_sids, uint32_t *info3_num_sids) { unsigned int i, j = 0; struct netr_SidAttr *info3_sids; info3_sids = talloc_array(mem_ctx, struct netr_SidAttr, num_sids); if (info3_sids == NULL) { return NT_STATUS_NO_MEMORY; } /* a wbcDomainSid is the same as a dom_sid */ for (i = 0; i < num_sids; i++) { const struct dom_sid *sid; sid = (const struct dom_sid *)&sids[i].sid; if (dom_sid_in_domain(domain_sid, sid)) { continue; } info3_sids[j].sid = dom_sid_dup(info3_sids, sid); if (info3_sids[j].sid == NULL) { talloc_free(info3_sids); return NT_STATUS_NO_MEMORY; } info3_sids[j].attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; j++; } *info3_num_sids = j; *_info3_sids = info3_sids; return NT_STATUS_OK; }
/* Split up a SID into its domain and RID part */ NTSTATUS dom_sid_split_rid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid, struct dom_sid **domain, uint32_t *rid) { if (sid->num_auths == 0) { return NT_STATUS_INVALID_PARAMETER; } if (domain) { if (!(*domain = dom_sid_dup(mem_ctx, sid))) { return NT_STATUS_NO_MEMORY; } (*domain)->num_auths -= 1; } if (rid) { *rid = sid->sub_auths[sid->num_auths - 1]; } return NT_STATUS_OK; }
static NTSTATUS append_netr_SidAttr(TALLOC_CTX *mem_ctx, struct netr_SidAttr **sids, uint32_t *count, const struct dom_sid2 *asid, uint32_t attributes) { uint32_t t = *count; *sids = talloc_realloc(mem_ctx, *sids, struct netr_SidAttr, t + 1); if (*sids == NULL) { return NT_STATUS_NO_MEMORY; } (*sids)[t].sid = dom_sid_dup(*sids, asid); if ((*sids)[t].sid == NULL) { return NT_STATUS_NO_MEMORY; } (*sids)[t].attributes = attributes; *count = t + 1; return NT_STATUS_OK; }
struct netlogon_creds_CredentialState *netlogon_creds_copy(TALLOC_CTX *mem_ctx, struct netlogon_creds_CredentialState *creds_in) { struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); if (!creds) { return NULL; } creds->sequence = creds_in->sequence; creds->negotiate_flags = creds_in->negotiate_flags; creds->secure_channel_type = creds_in->secure_channel_type; creds->computer_name = talloc_strdup(creds, creds_in->computer_name); if (!creds->computer_name) { talloc_free(creds); return NULL; } creds->account_name = talloc_strdup(creds, creds_in->account_name); if (!creds->account_name) { talloc_free(creds); return NULL; } if (creds_in->sid) { creds->sid = dom_sid_dup(creds, creds_in->sid); if (!creds->sid) { talloc_free(creds); return NULL; } } memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key)); memcpy(creds->seed.data, creds_in->seed.data, sizeof(creds->seed.data)); memcpy(creds->client.data, creds_in->client.data, sizeof(creds->client.data)); memcpy(creds->server.data, creds_in->server.data, sizeof(creds->server.data)); return creds; }
/* Recv the SAMR details (SamrConnect and SamrOpenDomain handle) and * open an LDAP connection */ static void init_domain_recv_samr(struct composite_context *ctx) { struct init_domain_state *state = talloc_get_type(ctx->async.private_data, struct init_domain_state); state->ctx->status = wb_connect_samr_recv( ctx, state->domain, &state->domain->libnet_ctx->samr.pipe, &state->domain->libnet_ctx->samr.connect_handle, &state->domain->libnet_ctx->samr.handle); if (!composite_is_ok(state->ctx)) return; talloc_reparent(state, state->domain->libnet_ctx->samr.pipe, state->domain->samr_binding); state->domain->libnet_ctx->samr.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; state->domain->libnet_ctx->samr.name = state->domain->info->name; state->domain->libnet_ctx->samr.sid = dom_sid_dup( state->domain->libnet_ctx, state->domain->info->sid); composite_done(state->ctx); }
static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx, struct passwd *pwd, struct netr_SamInfo3 *info3) { struct dom_sid domain_sid; const char *tmp; /* Set account name */ tmp = talloc_strdup(mem_ctx, pwd->pw_name); if (tmp == NULL) { return NT_STATUS_NO_MEMORY; } init_lsa_String(&info3->base.account_name, tmp); /* Set domain name */ tmp = talloc_strdup(mem_ctx, get_global_sam_name()); if (tmp == NULL) { return NT_STATUS_NO_MEMORY; } init_lsa_StringLarge(&info3->base.domain, tmp); /* Domain sid */ sid_copy(&domain_sid, get_global_sam_sid()); info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid); if (info3->base.domain_sid == NULL) { return NT_STATUS_NO_MEMORY; } /* Admin rid */ info3->base.rid = DOMAIN_RID_ADMINISTRATOR; /* Primary gid */ info3->base.primary_gid = BUILTIN_RID_ADMINISTRATORS; return NT_STATUS_OK; }
bool torture_rpc_lsa_lookup(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p; bool ret = true; struct policy_handle *handle; struct dom_sid *dom_sid = NULL; struct dom_sid *trusted_sid = NULL; struct dom_sid *sids[NUM_SIDS]; struct dcerpc_binding_handle *b; status = torture_rpc_connection(torture, &p, &ndr_table_lsarpc); if (!NT_STATUS_IS_OK(status)) { torture_fail(torture, "unable to connect to table"); } b = p->binding_handle; if (p->binding->transport != NCACN_NP && p->binding->transport != NCALRPC) { torture_comment(torture, "torture_rpc_lsa_lookup is only available " "over NCACN_NP or NCALRPC"); return true; } ret &= open_policy(torture, b, &handle); if (!ret) return false; ret &= get_domainsid(torture, b, handle, &dom_sid); if (!ret) return false; ret &= get_downleveltrust(torture, b, handle, &trusted_sid); if (!ret) return false; torture_comment(torture, "domain sid: %s\n", dom_sid_string(torture, dom_sid)); sids[0] = dom_sid_parse_talloc(torture, "S-1-1-0"); sids[1] = dom_sid_parse_talloc(torture, "S-1-5-4"); sids[2] = dom_sid_parse_talloc(torture, "S-1-5-32"); sids[3] = dom_sid_parse_talloc(torture, "S-1-5-32-545"); sids[4] = dom_sid_dup(torture, dom_sid); sids[5] = dom_sid_add_rid(torture, dom_sid, 512); sids[6] = dom_sid_dup(torture, trusted_sid); sids[7] = dom_sid_add_rid(torture, trusted_sid, 512); ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 0, NT_STATUS_INVALID_PARAMETER, NULL); { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_WKN_GRP, SID_NAME_WKN_GRP, SID_NAME_DOMAIN, SID_NAME_ALIAS, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_DOMAIN, SID_NAME_DOM_GRP }; ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 1, NT_STATUS_OK, types); } { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_DOMAIN, SID_NAME_DOM_GRP }; ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 2, STATUS_SOME_UNMAPPED, types); } { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 3, STATUS_SOME_UNMAPPED, types); } { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 4, STATUS_SOME_UNMAPPED, types); } ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 5, NT_STATUS_NONE_MAPPED, NULL); { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 6, STATUS_SOME_UNMAPPED, types); } ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 7, NT_STATUS_INVALID_PARAMETER, NULL); ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 8, NT_STATUS_INVALID_PARAMETER, NULL); ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 9, NT_STATUS_INVALID_PARAMETER, NULL); ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 10, NT_STATUS_INVALID_PARAMETER, NULL); return ret; }
NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, struct samu *samu, const char *login_server, struct netr_SamInfo3 **_info3, struct extra_auth_info *extra) { struct netr_SamInfo3 *info3; const struct dom_sid *user_sid; const struct dom_sid *group_sid; struct dom_sid domain_sid; struct dom_sid *group_sids; uint32_t num_group_sids = 0; const char *tmp; gid_t *gids; NTSTATUS status; user_sid = pdb_get_user_sid(samu); group_sid = pdb_get_group_sid(samu); if (!user_sid || !group_sid) { DEBUG(1, ("Sam account is missing sids!\n")); return NT_STATUS_UNSUCCESSFUL; } info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); if (!info3) { return NT_STATUS_NO_MEMORY; } ZERO_STRUCT(domain_sid); status = SamInfo3_handle_sids(pdb_get_username(samu), user_sid, group_sid, info3, &domain_sid, extra); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return status; } unix_to_nt_time(&info3->base.logon_time, pdb_get_logon_time(samu)); unix_to_nt_time(&info3->base.logoff_time, get_time_t_max()); unix_to_nt_time(&info3->base.kickoff_time, get_time_t_max()); unix_to_nt_time(&info3->base.last_password_change, pdb_get_pass_last_set_time(samu)); unix_to_nt_time(&info3->base.allow_password_change, pdb_get_pass_can_change_time(samu)); unix_to_nt_time(&info3->base.force_password_change, pdb_get_pass_must_change_time(samu)); tmp = pdb_get_username(samu); if (tmp) { info3->base.account_name.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.account_name.string); } tmp = pdb_get_fullname(samu); if (tmp) { info3->base.full_name.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.full_name.string); } tmp = pdb_get_logon_script(samu); if (tmp) { info3->base.logon_script.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.logon_script.string); } tmp = pdb_get_profile_path(samu); if (tmp) { info3->base.profile_path.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.profile_path.string); } tmp = pdb_get_homedir(samu); if (tmp) { info3->base.home_directory.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.home_directory.string); } tmp = pdb_get_dir_drive(samu); if (tmp) { info3->base.home_drive.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.home_drive.string); } info3->base.logon_count = pdb_get_logon_count(samu); info3->base.bad_password_count = pdb_get_bad_password_count(samu); info3->base.logon_domain.string = talloc_strdup(info3, pdb_get_domain(samu)); RET_NOMEM(info3->base.logon_domain.string); info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); RET_NOMEM(info3->base.domain_sid); status = pdb_enum_group_memberships(mem_ctx, samu, &group_sids, &gids, &num_group_sids); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to get groups from sam account.\n")); TALLOC_FREE(info3); return status; } if (num_group_sids) { status = group_sids_to_info3(info3, group_sids, num_group_sids); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return status; } } /* We don't need sids and gids after the conversion */ TALLOC_FREE(group_sids); TALLOC_FREE(gids); num_group_sids = 0; /* FIXME: should we add other flags ? */ info3->base.user_flags = NETLOGON_EXTRA_SIDS; if (login_server) { info3->base.logon_server.string = talloc_strdup(info3, login_server); RET_NOMEM(info3->base.logon_server.string); } info3->base.acct_flags = pdb_get_acct_ctrl(samu); *_info3 = info3; return NT_STATUS_OK; }
NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx, const char *unix_username, const struct passwd *pwd, struct netr_SamInfo3 **pinfo3, struct extra_auth_info *extra) { struct netr_SamInfo3 *info3; NTSTATUS status; TALLOC_CTX *tmp_ctx; const char *domain_name = NULL; const char *user_name = NULL; struct dom_sid domain_sid; struct dom_sid user_sid; struct dom_sid group_sid; enum lsa_SidType type; uint32_t num_sids = 0; struct dom_sid *user_sids = NULL; bool is_null; bool ok; tmp_ctx = talloc_stackframe(); ok = lookup_name_smbconf(tmp_ctx, unix_username, LOOKUP_NAME_ALL, &domain_name, &user_name, &user_sid, &type); if (!ok) { status = NT_STATUS_NO_SUCH_USER; goto done; } if (type != SID_NAME_USER) { status = NT_STATUS_NO_SUCH_USER; goto done; } ok = winbind_lookup_usersids(tmp_ctx, &user_sid, &num_sids, &user_sids); /* Check if winbind is running */ if (ok) { /* * Winbind is running and the first element of the user_sids * is the primary group. */ if (num_sids > 0) { group_sid = user_sids[0]; } } else { /* * Winbind is not running, try to create the group_sid from the * passwd group id. */ /* * This can lead to a primary group of S-1-22-2-XX which * will be rejected by other Samba code. */ gid_to_sid(&group_sid, pwd->pw_gid); } /* * If we are a unix group, or a wellknown/builtin alias, * set the group_sid to the * 'Domain Users' RID of 513 which will always resolve to a * name. */ if (sid_check_is_in_unix_groups(&group_sid) || sid_check_is_in_builtin(&group_sid) || sid_check_is_in_wellknown_domain(&group_sid)) { if (sid_check_is_in_unix_users(&user_sid)) { sid_compose(&group_sid, get_global_sam_sid(), DOMAIN_RID_USERS); } else { sid_copy(&domain_sid, &user_sid); sid_split_rid(&domain_sid, NULL); sid_compose(&group_sid, &domain_sid, DOMAIN_RID_USERS); } } /* Make sure we have a valid group sid */ is_null = is_null_sid(&group_sid); if (is_null) { status = NT_STATUS_NO_SUCH_USER; goto done; } /* Construct a netr_SamInfo3 from the information we have */ info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3); if (!info3) { status = NT_STATUS_NO_MEMORY; goto done; } info3->base.account_name.string = talloc_strdup(info3, unix_username); if (info3->base.account_name.string == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } ZERO_STRUCT(domain_sid); status = SamInfo3_handle_sids(unix_username, &user_sid, &group_sid, info3, &domain_sid, extra); if (!NT_STATUS_IS_OK(status)) { goto done; } info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); if (info3->base.domain_sid == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } ok = sid_peek_check_rid(&domain_sid, &group_sid, &info3->base.primary_gid); if (!ok) { DEBUG(1, ("The primary group domain sid(%s) does not " "match the domain sid(%s) for %s(%s)\n", sid_string_dbg(&group_sid), sid_string_dbg(&domain_sid), unix_username, sid_string_dbg(&user_sid))); status = NT_STATUS_INVALID_SID; goto done; } info3->base.acct_flags = ACB_NORMAL; if (num_sids) { status = group_sids_to_info3(info3, user_sids, num_sids); if (!NT_STATUS_IS_OK(status)) { goto done; } } *pinfo3 = talloc_steal(mem_ctx, info3); status = NT_STATUS_OK; done: talloc_free(tmp_ctx); return status; }
static NTSTATUS dcerpc_lsa_lookup_sids_noalloc(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, TALLOC_CTX *domains_ctx, TALLOC_CTX *names_ctx, struct policy_handle *pol, int num_sids, const struct dom_sid *sids, char **domains, char **names, enum lsa_SidType *types, bool use_lookupsids3, NTSTATUS *presult) { NTSTATUS status = NT_STATUS_OK; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; struct lsa_SidArray sid_array; struct lsa_RefDomainList *ref_domains = NULL; struct lsa_TransNameArray lsa_names; enum lsa_LookupNamesLevel level = LSA_LOOKUP_NAMES_ALL; uint32_t count = 0; int i; ZERO_STRUCT(lsa_names); sid_array.num_sids = num_sids; sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr, num_sids); if (sid_array.sids == NULL) { return NT_STATUS_NO_MEMORY; } for (i = 0; i<num_sids; i++) { sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sids[i]); if (!sid_array.sids[i].sid) { return NT_STATUS_NO_MEMORY; } } if (use_lookupsids3) { struct lsa_TransNameArray2 lsa_names2; uint32_t n; ZERO_STRUCT(lsa_names2); status = dcerpc_lsa_LookupSids3(h, mem_ctx, &sid_array, &ref_domains, &lsa_names2, level, &count, LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES, LSA_CLIENT_REVISION_2, &result); if (!NT_STATUS_IS_OK(status)) { return status; } if(!NT_STATUS_IS_ERR(result)) { lsa_names.count = lsa_names2.count; lsa_names.names = talloc_array(mem_ctx, struct lsa_TranslatedName, lsa_names.count); if (lsa_names.names == NULL) { return NT_STATUS_NO_MEMORY; } for (n=0; n < lsa_names.count; n++) { lsa_names.names[n].sid_type = lsa_names2.names[n].sid_type; lsa_names.names[n].name = lsa_names2.names[n].name; lsa_names.names[n].sid_index = lsa_names2.names[n].sid_index; } } } else {
static int samldb_fill_foreignSecurityPrincipal_object(struct ldb_module *module, const struct ldb_message *msg, struct ldb_message **ret_msg) { struct ldb_message *msg2; const char *rdn_name; struct dom_sid *dom_sid; struct dom_sid *sid; const char *dom_attrs[] = { "name", NULL }; struct ldb_message **dom_msgs; const char *errstr; int ret; TALLOC_CTX *mem_ctx = talloc_new(msg); if (!mem_ctx) { return LDB_ERR_OPERATIONS_ERROR; } /* build the new msg */ msg2 = ldb_msg_copy(mem_ctx, msg); if (!msg2) { ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_foreignSecurityPrincpal_object: ldb_msg_copy failed!\n"); talloc_free(mem_ctx); return LDB_ERR_OPERATIONS_ERROR; } ret = samdb_copy_template(module->ldb, msg2, "(&(CN=TemplateForeignSecurityPrincipal)(objectclass=foreignSecurityPrincipalTemplate))", &errstr); if (ret != 0) { ldb_asprintf_errstring(module->ldb, "samldb_fill_foreignSecurityPrincipal_object: " "Error copying template: %s", errstr); talloc_free(mem_ctx); return ret; } rdn_name = ldb_dn_get_rdn_name(msg2->dn); if (strcasecmp(rdn_name, "cn") != 0) { ldb_asprintf_errstring(module->ldb, "Bad RDN (%s=) for ForeignSecurityPrincipal, should be CN=!", rdn_name); talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } /* Slightly different for the foreign sids. We don't want * domain SIDs ending up there, it would cause all sorts of * pain */ sid = dom_sid_parse_talloc(msg2, (const char *)ldb_dn_get_rdn_val(msg2->dn)->data); if (!sid) { ldb_set_errstring(module->ldb, "No valid found SID in ForeignSecurityPrincipal CN!"); talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } if ( ! samldb_msg_add_sid(module, msg2, "objectSid", sid)) { talloc_free(sid); return LDB_ERR_OPERATIONS_ERROR; } dom_sid = dom_sid_dup(mem_ctx, sid); if (!dom_sid) { talloc_free(mem_ctx); return LDB_ERR_OPERATIONS_ERROR; } /* get the domain component part of the provided SID */ dom_sid->num_auths--; /* find the domain DN */ ret = gendb_search(module->ldb, mem_ctx, NULL, &dom_msgs, dom_attrs, "(&(objectSid=%s)(objectclass=domain))", ldap_encode_ndr_dom_sid(mem_ctx, dom_sid)); if (ret >= 1) { /* We don't really like the idea of foreign sids that are not foreign, but it happens */ const char *name = samdb_result_string(dom_msgs[0], "name", NULL); ldb_debug(module->ldb, LDB_DEBUG_TRACE, "NOTE (strange but valid): Adding foreign SID record with SID %s, but this domian (%s) is already in the database", dom_sid_string(mem_ctx, sid), name); } else if (ret == -1) { ldb_asprintf_errstring(module->ldb, "samldb_fill_foreignSecurityPrincipal_object: error searching for a domain with this sid: %s\n", dom_sid_string(mem_ctx, dom_sid)); talloc_free(dom_msgs); return LDB_ERR_OPERATIONS_ERROR; } /* This isn't an operation on a domain we know about, so just * check for the SID, looking for duplicates via the common * code */ ret = samldb_notice_sid(module, msg2, sid); if (ret == 0) { talloc_steal(msg, msg2); *ret_msg = msg2; } return ret; }
int samldb_notice_sid(struct ldb_module *module, TALLOC_CTX *mem_ctx, const struct dom_sid *sid) { int ret; struct ldb_dn *dom_dn; struct dom_sid *dom_sid; const char *attrs[] = { NULL }; struct ldb_result *dom_res; struct ldb_result *res; uint32_t old_rid; /* find if this SID already exists */ ret = ldb_search_exp_fmt(module->ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs, "(objectSid=%s)", ldap_encode_ndr_dom_sid(mem_ctx, sid)); if (ret == LDB_SUCCESS) { if (res->count > 0) { talloc_free(res); ldb_asprintf_errstring(module->ldb, "Attempt to add record with SID %s rejected," " because this SID is already in the database", dom_sid_string(mem_ctx, sid)); /* We have a duplicate SID, we must reject the add */ return LDB_ERR_CONSTRAINT_VIOLATION; } talloc_free(res); } else { ldb_asprintf_errstring(module->ldb, "samldb_notice_sid: error searching to see if sid %s is in use: %s\n", dom_sid_string(mem_ctx, sid), ldb_errstring(module->ldb)); return ret; } dom_sid = dom_sid_dup(mem_ctx, sid); if (!dom_sid) { return LDB_ERR_OPERATIONS_ERROR; } /* get the domain component part of the provided SID */ dom_sid->num_auths--; /* find the domain DN */ ret = ldb_search_exp_fmt(module->ldb, mem_ctx, &dom_res, NULL, LDB_SCOPE_SUBTREE, attrs, "(&(objectSid=%s)(objectclass=domain))", ldap_encode_ndr_dom_sid(mem_ctx, dom_sid)); if (ret == LDB_SUCCESS) { if (dom_res->count == 0) { talloc_free(dom_res); /* This isn't an operation on a domain we know about, so nothing to update */ return LDB_SUCCESS; } if (dom_res->count > 1) { talloc_free(dom_res); ldb_asprintf_errstring(module->ldb, "samldb_notice_sid: error retrieving domain from sid: duplicate (found %d) domain: %s!\n", dom_res->count, dom_sid_string(dom_res, dom_sid)); return LDB_ERR_OPERATIONS_ERROR; } } else { ldb_asprintf_errstring(module->ldb, "samldb_notice_sid: error retrieving domain from sid: %s: %s\n", dom_sid_string(dom_res, dom_sid), ldb_errstring(module->ldb)); return ret; } dom_dn = dom_res->msgs[0]->dn; ret = samldb_find_next_rid(module, mem_ctx, dom_dn, &old_rid); if (ret) { talloc_free(dom_res); return ret; } if (old_rid <= sid->sub_auths[sid->num_auths - 1]) { ret = samldb_set_next_rid(module->ldb, mem_ctx, dom_dn, old_rid, sid->sub_auths[sid->num_auths - 1] + 1); } talloc_free(dom_res); return ret; }
static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, uint32_t format_flags, enum drsuapi_DsNameFormat format_offered, enum drsuapi_DsNameFormat format_desired, struct ldb_dn *name_dn, const char *name, const char *domain_filter, const char *result_filter, struct drsuapi_DsNameInfo1 *info1, int scope, struct ldb_dn *search_dn) { int ldb_ret; struct ldb_result *domain_res = NULL; const char * const *domain_attrs; const char * const *result_attrs; struct ldb_message **result_res = NULL; struct ldb_message *result = NULL; int i; char *p; struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); const char * const _domain_attrs_1779[] = { "ncName", "dnsRoot", NULL}; const char * const _result_attrs_null[] = { NULL }; const char * const _domain_attrs_canonical[] = { "ncName", "dnsRoot", NULL}; const char * const _result_attrs_canonical[] = { "canonicalName", NULL }; const char * const _domain_attrs_nt4[] = { "ncName", "dnsRoot", "nETBIOSName", NULL}; const char * const _result_attrs_nt4[] = { "sAMAccountName", "objectSid", "objectClass", NULL}; const char * const _domain_attrs_guid[] = { "ncName", "dnsRoot", NULL}; const char * const _result_attrs_guid[] = { "objectGUID", NULL}; const char * const _domain_attrs_display[] = { "ncName", "dnsRoot", NULL}; const char * const _result_attrs_display[] = { "displayName", "samAccountName", NULL}; const char * const _domain_attrs_none[] = { "ncName", "dnsRoot" , NULL}; const char * const _result_attrs_none[] = { NULL}; /* here we need to set the attrs lists for domain and result lookups */ switch (format_desired) { case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: domain_attrs = _domain_attrs_1779; result_attrs = _result_attrs_null; break; case DRSUAPI_DS_NAME_FORMAT_CANONICAL: domain_attrs = _domain_attrs_canonical; result_attrs = _result_attrs_canonical; break; case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: domain_attrs = _domain_attrs_nt4; result_attrs = _result_attrs_nt4; break; case DRSUAPI_DS_NAME_FORMAT_GUID: domain_attrs = _domain_attrs_guid; result_attrs = _result_attrs_guid; break; case DRSUAPI_DS_NAME_FORMAT_DISPLAY: domain_attrs = _domain_attrs_display; result_attrs = _result_attrs_display; break; default: domain_attrs = _domain_attrs_none; result_attrs = _result_attrs_none; break; } if (domain_filter) { /* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */ ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res, partitions_basedn, LDB_SCOPE_ONELEVEL, domain_attrs, "%s", domain_filter); if (ldb_ret != LDB_SUCCESS) { DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx))); info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; } switch (domain_res->count) { case 1: break; case 0: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; default: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; return WERR_OK; } info1->dns_domain_name = ldb_msg_find_attr_as_string(domain_res->msgs[0], "dnsRoot", NULL); W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name); info1->status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY; } else { info1->dns_domain_name = NULL; info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; } if (result_filter) { int ret; struct ldb_result *res; uint32_t dsdb_flags = 0; struct ldb_dn *real_search_dn = NULL; info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; /* * From 4.1.4.2.11 of MS-DRSR * if DS_NAME_FLAG_GCVERIFY in flags then * rt := select all O from all * where attrValue in GetAttrVals(O, att, false) * else * rt := select all O from subtree DefaultNC() * where attrValue in GetAttrVals(O, att, false) * endif * return rt */ if (format_flags & DRSUAPI_DS_NAME_FLAG_GCVERIFY || format_offered == DRSUAPI_DS_NAME_FORMAT_GUID) { dsdb_flags = DSDB_SEARCH_SEARCH_ALL_PARTITIONS; } else if (domain_res) { if (!search_dn) { struct ldb_dn *tmp_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL); real_search_dn = tmp_dn; } else { real_search_dn = search_dn; } } else { real_search_dn = ldb_get_default_basedn(sam_ctx); } if (format_desired == DRSUAPI_DS_NAME_FORMAT_GUID){ dsdb_flags |= DSDB_SEARCH_SHOW_RECYCLED; } /* search with the 'phantom root' flag */ ret = dsdb_search(sam_ctx, mem_ctx, &res, real_search_dn, scope, result_attrs, dsdb_flags, "%s", result_filter); if (ret != LDB_SUCCESS) { DEBUG(2, ("DsCrackNameOneFilter search from '%s' with flags 0x%08x failed: %s\n", ldb_dn_get_linearized(real_search_dn), dsdb_flags, ldb_errstring(sam_ctx))); info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; } ldb_ret = res->count; result_res = res->msgs; } else if (format_offered == DRSUAPI_DS_NAME_FORMAT_FQDN_1779) { ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res, result_attrs); } else if (domain_res) { name_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL); ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res, result_attrs); } else { /* Can't happen */ DEBUG(0, ("LOGIC ERROR: DsCrackNameOneFilter domain ref search not available: This can't happen...\n")); info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; } switch (ldb_ret) { case 1: result = result_res[0]; break; case 0: switch (format_offered) { case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: return DsCrackNameSPNAlias(sam_ctx, mem_ctx, smb_krb5_context, format_flags, format_offered, format_desired, name, info1); case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: return DsCrackNameUPN(sam_ctx, mem_ctx, smb_krb5_context, format_flags, format_offered, format_desired, name, info1); default: break; } info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; case -1: DEBUG(2, ("DsCrackNameOneFilter result search failed: %s\n", ldb_errstring(sam_ctx))); info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; default: switch (format_offered) { case DRSUAPI_DS_NAME_FORMAT_CANONICAL: case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: { const char *canonical_name = NULL; /* Not required, but we get warnings... */ /* We may need to manually filter further */ for (i = 0; i < ldb_ret; i++) { switch (format_offered) { case DRSUAPI_DS_NAME_FORMAT_CANONICAL: canonical_name = ldb_dn_canonical_string(mem_ctx, result_res[i]->dn); break; case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: canonical_name = ldb_dn_canonical_ex_string(mem_ctx, result_res[i]->dn); break; default: break; } if (strcasecmp_m(canonical_name, name) == 0) { result = result_res[i]; break; } } if (!result) { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; } } /* FALL TROUGH */ default: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; return WERR_OK; } } info1->dns_domain_name = ldb_dn_canonical_string(mem_ctx, result->dn); W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name); p = strchr(info1->dns_domain_name, '/'); if (p) { p[0] = '\0'; } /* here we can use result and domain_res[0] */ switch (format_desired) { case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: { info1->result_name = ldb_dn_alloc_linearized(mem_ctx, result->dn); W_ERROR_HAVE_NO_MEMORY(info1->result_name); info1->status = DRSUAPI_DS_NAME_STATUS_OK; return WERR_OK; } case DRSUAPI_DS_NAME_FORMAT_CANONICAL: { info1->result_name = ldb_msg_find_attr_as_string(result, "canonicalName", NULL); info1->status = DRSUAPI_DS_NAME_STATUS_OK; return WERR_OK; } case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: { /* Not in the virtual ldb attribute */ return DsCrackNameOneSyntactical(mem_ctx, DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX, result->dn, name, info1); } case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: { const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result, "objectSid"); const char *_acc = "", *_dom = ""; if (sid == NULL) { info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING; return WERR_OK; } if (samdb_find_attribute(sam_ctx, result, "objectClass", "domain")) { /* This can also find a DomainDNSZones entry, * but it won't have the SID we just * checked. */ ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res, partitions_basedn, LDB_SCOPE_ONELEVEL, domain_attrs, "(ncName=%s)", ldb_dn_get_linearized(result->dn)); if (ldb_ret != LDB_SUCCESS) { DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx))); info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; } switch (domain_res->count) { case 1: break; case 0: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; default: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; return WERR_OK; } _dom = ldb_msg_find_attr_as_string(domain_res->msgs[0], "nETBIOSName", NULL); W_ERROR_HAVE_NO_MEMORY(_dom); } else { _acc = ldb_msg_find_attr_as_string(result, "sAMAccountName", NULL); if (!_acc) { info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING; return WERR_OK; } if (dom_sid_in_domain(dom_sid_parse_talloc(mem_ctx, SID_BUILTIN), sid)) { _dom = "BUILTIN"; } else { const char *attrs[] = { NULL }; struct ldb_result *domain_res2; struct dom_sid *dom_sid = dom_sid_dup(mem_ctx, sid); if (!dom_sid) { return WERR_OK; } dom_sid->num_auths--; ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res, NULL, LDB_SCOPE_BASE, attrs, "(&(objectSid=%s)(objectClass=domain))", ldap_encode_ndr_dom_sid(mem_ctx, dom_sid)); if (ldb_ret != LDB_SUCCESS) { DEBUG(2, ("DsCrackNameOneFilter domain search failed: %s\n", ldb_errstring(sam_ctx))); info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; } switch (domain_res->count) { case 1: break; case 0: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; default: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; return WERR_OK; } ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res2, partitions_basedn, LDB_SCOPE_ONELEVEL, domain_attrs, "(ncName=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn)); if (ldb_ret != LDB_SUCCESS) { DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx))); info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; } switch (domain_res2->count) { case 1: break; case 0: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; default: info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; return WERR_OK; } _dom = ldb_msg_find_attr_as_string(domain_res2->msgs[0], "nETBIOSName", NULL); W_ERROR_HAVE_NO_MEMORY(_dom); } } info1->result_name = talloc_asprintf(mem_ctx, "%s\\%s", _dom, _acc); W_ERROR_HAVE_NO_MEMORY(info1->result_name); info1->status = DRSUAPI_DS_NAME_STATUS_OK; return WERR_OK; } case DRSUAPI_DS_NAME_FORMAT_GUID: { struct GUID guid; guid = samdb_result_guid(result, "objectGUID"); info1->result_name = GUID_string2(mem_ctx, &guid); W_ERROR_HAVE_NO_MEMORY(info1->result_name); info1->status = DRSUAPI_DS_NAME_STATUS_OK; return WERR_OK; } case DRSUAPI_DS_NAME_FORMAT_DISPLAY: { info1->result_name = ldb_msg_find_attr_as_string(result, "displayName", NULL); if (!info1->result_name) { info1->result_name = ldb_msg_find_attr_as_string(result, "sAMAccountName", NULL); } if (!info1->result_name) { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; } else { info1->status = DRSUAPI_DS_NAME_STATUS_OK; } return WERR_OK; } case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; return WERR_OK; } case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN: case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: { info1->dns_domain_name = NULL; info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; return WERR_OK; } default: info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING; return WERR_OK; } }
BOOL torture_rpc_lsa_lookup(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p; TALLOC_CTX *mem_ctx; BOOL ret = True; struct policy_handle *handle; struct dom_sid *dom_sid; struct dom_sid *trusted_sid; struct dom_sid *sids[NUM_SIDS]; mem_ctx = talloc_init("torture_rpc_lsa"); status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_lsarpc); if (!NT_STATUS_IS_OK(status)) { ret = False; goto done; } ret &= open_policy(mem_ctx, p, &handle); if (!ret) goto done; ret &= get_domainsid(mem_ctx, p, handle, &dom_sid); if (!ret) goto done; ret &= get_downleveltrust(mem_ctx, p, handle, &trusted_sid); if (!ret) goto done; printf("domain sid: %s\n", dom_sid_string(mem_ctx, dom_sid)); sids[0] = dom_sid_parse_talloc(mem_ctx, "S-1-1-0"); sids[1] = dom_sid_parse_talloc(mem_ctx, "S-1-5-4"); sids[2] = dom_sid_parse_talloc(mem_ctx, "S-1-5-32"); sids[3] = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-545"); sids[4] = dom_sid_dup(mem_ctx, dom_sid); sids[5] = dom_sid_add_rid(mem_ctx, dom_sid, 512); sids[6] = dom_sid_dup(mem_ctx, trusted_sid); sids[7] = dom_sid_add_rid(mem_ctx, trusted_sid, 512); ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 0, NT_STATUS_INVALID_PARAMETER, NULL); { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_WKN_GRP, SID_NAME_WKN_GRP, SID_NAME_DOMAIN, SID_NAME_ALIAS, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_DOMAIN, SID_NAME_DOM_GRP }; ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 1, NT_STATUS_OK, types); } { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_DOMAIN, SID_NAME_DOM_GRP }; ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 2, STATUS_SOME_UNMAPPED, types); } { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 3, STATUS_SOME_UNMAPPED, types); } { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 4, STATUS_SOME_UNMAPPED, types); } ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 5, NT_STATUS_NONE_MAPPED, NULL); { enum lsa_SidType types[NUM_SIDS] = { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN, SID_NAME_DOMAIN, SID_NAME_DOM_GRP, SID_NAME_UNKNOWN, SID_NAME_UNKNOWN }; ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 6, STATUS_SOME_UNMAPPED, types); } ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 7, NT_STATUS_INVALID_PARAMETER, NULL); ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 8, NT_STATUS_INVALID_PARAMETER, NULL); ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 9, NT_STATUS_INVALID_PARAMETER, NULL); ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 10, NT_STATUS_INVALID_PARAMETER, NULL); done: talloc_free(mem_ctx); return ret; }
NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, struct samu *samu, const char *login_server, struct netr_SamInfo3 **_info3, struct extra_auth_info *extra) { struct netr_SamInfo3 *info3; const struct dom_sid *user_sid; const struct dom_sid *group_sid; struct dom_sid domain_sid; struct dom_sid *group_sids; uint32_t num_group_sids = 0; const char *tmp; gid_t *gids; NTSTATUS status; bool ok; user_sid = pdb_get_user_sid(samu); group_sid = pdb_get_group_sid(samu); if (!user_sid || !group_sid) { DEBUG(1, ("Sam account is missing sids!\n")); return NT_STATUS_UNSUCCESSFUL; } info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); if (!info3) { return NT_STATUS_NO_MEMORY; } ZERO_STRUCT(domain_sid); /* check if this is a "Unix Users" domain user, * we need to handle it in a special way if that's the case */ if (sid_check_is_in_unix_users(user_sid)) { /* in info3 you can only set rids for the user and the * primary group, and the domain sid must be that of * the sam domain. * * Store a completely bogus value here. * The real SID is stored in the extra sids. * Other code will know to look there if (-1) is found */ info3->base.rid = (uint32_t)(-1); sid_copy(&extra->user_sid, user_sid); DEBUG(10, ("Unix User found in struct samu. Rid marked as " "special and sid (%s) saved as extra sid\n", sid_string_dbg(user_sid))); } else { sid_copy(&domain_sid, user_sid); sid_split_rid(&domain_sid, &info3->base.rid); } if (is_null_sid(&domain_sid)) { sid_copy(&domain_sid, get_global_sam_sid()); } /* check if this is a "Unix Groups" domain group, * if so we need special handling */ if (sid_check_is_in_unix_groups(group_sid)) { /* in info3 you can only set rids for the user and the * primary group, and the domain sid must be that of * the sam domain. * * Store a completely bogus value here. * The real SID is stored in the extra sids. * Other code will know to look there if (-1) is found */ info3->base.primary_gid = (uint32_t)(-1); sid_copy(&extra->pgid_sid, group_sid); DEBUG(10, ("Unix Group found in struct samu. Rid marked as " "special and sid (%s) saved as extra sid\n", sid_string_dbg(group_sid))); } else { ok = sid_peek_check_rid(&domain_sid, group_sid, &info3->base.primary_gid); if (!ok) { DEBUG(1, ("The primary group domain sid(%s) does not " "match the domain sid(%s) for %s(%s)\n", sid_string_dbg(group_sid), sid_string_dbg(&domain_sid), pdb_get_username(samu), sid_string_dbg(user_sid))); TALLOC_FREE(info3); return NT_STATUS_UNSUCCESSFUL; } } unix_to_nt_time(&info3->base.last_logon, pdb_get_logon_time(samu)); unix_to_nt_time(&info3->base.last_logoff, get_time_t_max()); unix_to_nt_time(&info3->base.acct_expiry, get_time_t_max()); unix_to_nt_time(&info3->base.last_password_change, pdb_get_pass_last_set_time(samu)); unix_to_nt_time(&info3->base.allow_password_change, pdb_get_pass_can_change_time(samu)); unix_to_nt_time(&info3->base.force_password_change, pdb_get_pass_must_change_time(samu)); tmp = pdb_get_username(samu); if (tmp) { info3->base.account_name.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.account_name.string); } tmp = pdb_get_fullname(samu); if (tmp) { info3->base.full_name.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.full_name.string); } tmp = pdb_get_logon_script(samu); if (tmp) { info3->base.logon_script.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.logon_script.string); } tmp = pdb_get_profile_path(samu); if (tmp) { info3->base.profile_path.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.profile_path.string); } tmp = pdb_get_homedir(samu); if (tmp) { info3->base.home_directory.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.home_directory.string); } tmp = pdb_get_dir_drive(samu); if (tmp) { info3->base.home_drive.string = talloc_strdup(info3, tmp); RET_NOMEM(info3->base.home_drive.string); } info3->base.logon_count = pdb_get_logon_count(samu); info3->base.bad_password_count = pdb_get_bad_password_count(samu); info3->base.domain.string = talloc_strdup(info3, pdb_get_domain(samu)); RET_NOMEM(info3->base.domain.string); info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); RET_NOMEM(info3->base.domain_sid); status = pdb_enum_group_memberships(mem_ctx, samu, &group_sids, &gids, &num_group_sids); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to get groups from sam account.\n")); TALLOC_FREE(info3); return status; } if (num_group_sids) { status = group_sids_to_info3(info3, group_sids, num_group_sids); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return status; } } /* We don't need sids and gids after the conversion */ TALLOC_FREE(group_sids); TALLOC_FREE(gids); num_group_sids = 0; /* FIXME: should we add other flags ? */ info3->base.user_flags = NETLOGON_EXTRA_SIDS; if (login_server) { info3->base.logon_server.string = talloc_strdup(info3, login_server); RET_NOMEM(info3->base.logon_server.string); } info3->base.acct_flags = pdb_get_acct_ctrl(samu); *_info3 = info3; return NT_STATUS_OK; }
/* lookup a SID for 1 name */ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx, struct loadparm_context *lp_ctx, struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, const char *name, const char **authority_name, struct dom_sid **sid, enum lsa_SidType *rtype, uint32_t *rid) { int ret, i; uint32_t atype; struct ldb_message **res; const char * const attrs[] = { "objectSid", "sAMAccountType", NULL}; const char *p; const char *domain; const char *username; struct ldb_dn *domain_dn; struct dom_sid *domain_sid; NTSTATUS status; p = strchr_m(name, '\\'); if (p != NULL) { domain = talloc_strndup(mem_ctx, name, p-name); if (!domain) { return NT_STATUS_NO_MEMORY; } username = p + 1; } else if (strchr_m(name, '@')) { status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status))); return status; } } else { domain = NULL; username = name; } if (!domain) { /* Look up table of well known names */ status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype); if (NT_STATUS_IS_OK(status)) { dom_sid_split_rid(NULL, *sid, NULL, rid); return NT_STATUS_OK; } if (username == NULL) { *authority_name = NAME_BUILTIN; *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN); if (*sid == NULL) { return NT_STATUS_NO_MEMORY; } *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) { *authority_name = NAME_NT_AUTHORITY; *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY); if (*sid == NULL) { return NT_STATUS_NO_MEMORY; } *rtype = SID_NAME_DOMAIN; dom_sid_split_rid(NULL, *sid, NULL, rid); return NT_STATUS_OK; } if (strcasecmp_m(username, NAME_BUILTIN) == 0) { *authority_name = NAME_BUILTIN; *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN); if (*sid == NULL) { return NT_STATUS_NO_MEMORY; } *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } if (strcasecmp_m(username, state->domain_dns) == 0) { *authority_name = talloc_strdup(mem_ctx, state->domain_name); if (*authority_name == NULL) { return NT_STATUS_NO_MEMORY; } *sid = dom_sid_dup(mem_ctx, state->domain_sid); if (*sid == NULL) { return NT_STATUS_NO_MEMORY; } *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } if (strcasecmp_m(username, state->domain_name) == 0) { *authority_name = talloc_strdup(mem_ctx, state->domain_name); if (*authority_name == NULL) { return NT_STATUS_NO_MEMORY; } *sid = dom_sid_dup(mem_ctx, state->domain_sid); if (*sid == NULL) { return NT_STATUS_NO_MEMORY; } *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } /* Perhaps this is a well known user? */ name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username); if (!name) { return NT_STATUS_NO_MEMORY; } status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); if (NT_STATUS_IS_OK(status)) { return status; } /* Perhaps this is a BUILTIN user? */ name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username); if (!name) { return NT_STATUS_NO_MEMORY; } status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); if (NT_STATUS_IS_OK(status)) { return status; } /* OK, I give up - perhaps we need to assume the user is in our domain? */ name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username); if (!name) { return NT_STATUS_NO_MEMORY; } status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); if (NT_STATUS_IS_OK(status)) { return status; } return STATUS_SOME_UNMAPPED; } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) { if (!*username) { *authority_name = NAME_NT_AUTHORITY; *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY); if (*sid == NULL) { return NT_STATUS_NO_MEMORY; } *rtype = SID_NAME_DOMAIN; dom_sid_split_rid(NULL, *sid, NULL, rid); return NT_STATUS_OK; } /* Look up table of well known names */ status = lookup_well_known_names(mem_ctx, domain, username, authority_name, sid, rtype); if (NT_STATUS_IS_OK(status)) { dom_sid_split_rid(NULL, *sid, NULL, rid); } return status; } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) { *authority_name = NAME_BUILTIN; domain_dn = state->builtin_dn; } else if (strcasecmp_m(domain, state->domain_dns) == 0) { *authority_name = talloc_strdup(mem_ctx, state->domain_name); if (*authority_name == NULL) { return NT_STATUS_NO_MEMORY; } domain_dn = state->domain_dn; } else if (strcasecmp_m(domain, state->domain_name) == 0) { *authority_name = talloc_strdup(mem_ctx, state->domain_name); if (*authority_name == NULL) { return NT_STATUS_NO_MEMORY; } domain_dn = state->domain_dn; } else { /* Not local, need to ask winbind in future */ return STATUS_SOME_UNMAPPED; } ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs); if (ret != 1) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid"); if (domain_sid == NULL) { return NT_STATUS_INVALID_SID; } if (!*username) { *sid = domain_sid; *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, "(&(sAMAccountName=%s)(objectSid=*))", ldb_binary_encode_string(mem_ctx, username)); if (ret < 0) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } for (i=0; i < ret; i++) { *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid"); if (*sid == NULL) { return NT_STATUS_INVALID_SID; } /* Check that this is in the domain */ if (!dom_sid_in_domain(domain_sid, *sid)) { continue; } atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0); *rtype = ds_atype_map(atype); if (*rtype == SID_NAME_UNKNOWN) { return STATUS_SOME_UNMAPPED; } dom_sid_split_rid(NULL, *sid, NULL, rid); return NT_STATUS_OK; } /* need to check for an allocated sid */ return NT_STATUS_INVALID_SID; }
/* save the acl for a file into system.nfs4acl */ static NTSTATUS pvfs_acl_save_nfs4(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, struct security_descriptor *sd) { NTSTATUS status; void *privs; struct nfs4acl acl; int i; TALLOC_CTX *tmp_ctx; struct id_map *ids; tmp_ctx = talloc_new(pvfs); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); acl.a_version = 0; acl.a_flags = sd->type; acl.a_count = sd->dacl?sd->dacl->num_aces:0; acl.a_owner_mask = 0; acl.a_group_mask = 0; acl.a_other_mask = 0; acl.ace = talloc_array(tmp_ctx, struct nfs4ace, acl.a_count); if (!acl.ace) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } ids = talloc_array(tmp_ctx, struct id_map, acl.a_count); if (ids == NULL) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } for (i=0;i<acl.a_count;i++) { struct security_ace *ace = &sd->dacl->aces[i]; ZERO_STRUCT(ids[i].xid); ids[i].sid = dom_sid_dup(ids, &ace->trustee); if (ids[i].sid == NULL) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } ids[i].status = ID_UNKNOWN; } status = wbc_sids_to_xids(ids, acl.a_count); if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); return status; } for (i=0;i<acl.a_count;i++) { struct nfs4ace *a = &acl.ace[i]; struct security_ace *ace = &sd->dacl->aces[i]; a->e_type = ace->type; a->e_flags = ace->flags; a->e_mask = ace->access_mask; if (ids[i].xid.type != ID_TYPE_UID) { a->e_flags |= ACE4_IDENTIFIER_GROUP; } a->e_id = ids[i].xid.id; a->e_who = ""; } privs = root_privileges(); status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd, NFS4ACL_XATTR_NAME, &acl, (void *) ndr_push_nfs4acl); talloc_free(privs); talloc_free(tmp_ctx); return status; }
struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx, const struct wbcAuthUserInfo *info) { struct netr_SamInfo3 *info3; struct dom_sid user_sid; struct dom_sid group_sid; struct dom_sid domain_sid; NTSTATUS status; bool ok; memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid)); memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid)); info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); if (!info3) return NULL; unix_to_nt_time(&info3->base.logon_time, info->logon_time); unix_to_nt_time(&info3->base.logoff_time, info->logoff_time); unix_to_nt_time(&info3->base.kickoff_time, info->kickoff_time); unix_to_nt_time(&info3->base.last_password_change, info->pass_last_set_time); unix_to_nt_time(&info3->base.allow_password_change, info->pass_can_change_time); unix_to_nt_time(&info3->base.force_password_change, info->pass_must_change_time); if (info->account_name) { info3->base.account_name.string = talloc_strdup(info3, info->account_name); RET_NOMEM(info3->base.account_name.string); } if (info->full_name) { info3->base.full_name.string = talloc_strdup(info3, info->full_name); RET_NOMEM(info3->base.full_name.string); } if (info->logon_script) { info3->base.logon_script.string = talloc_strdup(info3, info->logon_script); RET_NOMEM(info3->base.logon_script.string); } if (info->profile_path) { info3->base.profile_path.string = talloc_strdup(info3, info->profile_path); RET_NOMEM(info3->base.profile_path.string); } if (info->home_directory) { info3->base.home_directory.string = talloc_strdup(info3, info->home_directory); RET_NOMEM(info3->base.home_directory.string); } if (info->home_drive) { info3->base.home_drive.string = talloc_strdup(info3, info->home_drive); RET_NOMEM(info3->base.home_drive.string); } info3->base.logon_count = info->logon_count; info3->base.bad_password_count = info->bad_password_count; sid_copy(&domain_sid, &user_sid); sid_split_rid(&domain_sid, &info3->base.rid); ok = sid_peek_check_rid(&domain_sid, &group_sid, &info3->base.primary_gid); if (!ok) { DEBUG(1, ("The primary group sid domain does not" "match user sid domain for user: %s\n", info->account_name)); TALLOC_FREE(info3); return NULL; } status = wbcsids_to_samr_RidWithAttributeArray(info3, &info3->base.groups, &domain_sid, &info->sids[1], info->num_sids - 1); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return NULL; } status = wbcsids_to_netr_SidAttrArray(&domain_sid, &info->sids[1], info->num_sids - 1, info3, &info3->sids, &info3->sidcount); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return NULL; } info3->base.user_flags = info->user_flags; memcpy(info3->base.key.key, info->user_session_key, 16); if (info->logon_server) { info3->base.logon_server.string = talloc_strdup(info3, info->logon_server); RET_NOMEM(info3->base.logon_server.string); } if (info->domain_name) { info3->base.logon_domain.string = talloc_strdup(info3, info->domain_name); RET_NOMEM(info3->base.logon_domain.string); } info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); RET_NOMEM(info3->base.domain_sid); memcpy(info3->base.LMSessKey.key, info->lm_session_key, 8); info3->base.acct_flags = info->acct_flags; return info3; }