static bool wbinfo_auth_crap(char *username, const char *pass) { wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; DATA_BLOB lm = data_blob_null; DATA_BLOB nt = data_blob_null; fstring name_user; fstring name_domain; parse_wbinfo_domain_user(username, name_domain, name_user); params.account_name = name_user; params.domain_name = name_domain; params.workstation_name = NULL; params.flags = 0; params.parameter_control= WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT; params.level = WBC_AUTH_USER_LEVEL_RESPONSE; generate_random_buffer(params.password.response.challenge, 8); if (lp_client_ntlmv2_auth()) { DATA_BLOB server_chal; DATA_BLOB names_blob; server_chal = data_blob(params.password.response.challenge, 8); /* Pretend this is a login to 'us', for blob purposes */ names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); if (!SMBNTLMv2encrypt(name_user, name_domain, pass, &server_chal, &names_blob, &lm, &nt, NULL)) { data_blob_free(&names_blob); data_blob_free(&server_chal); return false; } data_blob_free(&names_blob); data_blob_free(&server_chal); } else { if (lp_client_lanman_auth()) { bool ok; lm = data_blob(NULL, 24); ok = SMBencrypt(pass, params.password.response.challenge, lm.data); if (!ok) { data_blob_free(&lm); } } nt = data_blob(NULL, 24); SMBNTencrypt(pass, params.password.response.challenge, nt.data); } params.password.response.nt_length = nt.length; params.password.response.nt_data = nt.data; params.password.response.lm_length = lm.length; params.password.response.lm_data = lm.data; wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); /* Display response */ d_printf("challenge/response password authentication %s\n", WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed"); if (wbc_status == WBC_ERR_AUTH_ERROR) { d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", err->nt_string, err->nt_status, err->display_string); wbcFreeMemory(err); } else if (WBC_ERROR_IS_OK(wbc_status)) { wbcFreeMemory(info); } data_blob_free(&nt); data_blob_free(&lm); return WBC_ERROR_IS_OK(wbc_status); }
static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, const DATA_BLOB reply, DATA_BLOB *next_request) { uint32 chal_flags, ntlmssp_command, unkn1, unkn2; DATA_BLOB server_domain_blob; DATA_BLOB challenge_blob; DATA_BLOB struct_blob = data_blob(NULL, 0); char *server_domain; const char *chal_parse_string; const char *auth_gen_string; DATA_BLOB lm_response = data_blob(NULL, 0); DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB encrypted_session_key = data_blob(NULL, 0); NTSTATUS nt_status; if (!msrpc_parse(&reply, "CdBd", "NTLMSSP", &ntlmssp_command, &server_domain_blob, &chal_flags)) { DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n")); dump_data(2, (const char *)reply.data, reply.length); return NT_STATUS_INVALID_PARAMETER; } data_blob_free(&server_domain_blob); DEBUG(3, ("Got challenge flags:\n")); debug_ntlmssp_flags(chal_flags); ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth()); if (ntlmssp_state->unicode) { if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { chal_parse_string = "CdUdbddB"; } else { chal_parse_string = "CdUdbdd"; } auth_gen_string = "CdBBUUUBd"; } else { if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { chal_parse_string = "CdAdbddB"; } else { chal_parse_string = "CdAdbdd"; } auth_gen_string = "CdBBAAABd"; } DEBUG(3, ("NTLMSSP: Set final flags:\n")); debug_ntlmssp_flags(ntlmssp_state->neg_flags); if (!msrpc_parse(&reply, chal_parse_string, "NTLMSSP", &ntlmssp_command, &server_domain, &chal_flags, &challenge_blob, 8, &unkn1, &unkn2, &struct_blob)) { DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n")); dump_data(2, (const char *)reply.data, reply.length); return NT_STATUS_INVALID_PARAMETER; } ntlmssp_state->server_domain = talloc_strdup(ntlmssp_state->mem_ctx, server_domain); SAFE_FREE(server_domain); if (challenge_blob.length != 8) { data_blob_free(&struct_blob); return NT_STATUS_INVALID_PARAMETER; } if (!ntlmssp_state->password) { static const uchar zeros[16]; /* do nothing - blobs are zero length */ /* session key is all zeros */ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16); /* not doing NLTM2 without a password */ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; } else if (ntlmssp_state->use_ntlmv2) { if (!struct_blob.length) { /* be lazy, match win2k - we can't do NTLMv2 without it */ DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n")); return NT_STATUS_INVALID_PARAMETER; } /* TODO: if the remote server is standalone, then we should replace 'domain' with the server name as supplied above */ if (!SMBNTLMv2encrypt(ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->password, &challenge_blob, &struct_blob, &lm_response, &nt_response, &session_key)) { data_blob_free(&challenge_blob); data_blob_free(&struct_blob); return NT_STATUS_NO_MEMORY; } } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { struct MD5Context md5_session_nonce_ctx; uchar nt_hash[16]; uchar session_nonce[16]; uchar session_nonce_hash[16]; uchar user_session_key[16]; E_md4hash(ntlmssp_state->password, nt_hash); lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); generate_random_buffer(lm_response.data, 8); memset(lm_response.data+8, 0, 16); memcpy(session_nonce, challenge_blob.data, 8); memcpy(&session_nonce[8], lm_response.data, 8); MD5Init(&md5_session_nonce_ctx); MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8); MD5Update(&md5_session_nonce_ctx, lm_response.data, 8); MD5Final(session_nonce_hash, &md5_session_nonce_ctx); DEBUG(5, ("NTLMSSP challenge set by NTLM2\n")); DEBUG(5, ("challenge is: \n")); dump_data(5, (const char *)session_nonce_hash, 8); nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); SMBNTencrypt(ntlmssp_state->password, session_nonce_hash, nt_response.data); session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); SMBsesskeygen_ntv1(nt_hash, NULL, user_session_key); hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { uchar lm_hash[16]; uchar nt_hash[16]; E_deshash(ntlmssp_state->password, lm_hash); E_md4hash(ntlmssp_state->password, nt_hash); /* lanman auth is insecure, it may be disabled */ if (lp_client_lanman_auth()) { lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); SMBencrypt(ntlmssp_state->password,challenge_blob.data, lm_response.data); } nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); SMBNTencrypt(ntlmssp_state->password,challenge_blob.data, nt_response.data); session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && lp_client_lanman_auth()) { SMBsesskeygen_lmv1(lm_hash, lm_response.data, session_key.data); dump_data_pw("LM session key\n", session_key.data, session_key.length); } else { SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); dump_data_pw("NT session key:\n", session_key.data, session_key.length); } } data_blob_free(&struct_blob); /* Key exchange encryptes a new client-generated session key with the password-derived key */ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { /* Make up a new session key */ uint8 client_session_key[16]; generate_random_buffer(client_session_key, sizeof(client_session_key)); /* Encrypt the new session key with the old one */ encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key)); dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length); SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length); dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); /* Mark the new session key as the 'real' session key */ data_blob_free(&session_key); session_key = data_blob_talloc(ntlmssp_state->mem_ctx, client_session_key, sizeof(client_session_key)); } /* this generates the actual auth packet */ if (!msrpc_gen(next_request, auth_gen_string, "NTLMSSP", NTLMSSP_AUTH, lm_response.data, lm_response.length, nt_response.data, nt_response.length, ntlmssp_state->domain, ntlmssp_state->user, ntlmssp_state->get_global_myname(), encrypted_session_key.data, encrypted_session_key.length, ntlmssp_state->neg_flags)) { return NT_STATUS_NO_MEMORY; } data_blob_free(&encrypted_session_key); data_blob_free(&ntlmssp_state->chal); ntlmssp_state->chal = challenge_blob; ntlmssp_state->lm_resp = lm_response; ntlmssp_state->nt_resp = nt_response; ntlmssp_state->session_key = session_key; ntlmssp_state->expected_state = NTLMSSP_UNKNOWN; if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) { DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status))); return nt_status; } return NT_STATUS_MORE_PROCESSING_REQUIRED; }
static bool test_lmv2_ntlmv2_broken(enum ntlm_break break_which) { bool pass = True; NTSTATUS nt_status; uint32 flags = 0; DATA_BLOB ntlmv2_response = data_blob_null; DATA_BLOB lmv2_response = data_blob_null; DATA_BLOB ntlmv2_session_key = data_blob_null; DATA_BLOB names_blob = NTLMv2_generate_names_blob(NULL, get_winbind_netbios_name(), get_winbind_domain()); uchar user_session_key[16]; DATA_BLOB chall = get_challenge(); char *error_string; ZERO_STRUCT(user_session_key); flags |= WBFLAG_PAM_USER_SESSION_KEY; if (!SMBNTLMv2encrypt(NULL, opt_username, opt_domain, opt_password, &chall, &names_blob, &lmv2_response, &ntlmv2_response, NULL, &ntlmv2_session_key)) { data_blob_free(&names_blob); return False; } data_blob_free(&names_blob); switch (break_which) { case BREAK_NONE: break; case BREAK_LM: lmv2_response.data[0]++; break; case BREAK_NT: ntlmv2_response.data[0]++; break; case NO_LM: data_blob_free(&lmv2_response); break; case NO_NT: data_blob_free(&ntlmv2_response); break; } nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, &chall, &lmv2_response, &ntlmv2_response, flags, NULL, user_session_key, &error_string, NULL); data_blob_free(&lmv2_response); data_blob_free(&ntlmv2_response); if (!NT_STATUS_IS_OK(nt_status)) { d_printf("%s (0x%x)\n", error_string, NT_STATUS_V(nt_status)); SAFE_FREE(error_string); return break_which == BREAK_NT; } if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key, sizeof(user_session_key)) != 0) { DEBUG(1, ("USER (NTLMv2) Session Key does not match expectations!\n")); DEBUG(1, ("user_session_key:\n")); dump_data(1, user_session_key, 16); DEBUG(1, ("expected:\n")); dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length); pass = False; } return pass; }
static bool wbinfo_auth_crap(struct loadparm_context *lp_ctx, char *username) { struct winbindd_request request; struct winbindd_response response; NSS_STATUS result; fstring name_user; fstring name_domain; fstring pass; char *p; /* Send off request */ ZERO_STRUCT(request); ZERO_STRUCT(response); p = strchr(username, '%'); if (p) { *p = 0; fstrcpy(pass, p + 1); } parse_wbinfo_domain_user(username, name_domain, name_user); request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT; fstrcpy(request.data.auth_crap.user, name_user); fstrcpy(request.data.auth_crap.domain, name_domain); generate_random_buffer(request.data.auth_crap.chal, 8); if (lp_client_ntlmv2_auth(lp_ctx)) { DATA_BLOB server_chal; DATA_BLOB names_blob; DATA_BLOB lm_response; DATA_BLOB nt_response; TALLOC_CTX *mem_ctx; mem_ctx = talloc_new(NULL); if (mem_ctx == NULL) { d_printf("talloc_new failed\n"); return false; } server_chal = data_blob(request.data.auth_crap.chal, 8); /* Pretend this is a login to 'us', for blob purposes */ names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(lp_ctx), lp_workgroup(lp_ctx)); if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, pass, &server_chal, &names_blob, &lm_response, &nt_response, NULL, NULL)) { data_blob_free(&names_blob); data_blob_free(&server_chal); return false; } data_blob_free(&names_blob); data_blob_free(&server_chal); memcpy(request.data.auth_crap.nt_resp, nt_response.data, MIN(nt_response.length, sizeof(request.data.auth_crap.nt_resp))); request.data.auth_crap.nt_resp_len = nt_response.length; memcpy(request.data.auth_crap.lm_resp, lm_response.data, MIN(lm_response.length, sizeof(request.data.auth_crap.lm_resp))); request.data.auth_crap.lm_resp_len = lm_response.length; data_blob_free(&nt_response); data_blob_free(&lm_response); } else { if (lp_client_lanman_auth(lp_ctx) && SMBencrypt(pass, request.data.auth_crap.chal, (unsigned char *)request.data.auth_crap.lm_resp)) { request.data.auth_crap.lm_resp_len = 24; } else { request.data.auth_crap.lm_resp_len = 0; } SMBNTencrypt(pass, request.data.auth_crap.chal, (unsigned char *)request.data.auth_crap.nt_resp); request.data.auth_crap.nt_resp_len = 24; } result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response); /* Display response */ d_printf("challenge/response password authentication %s\n", (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); if (response.data.auth.nt_status) d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", response.data.auth.nt_status_string, response.data.auth.nt_status, response.data.auth.error_string); return result == NSS_STATUS_SUCCESS; }