uint32 pdb_get_group_rid (struct samu *sampass) { uint32 g_rid; if (sampass) if (sid_peek_check_rid(get_global_sam_sid(), pdb_get_group_sid(sampass),&g_rid)) return g_rid; return (0); }
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; }
static int print_sam_info (struct samu *sam_pwent, bool verbosity, bool smbpwdstyle) { uid_t uid; time_t tmp; /* TODO: check if entry is a user or a workstation */ if (!sam_pwent) return -1; if (verbosity) { char temp[44]; const uint8_t *hours; printf ("Unix username: %s\n", pdb_get_username(sam_pwent)); printf ("NT username: %s\n", pdb_get_nt_username(sam_pwent)); printf ("Account Flags: %s\n", pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent), NEW_PW_FORMAT_SPACE_PADDED_LEN)); printf ("User SID: %s\n", sid_string_tos(pdb_get_user_sid(sam_pwent))); printf ("Primary Group SID: %s\n", sid_string_tos(pdb_get_group_sid(sam_pwent))); printf ("Full Name: %s\n", pdb_get_fullname(sam_pwent)); printf ("Home Directory: %s\n", pdb_get_homedir(sam_pwent)); printf ("HomeDir Drive: %s\n", pdb_get_dir_drive(sam_pwent)); printf ("Logon Script: %s\n", pdb_get_logon_script(sam_pwent)); printf ("Profile Path: %s\n", pdb_get_profile_path(sam_pwent)); printf ("Domain: %s\n", pdb_get_domain(sam_pwent)); printf ("Account desc: %s\n", pdb_get_acct_desc(sam_pwent)); printf ("Workstations: %s\n", pdb_get_workstations(sam_pwent)); printf ("Munged dial: %s\n", pdb_get_munged_dial(sam_pwent)); tmp = pdb_get_logon_time(sam_pwent); printf ("Logon time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_logoff_time(sam_pwent); printf ("Logoff time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_kickoff_time(sam_pwent); printf ("Kickoff time: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_last_set_time(sam_pwent); printf ("Password last set: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_can_change_time(sam_pwent); printf ("Password can change: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_pass_must_change_time(sam_pwent); printf ("Password must change: %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); tmp = pdb_get_bad_password_time(sam_pwent); printf ("Last bad password : %s\n", tmp ? http_timestring(talloc_tos(), tmp) : "0"); printf ("Bad password count : %d\n", pdb_get_bad_password_count(sam_pwent)); hours = pdb_get_hours(sam_pwent); pdb_sethexhours(temp, hours); printf ("Logon hours : %s\n", temp); } else if (smbpwdstyle) { char lm_passwd[33]; char nt_passwd[33]; uid = nametouid(pdb_get_username(sam_pwent)); pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); printf("%s:%lu:%s:%s:%s:LCT-%08X:\n", pdb_get_username(sam_pwent), (unsigned long)uid, lm_passwd, nt_passwd, pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32_t)convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sam_pwent))); } else { uid = nametouid(pdb_get_username(sam_pwent)); printf ("%s:%lu:%s\n", pdb_get_username(sam_pwent), (unsigned long)uid, pdb_get_fullname(sam_pwent)); } return 0; }
NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u) { NTSTATUS status = NT_STATUS_OK; NET_USER_INFO_3 *usr_info = NULL; NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr; DOM_CRED srv_cred; UNISTR2 *uni_samlogon_user = NULL; UNISTR2 *uni_samlogon_domain = NULL; UNISTR2 *uni_samlogon_workstation = NULL; fstring nt_username, nt_domain, nt_workstation; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; extern userdom_struct current_user_info; SAM_ACCOUNT *sampw; struct auth_context *auth_context = NULL; usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3)); if (!usr_info) return NT_STATUS_NO_MEMORY; ZERO_STRUCTP(usr_info); /* store the user information, if there is any. */ r_u->user = usr_info; r_u->switch_value = 0; /* indicates no info */ r_u->auth_resp = 1; /* authoritative response */ r_u->switch_value = 3; /* indicates type of validation user info */ if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; if ( (lp_server_schannel() == True) && (!p->netsec_auth_validated) ) { /* 'server schannel = yes' should enforce use of schannel, the client did offer it in auth2, but obviously did not use it. */ return NT_STATUS_ACCESS_DENIED; } /* checks and updates credentials. creates reply credentials */ if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred))) return NT_STATUS_INVALID_HANDLE; memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); r_u->buffer_creds = 1; /* yes, we have valid server credentials */ memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds)); /* find the username */ switch (q_u->sam_id.logon_level) { case INTERACTIVE_LOGON_TYPE: uni_samlogon_user = &ctr->auth.id1.uni_user_name; uni_samlogon_domain = &ctr->auth.id1.uni_domain_name; uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name; DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup())); break; case NET_LOGON_TYPE: uni_samlogon_user = &ctr->auth.id2.uni_user_name; uni_samlogon_domain = &ctr->auth.id2.uni_domain_name; uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name; DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup())); break; default: DEBUG(2,("SAM Logon: unsupported switch value\n")); return NT_STATUS_INVALID_INFO_CLASS; } /* end switch */ rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0); rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0); rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0); DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, nt_workstation, nt_domain)); fstrcpy(current_user_info.smb_name, nt_username); sub_set_smb_name(nt_username); DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username)); status = NT_STATUS_OK; switch (ctr->switch_value) { case NET_LOGON_TYPE: { const char *wksname = nt_workstation; if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) { return status; } /* For a network logon, the workstation name comes in with two * backslashes in the front. Strip them if they are there. */ if (*wksname == '\\') wksname++; if (*wksname == '\\') wksname++; /* Standard challenge/response authenticaion */ if (!make_user_info_netlogon_network(&user_info, nt_username, nt_domain, wksname, ctr->auth.id2.lm_chal_resp.buffer, ctr->auth.id2.lm_chal_resp.str_str_len, ctr->auth.id2.nt_chal_resp.buffer, ctr->auth.id2.nt_chal_resp.str_str_len)) { status = NT_STATUS_NO_MEMORY; } break; } case INTERACTIVE_LOGON_TYPE: /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted with the session key. We will convert this to chellange/responce for the auth subsystem to chew on */ { const uint8 *chal; if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) { return status; } chal = auth_context->get_ntlm_challenge(auth_context); if (!make_user_info_netlogon_interactive(&user_info, nt_username, nt_domain, nt_workstation, chal, ctr->auth.id1.lm_owf.data, ctr->auth.id1.nt_owf.data, p->dc.sess_key)) { status = NT_STATUS_NO_MEMORY; } break; } default: DEBUG(2,("SAM Logon: unsupported switch value\n")); return NT_STATUS_INVALID_INFO_CLASS; } /* end switch */ if ( NT_STATUS_IS_OK(status) ) { status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); } (auth_context->free)(&auth_context); free_user_info(&user_info); DEBUG(5, ("_net_sam_logon: check_password returned status %s\n", nt_errstr(status))); /* Check account and password */ if (!NT_STATUS_IS_OK(status)) { free_server_info(&server_info); return status; } if (server_info->guest) { /* We don't like guest domain logons... */ DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n")); free_server_info(&server_info); return NT_STATUS_LOGON_FAILURE; } /* This is the point at which, if the login was successful, that the SAM Local Security Authority should record that the user is logged in to the domain. */ { DOM_GID *gids = NULL; const DOM_SID *user_sid = NULL; const DOM_SID *group_sid = NULL; DOM_SID domain_sid; uint32 user_rid, group_rid; int num_gids = 0; pstring my_name; fstring user_sid_string; fstring group_sid_string; uchar user_session_key[16]; uchar lm_session_key[16]; uchar netlogon_sess_key[16]; sampw = server_info->sam_account; /* set up pointer indicating user/password failed to be found */ usr_info->ptr_user_info = 0; user_sid = pdb_get_user_sid(sampw); group_sid = pdb_get_group_sid(sampw); sid_copy(&domain_sid, user_sid); sid_split_rid(&domain_sid, &user_rid); if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) { DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n", pdb_get_domain(sampw), pdb_get_username(sampw), sid_to_string(user_sid_string, user_sid), sid_to_string(group_sid_string, group_sid))); return NT_STATUS_UNSUCCESSFUL; } pstrcpy(my_name, global_myname()); if (!NT_STATUS_IS_OK(status = nt_token_to_group_list(p->mem_ctx, &domain_sid, server_info->ptok, &num_gids, &gids))) { return status; } ZERO_STRUCT(netlogon_sess_key); memcpy(netlogon_sess_key, p->dc.sess_key, 8); if (server_info->user_session_key.length) { memcpy(user_session_key, server_info->user_session_key.data, MIN(sizeof(user_session_key), server_info->user_session_key.length)); SamOEMhash(user_session_key, netlogon_sess_key, 16); } if (server_info->lm_session_key.length) { memcpy(lm_session_key, server_info->lm_session_key.data, MIN(sizeof(lm_session_key), server_info->lm_session_key.length)); SamOEMhash(lm_session_key, netlogon_sess_key, 16); } ZERO_STRUCT(netlogon_sess_key); init_net_user_info3(p->mem_ctx, usr_info, user_rid, group_rid, pdb_get_username(sampw), pdb_get_fullname(sampw), pdb_get_homedir(sampw), pdb_get_dir_drive(sampw), pdb_get_logon_script(sampw), pdb_get_profile_path(sampw), pdb_get_logon_time(sampw), get_time_t_max(), get_time_t_max(), pdb_get_pass_last_set_time(sampw), pdb_get_pass_can_change_time(sampw), pdb_get_pass_must_change_time(sampw), 0, /* logon_count */ 0, /* bad_pw_count */ num_gids, /* uint32 num_groups */ gids , /* DOM_GID *gids */ 0x20 , /* uint32 user_flgs (?) */ server_info->user_session_key.length ? user_session_key : NULL, server_info->lm_session_key.length ? lm_session_key : NULL, my_name , /* char *logon_srv */ pdb_get_domain(sampw), &domain_sid, /* DOM_SID *dom_sid */ /* Should be users domain sid, not servers - for trusted domains */ NULL); /* char *other_sids */ ZERO_STRUCT(user_session_key); ZERO_STRUCT(lm_session_key); } free_server_info(&server_info); return status; }
/******************************************************************* gets a domain user's groups ********************************************************************/ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, uint32 **prids, DOM_SID *q_sid) { SAM_ACCOUNT *sam_pass=NULL; int i, cur_rid=0; gid_t gid; gid_t *groups = NULL; int num_groups; GROUP_MAP map; DOM_SID tmp_sid; fstring user_name; fstring str_domsid, str_qsid; uint32 rid,grid; uint32 *rids=NULL, *new_rids=NULL; gid_t winbind_gid_low, winbind_gid_high; BOOL ret; BOOL winbind_groups_exist; /* * this code is far from perfect. * first it enumerates the full /etc/group and that can be slow. * second, it works only with users' SIDs * whereas the day we support nested groups, it will have to * support both users's SIDs and domain groups' SIDs * * having our own ldap backend would be so much faster ! * we're far from that, but hope one day ;-) JFM. */ *prids=NULL; *numgroups=0; winbind_groups_exist = lp_idmap_gid(&winbind_gid_low, &winbind_gid_high); DEBUG(10,("get_alias_user_groups: looking if SID %s is a member of groups in the SID domain %s\n", sid_to_string(str_qsid, q_sid), sid_to_string(str_domsid, sid))); pdb_init_sam(&sam_pass); become_root(); ret = pdb_getsampwsid(sam_pass, q_sid); unbecome_root(); if (ret == False) { pdb_free_sam(&sam_pass); return NT_STATUS_NO_SUCH_USER; } fstrcpy(user_name, pdb_get_username(sam_pass)); grid=pdb_get_group_rid(sam_pass); if (!NT_STATUS_IS_OK(sid_to_gid(pdb_get_group_sid(sam_pass), &gid))) { /* this should never happen */ DEBUG(2,("get_alias_user_groups: sid_to_gid failed!\n")); pdb_free_sam(&sam_pass); return NT_STATUS_UNSUCCESSFUL; } become_root(); /* on some systems this must run as root */ num_groups = getgroups_user(user_name, &groups); unbecome_root(); if (num_groups == -1) { /* this should never happen */ DEBUG(2,("get_alias_user_groups: getgroups_user failed\n")); pdb_free_sam(&sam_pass); return NT_STATUS_UNSUCCESSFUL; } for (i=0;i<num_groups;i++) { if (!get_group_from_gid(groups[i], &map)) { DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups[i])); continue; } /* if it's not an alias, continue */ if (map.sid_name_use != SID_NAME_ALIAS) { DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name)); continue; } sid_copy(&tmp_sid, &map.sid); sid_split_rid(&tmp_sid, &rid); /* if the sid is not in the correct domain, continue */ if (!sid_equal(&tmp_sid, sid)) { DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name)); continue; } /* Don't return winbind groups as they are not local! */ if (winbind_groups_exist && (groups[i] >= winbind_gid_low) && (groups[i] <= winbind_gid_high)) { DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name)); continue; } /* Don't return user private groups... */ if (Get_Pwnam(map.nt_name) != 0) { DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name)); continue; } new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1)); if (new_rids==NULL) { DEBUG(10,("get_alias_user_groups: could not realloc memory\n")); pdb_free_sam(&sam_pass); free(groups); return NT_STATUS_NO_MEMORY; } rids=new_rids; sid_peek_rid(&map.sid, &(rids[cur_rid])); cur_rid++; break; } if(num_groups) free(groups); /* now check for the user's gid (the primary group rid) */ for (i=0; i<cur_rid && grid!=rids[i]; i++) ; /* the user's gid is already there */ if (i!=cur_rid) { DEBUG(10,("get_alias_user_groups: user is already in the list. good.\n")); goto done; } DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)gid, user_name)); if(!get_group_from_gid(gid, &map)) { DEBUG(0,("get_alias_user_groups: gid of user %s doesn't exist. Check your " "/etc/passwd and /etc/group files\n", user_name)); goto done; } /* the primary group isn't an alias */ if (map.sid_name_use!=SID_NAME_ALIAS) { DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name)); goto done; } sid_copy(&tmp_sid, &map.sid); sid_split_rid(&tmp_sid, &rid); /* if the sid is not in the correct domain, continue */ if (!sid_equal(&tmp_sid, sid)) { DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name)); goto done; } /* Don't return winbind groups as they are not local! */ if (winbind_groups_exist && (gid >= winbind_gid_low) && (gid <= winbind_gid_high)) { DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name )); goto done; } /* Don't return user private groups... */ if (Get_Pwnam(map.nt_name) != 0) { DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name )); goto done; } new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1)); if (new_rids==NULL) { DEBUG(10,("get_alias_user_groups: could not realloc memory\n")); pdb_free_sam(&sam_pass); return NT_STATUS_NO_MEMORY; } rids=new_rids; sid_peek_rid(&map.sid, &(rids[cur_rid])); cur_rid++; done: *prids=rids; *numgroups=cur_rid; pdb_free_sam(&sam_pass); return NT_STATUS_OK; }
NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info, uint8_t pipe_session_key[16], struct netr_SamInfo3 *sam3) { struct samu *sampw; DOM_GID *gids = NULL; const DOM_SID *user_sid = NULL; const DOM_SID *group_sid = NULL; DOM_SID domain_sid; uint32 user_rid, group_rid; NTSTATUS status; int num_gids = 0; const char *my_name; struct netr_UserSessionKey user_session_key; struct netr_LMSessionKey lm_session_key; NTTIME last_logon, last_logoff, acct_expiry, last_password_change; NTTIME allow_password_change, force_password_change; struct samr_RidWithAttributeArray groups; int i; struct dom_sid2 *sid = NULL; ZERO_STRUCT(user_session_key); ZERO_STRUCT(lm_session_key); sampw = server_info->sam_account; user_sid = pdb_get_user_sid(sampw); group_sid = pdb_get_group_sid(sampw); if ((user_sid == NULL) || (group_sid == NULL)) { DEBUG(1, ("_netr_LogonSamLogon: User without group or user SID\n")); return NT_STATUS_UNSUCCESSFUL; } sid_copy(&domain_sid, user_sid); sid_split_rid(&domain_sid, &user_rid); sid = sid_dup_talloc(sam3, &domain_sid); if (!sid) { return NT_STATUS_NO_MEMORY; } if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) { DEBUG(1, ("_netr_LogonSamLogon: user %s\\%s has user sid " "%s\n but group sid %s.\n" "The conflicting domain portions are not " "supported for NETLOGON calls\n", pdb_get_domain(sampw), pdb_get_username(sampw), sid_string_dbg(user_sid), sid_string_dbg(group_sid))); return NT_STATUS_UNSUCCESSFUL; } if(server_info->login_server) { my_name = server_info->login_server; } else { my_name = global_myname(); } status = nt_token_to_group_list(sam3, &domain_sid, server_info->num_sids, server_info->sids, &num_gids, &gids); if (!NT_STATUS_IS_OK(status)) { return status; } if (server_info->user_session_key.length) { memcpy(user_session_key.key, server_info->user_session_key.data, MIN(sizeof(user_session_key.key), server_info->user_session_key.length)); SamOEMhash(user_session_key.key, pipe_session_key, 16); } if (server_info->lm_session_key.length) { memcpy(lm_session_key.key, server_info->lm_session_key.data, MIN(sizeof(lm_session_key.key), server_info->lm_session_key.length)); SamOEMhash(lm_session_key.key, pipe_session_key, 8); } groups.count = num_gids; groups.rids = TALLOC_ARRAY(sam3, struct samr_RidWithAttribute, groups.count); if (!groups.rids) { return NT_STATUS_NO_MEMORY; } for (i=0; i < groups.count; i++) { groups.rids[i].rid = gids[i].g_rid; groups.rids[i].attributes = gids[i].attr; } unix_to_nt_time(&last_logon, pdb_get_logon_time(sampw)); unix_to_nt_time(&last_logoff, get_time_t_max()); unix_to_nt_time(&acct_expiry, get_time_t_max()); unix_to_nt_time(&last_password_change, pdb_get_pass_last_set_time(sampw)); unix_to_nt_time(&allow_password_change, pdb_get_pass_can_change_time(sampw)); unix_to_nt_time(&force_password_change, pdb_get_pass_must_change_time(sampw)); init_netr_SamInfo3(sam3, last_logon, last_logoff, acct_expiry, last_password_change, allow_password_change, force_password_change, talloc_strdup(sam3, pdb_get_username(sampw)), talloc_strdup(sam3, pdb_get_fullname(sampw)), talloc_strdup(sam3, pdb_get_logon_script(sampw)), talloc_strdup(sam3, pdb_get_profile_path(sampw)), talloc_strdup(sam3, pdb_get_homedir(sampw)), talloc_strdup(sam3, pdb_get_dir_drive(sampw)), 0, /* logon_count */ 0, /* bad_password_count */ user_rid, group_rid, groups, NETLOGON_EXTRA_SIDS, user_session_key, my_name, talloc_strdup(sam3, pdb_get_domain(sampw)), sid, lm_session_key, pdb_get_acct_ctrl(sampw), 0, /* sidcount */ NULL); /* struct netr_SidAttr *sids */ ZERO_STRUCT(user_session_key); ZERO_STRUCT(lm_session_key); return NT_STATUS_OK; }
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; }