📄 srv_netlog_nt.c
字号:
uint32 acct_ctrl; DOM_CRED cred_out; const uchar *old_pw; if (!p->dc || !p->dc->authenticated) { return NT_STATUS_INVALID_HANDLE; } /* Step the creds chain forward. */ if (!creds_server_step(p->dc, &q_u->clnt_id.cred, &cred_out)) { DEBUG(2,("_net_srv_pwset: creds_server_step failed. Rejecting auth " "request from client %s machine account %s\n", p->dc->remote_machine, p->dc->mach_acct )); return NT_STATUS_ACCESS_DENIED; } DEBUG(5,("_net_srv_pwset: %d\n", __LINE__)); rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer, sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0); DEBUG(3,("_net_srv_pwset: Server Password Set by Wksta:[%s] on account [%s]\n", workstation, p->dc->mach_acct)); pdb_init_sam(&sampass); become_root(); ret=pdb_getsampwnam(sampass, p->dc->mach_acct); unbecome_root(); /* Ensure the account exists and is a machine account. */ acct_ctrl = pdb_get_acct_ctrl(sampass); if (!(ret && (acct_ctrl & ACB_WSTRUST || acct_ctrl & ACB_SVRTRUST || acct_ctrl & ACB_DOMTRUST))) { pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { pdb_free_sam(&sampass); return NT_STATUS_ACCOUNT_DISABLED; } /* Woah - what does this to to the credential chain ? JRA */ cred_hash3( pwd, q_u->pwd, p->dc->sess_key, 0); DEBUG(100,("Server password set : new given value was :\n")); for(i = 0; i < sizeof(pwd); i++) DEBUG(100,("%02X ", pwd[i])); DEBUG(100,("\n")); old_pw = pdb_get_nt_passwd(sampass); if (old_pw && memcmp(pwd, old_pw, 16) == 0) { /* Avoid backend modificiations and other fun if the client changed the password to the *same thing* */ ret = True; } else { /* LM password should be NULL for machines */ if (!pdb_set_lanman_passwd(sampass, NULL, PDB_CHANGED)) { pdb_free_sam(&sampass); return NT_STATUS_NO_MEMORY; } if (!pdb_set_nt_passwd(sampass, pwd, PDB_CHANGED)) { pdb_free_sam(&sampass); return NT_STATUS_NO_MEMORY; } if (!pdb_set_pass_changed_now(sampass)) { pdb_free_sam(&sampass); /* Not quite sure what this one qualifies as, but this will do */ return NT_STATUS_UNSUCCESSFUL; } become_root(); ret = pdb_update_sam_account (sampass); unbecome_root(); } if (ret) { status = NT_STATUS_OK; } /* set up the LSA Server Password Set response */ init_net_r_srv_pwset(r_u, &cred_out, status); pdb_free_sam(&sampass); return r_u->status;}/************************************************************************* _net_sam_logoff: *************************************************************************/NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u){ if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; if (!p->dc || !p->dc->authenticated) { return NT_STATUS_INVALID_HANDLE; } r_u->buffer_creds = 1; /* yes, we have valid server credentials */ /* checks and updates credentials. creates reply credentials */ if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) { DEBUG(2,("_net_sam_logoff: creds_server_step failed. Rejecting auth " "request from client %s machine account %s\n", p->dc->remote_machine, p->dc->mach_acct )); return NT_STATUS_ACCESS_DENIED; } r_u->status = NT_STATUS_OK; return r_u->status;}/******************************************************************* gets a domain user's groups from their already-calculated NT_USER_TOKEN ********************************************************************/static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, const NT_USER_TOKEN *nt_token, int *numgroups, DOM_GID **pgids) { DOM_GID *gids; int i; gids = TALLOC_ARRAY(mem_ctx, DOM_GID, nt_token->num_sids); if (!gids) { return NT_STATUS_NO_MEMORY; } *numgroups=0; for (i=PRIMARY_GROUP_SID_INDEX; i < nt_token->num_sids; i++) { if (sid_compare_domain(domain_sid, &nt_token->user_sids[i])==0) { sid_peek_rid(&nt_token->user_sids[i], &(gids[*numgroups].g_rid)); gids[*numgroups].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED); (*numgroups)++; } } *pgids = gids; return NT_STATUS_OK;}/************************************************************************* _net_sam_logon *************************************************************************/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; 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; SAM_ACCOUNT *sampw; struct auth_context *auth_context = NULL; usr_info = TALLOC_P(p->mem_ctx, 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 */ r_u->buffer_creds = 1; /* Ensure we always return server creds. */ if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; if (!p->dc || !p->dc->authenticated) { return NT_STATUS_INVALID_HANDLE; } if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) { /* 'server schannel = yes' should enforce use of schannel, the client did offer it in auth2, but obviously did not use it. */ DEBUG(0,("_net_sam_logoff: client %s not using schannel for netlogon\n", p->dc->remote_machine )); return NT_STATUS_ACCESS_DENIED; } /* checks and updates credentials. creates reply credentials */ if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) { DEBUG(2,("_net_sam_logon: creds_server_step failed. Rejecting auth " "request from client %s machine account %s\n", p->dc->remote_machine, p->dc->mach_acct )); return NT_STATUS_ACCESS_DENIED; } /* 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.param_ctrl, 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, ctr->auth.id1.param_ctrl, 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)) { /* If we don't know what this domain is, we need to indicate that we are not authoritative. This allows the client to decide if it needs to try a local user. Fix by jpjanosi@us.ibm.com, #2976 */ if ( NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER) && !strequal(nt_domain, get_global_sam_name()) && !is_trusted_domain(nt_domain) ) r_u->auth_resp = 0; /* We are not authoritative */ 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; } if(server_info->login_server) { pstrcpy(my_name, server_info->login_server); } else { 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;}/************************************************************************* _ds_enum_dom_trusts *************************************************************************/#if 0 /* JERRY -- not correct */NTSTATUS _ds_enum_dom_trusts(pipes_struct *p, DS_Q_ENUM_DOM_TRUSTS *q_u, DS_R_ENUM_DOM_TRUSTS *r_u){ NTSTATUS status = NT_STATUS_OK; /* TODO: According to MSDN, the can only be executed against a DC or domain member running Windows 2000 or later. Need to test against a standalone 2k server and see what it does. A windows 2000 DC includes its own domain in the list. --jerry */ return status;}#endif /* JERRY */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -