static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) { NTSTATUS nt_status; uint8 lm_pw[16], nt_pw[16]; nt_lm_owf_gen (opt_password, nt_pw, lm_pw); nt_status = ntlm_password_check(ntlmssp_state->mem_ctx, &ntlmssp_state->chal, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, NULL, NULL, ntlmssp_state->user, ntlmssp_state->user, ntlmssp_state->domain, lm_pw, nt_pw, user_session_key, lm_session_key); if (NT_STATUS_IS_OK(nt_status)) { ntlmssp_state->auth_context = talloc_asprintf(ntlmssp_state->mem_ctx, "%s%c%s", ntlmssp_state->domain, *lp_winbind_separator(), ntlmssp_state->user); } else { DEBUG(3, ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n", ntlmssp_state->domain, ntlmssp_state->user, ntlmssp_state->workstation, nt_errstr(nt_status))); ntlmssp_state->auth_context = NULL; } return nt_status; }
/**************************************************************************** makes lm and nt hashed passwords ****************************************************************************/ void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr) { pwd_init(pwd); nt_lm_owf_gen(clr, pwd->smb_nt_pwd, pwd->smb_lm_pwd); pwd->null_pwd = False; pwd->cleartext = False; pwd->crypted = False; pwd_obfuscate(pwd); }
/**************************************************************************** makes lm and nt hashed passwords ****************************************************************************/ void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr) { pstring dos_passwd; pwd_init(pwd); pstrcpy(dos_passwd, clr); unix_to_dos(dos_passwd, True); nt_lm_owf_gen(dos_passwd, pwd->smb_nt_pwd, pwd->smb_lm_pwd); pwd->null_pwd = False; pwd->cleartext = False; pwd->crypted = False; }
/*********************************************************** Code to check the OEM hashed password. this function ignores the 516 byte nt OEM hashed password but does use the lm OEM password to check the nt hashed-hash. ************************************************************/ BOOL check_oem_password(char *user, uchar *lmdata, uchar *lmhash, uchar *ntdata, uchar *nthash, struct smb_passwd **psmbpw, char *new_passwd, int new_passwd_size) { static uchar null_pw[16]; static uchar null_ntpw[16]; struct smb_passwd *smbpw = NULL; int new_pw_len; uchar new_ntp16[16]; uchar unenc_old_ntpw[16]; uchar new_p16[16]; uchar unenc_old_pw[16]; char no_pw[2]; BOOL nt_pass_set = (ntdata != NULL && nthash != NULL); become_root(False); *psmbpw = smbpw = getsmbpwnam(user); unbecome_root(False); if (smbpw == NULL) { DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n")); return False; } if (smbpw->acct_ctrl & ACB_DISABLED) { DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); return False; } /* construct a null password (in case one is needed */ no_pw[0] = 0; no_pw[1] = 0; nt_lm_owf_gen(no_pw, null_ntpw, null_pw); /* check for null passwords */ if (smbpw->smb_passwd == NULL) { if (smbpw->acct_ctrl & ACB_PWNOTREQ) { smbpw->smb_passwd = null_pw; } else { DEBUG(0,("check_oem_password: no lanman password !\n")); return False; } } if (smbpw->smb_nt_passwd == NULL && nt_pass_set) { if (smbpw->acct_ctrl & ACB_PWNOTREQ) { smbpw->smb_nt_passwd = null_pw; } else { DEBUG(0,("check_oem_password: no ntlm password !\n")); return False; } } /* * Call the hash function to get the new password. */ SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True); /* * The length of the new password is in the last 4 bytes of * the data buffer. */ new_pw_len = IVAL(lmdata, 512); if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1) { DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len)); return False; } if (nt_pass_set) { /* * nt passwords are in unicode */ int uni_pw_len = new_pw_len; char *pw; new_pw_len /= 2; pw = dos_unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len); memcpy(new_passwd, pw, new_pw_len+1); } else { memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len); new_passwd[new_pw_len] = '\0'; } /* * To ensure we got the correct new password, hash it and * use it as a key to test the passed old password. */ nt_lm_owf_gen(new_passwd, new_ntp16, new_p16); if (!nt_pass_set) { /* * Now use new_p16 as the key to see if the old * password matches. */ D_P16(new_p16 , lmhash, unenc_old_pw); if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); return False; } #ifdef DEBUG_PASSWORD DEBUG(100,("check_oem_password: password %s ok\n", new_passwd)); #endif return True; } /* * Now use new_p16 as the key to see if the old * password matches. */ D_P16(new_ntp16, lmhash, unenc_old_pw); D_P16(new_ntp16, nthash, unenc_old_ntpw); if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) { DEBUG(0,("check_oem_password: old lm password doesn't match.\n")); return False; } if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16)) { DEBUG(0,("check_oem_password: old nt password doesn't match.\n")); return False; } #ifdef DEBUG_PASSWORD DEBUG(100,("check_oem_password: password %s ok\n", new_passwd)); #endif return True; }
NTSTATUS rpccli_netlogon_password_logon( struct netlogon_creds_cli_context *creds_ctx, struct dcerpc_binding_handle *binding_handle, TALLOC_CTX *mem_ctx, uint32_t logon_parameters, const char *domain, const char *username, const char *password, const char *workstation, enum netr_LogonInfoClass logon_type, uint8_t *authoritative, uint32_t *flags, uint16_t *_validation_level, union netr_Validation **_validation) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; union netr_LogonLevel *logon; uint16_t validation_level = 0; union netr_Validation *validation = NULL; char *workstation_slash = NULL; logon = talloc_zero(frame, union netr_LogonLevel); if (logon == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } if (workstation == NULL) { workstation = lp_netbios_name(); } workstation_slash = talloc_asprintf(frame, "\\\\%s", workstation); if (workstation_slash == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } /* Initialise input parameters */ switch (logon_type) { case NetlogonInteractiveInformation: case NetlogonInteractiveTransitiveInformation: { struct netr_PasswordInfo *password_info; struct samr_Password lmpassword; struct samr_Password ntpassword; password_info = talloc_zero(frame, struct netr_PasswordInfo); if (password_info == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); password_info->identity_info.domain_name.string = domain; password_info->identity_info.parameter_control = logon_parameters; password_info->identity_info.logon_id_low = 0xdead; password_info->identity_info.logon_id_high = 0xbeef; password_info->identity_info.account_name.string = username; password_info->identity_info.workstation.string = workstation_slash; password_info->lmpassword = lmpassword; password_info->ntpassword = ntpassword; logon->password = password_info; break; } case NetlogonNetworkInformation: case NetlogonNetworkTransitiveInformation: { struct netr_NetworkInfo *network_info; uint8_t chal[8]; unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; struct netr_ChallengeResponse lm; struct netr_ChallengeResponse nt; ZERO_STRUCT(lm); ZERO_STRUCT(nt); network_info = talloc_zero(frame, struct netr_NetworkInfo); if (network_info == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } generate_random_buffer(chal, 8); SMBencrypt(password, chal, local_lm_response); SMBNTencrypt(password, chal, local_nt_response); lm.length = 24; lm.data = local_lm_response; nt.length = 24; nt.data = local_nt_response; network_info->identity_info.domain_name.string = domain; network_info->identity_info.parameter_control = logon_parameters; network_info->identity_info.logon_id_low = 0xdead; network_info->identity_info.logon_id_high = 0xbeef; network_info->identity_info.account_name.string = username; network_info->identity_info.workstation.string = workstation_slash; memcpy(network_info->challenge, chal, 8); network_info->nt = nt; network_info->lm = lm; logon->network = network_info; break; } default: DEBUG(0, ("switch value %d not supported\n", logon_type)); TALLOC_FREE(frame); return NT_STATUS_INVALID_INFO_CLASS; } status = netlogon_creds_cli_LogonSamLogon(creds_ctx, binding_handle, logon_type, logon, mem_ctx, &validation_level, &validation, authoritative, flags); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); return status; } TALLOC_FREE(frame); *_validation_level = validation_level; *_validation = validation; return NT_STATUS_OK; }
NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 logon_parameters, const char *domain, const char *username, const char *password, const char *workstation, uint16_t validation_level, int logon_type) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; NTSTATUS status; struct netr_Authenticator clnt_creds; struct netr_Authenticator ret_creds; union netr_LogonLevel *logon; union netr_Validation validation; uint8_t authoritative; fstring clnt_name_slash; struct dcerpc_binding_handle *b = cli->binding_handle; ZERO_STRUCT(ret_creds); logon = talloc_zero(mem_ctx, union netr_LogonLevel); if (!logon) { return NT_STATUS_NO_MEMORY; } if (workstation) { fstr_sprintf( clnt_name_slash, "\\\\%s", workstation ); } else { fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() ); } /* Initialise input parameters */ netlogon_creds_client_authenticator(cli->dc, &clnt_creds); switch (logon_type) { case NetlogonInteractiveInformation: { struct netr_PasswordInfo *password_info; struct samr_Password lmpassword; struct samr_Password ntpassword; password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo); if (!password_info) { return NT_STATUS_NO_MEMORY; } nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); if (cli->dc->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { netlogon_creds_aes_encrypt(cli->dc, lmpassword.hash, 16); netlogon_creds_aes_encrypt(cli->dc, ntpassword.hash, 16); } else if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) { netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16); netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16); } else { netlogon_creds_des_encrypt(cli->dc, &lmpassword); netlogon_creds_des_encrypt(cli->dc, &ntpassword); } password_info->identity_info.domain_name.string = domain; password_info->identity_info.parameter_control = logon_parameters; password_info->identity_info.logon_id_low = 0xdead; password_info->identity_info.logon_id_high = 0xbeef; password_info->identity_info.account_name.string = username; password_info->identity_info.workstation.string = clnt_name_slash; password_info->lmpassword = lmpassword; password_info->ntpassword = ntpassword; logon->password = password_info; break; } case NetlogonNetworkInformation: { struct netr_NetworkInfo *network_info; uint8 chal[8]; unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; struct netr_ChallengeResponse lm; struct netr_ChallengeResponse nt; ZERO_STRUCT(lm); ZERO_STRUCT(nt); network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); if (!network_info) { return NT_STATUS_NO_MEMORY; } generate_random_buffer(chal, 8); SMBencrypt(password, chal, local_lm_response); SMBNTencrypt(password, chal, local_nt_response); lm.length = 24; lm.data = local_lm_response; nt.length = 24; nt.data = local_nt_response; network_info->identity_info.domain_name.string = domain; network_info->identity_info.parameter_control = logon_parameters; network_info->identity_info.logon_id_low = 0xdead; network_info->identity_info.logon_id_high = 0xbeef; network_info->identity_info.account_name.string = username; network_info->identity_info.workstation.string = clnt_name_slash; memcpy(network_info->challenge, chal, 8); network_info->nt = nt; network_info->lm = lm; logon->network = network_info; break; } default: DEBUG(0, ("switch value %d not supported\n", logon_type)); return NT_STATUS_INVALID_INFO_CLASS; } status = dcerpc_netr_LogonSamLogon(b, mem_ctx, cli->srv_name_slash, lp_netbios_name(), &clnt_creds, &ret_creds, logon_type, logon, validation_level, &validation, &authoritative, &result); if (!NT_STATUS_IS_OK(status)) { return status; } /* Always check returned credentials */ if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n")); return NT_STATUS_ACCESS_DENIED; } return result; }