void buildSmbNtlmAuthResponse(tSmbNtlmAuthChallenge *challenge, tSmbNtlmAuthResponse *response, char *user, char *password) { uint8 lmRespData[24]; uint8 ntRespData[24]; char *d = strdup(GetUnicodeString(challenge,uDomain)); char *domain = d; char *u = strdup(user); char *p = strchr(u,'@'); if (p) { domain = p+1; *p = '\0'; } SMBencrypt(password, challenge->challengeData, lmRespData); SMBNTencrypt(password, challenge->challengeData, ntRespData); response->bufIndex = 0; memcpy(response->ident,"NTLMSSP\0\0\0",8); SIVAL(&response->msgType,0,3); AddBytes(response,lmResponse,lmRespData,24); AddBytes(response,ntResponse,ntRespData,24); AddUnicodeString(response,uDomain,domain); AddUnicodeString(response,uUser,u); AddUnicodeString(response,uWks,u); AddString(response,sessionKey,NULL); response->flags = challenge->flags; free(d); free(u); }
/* returns 0 on success, > 0 on failure */ static int init_challenge(char *domain, char *domain_controller) { int smberr; if (handle != NULL) { return 0; } debug("Connecting to server %s domain %s\n", domain_controller, domain); handle = SMB_Connect_Server(NULL, domain_controller, domain); smberr = SMB_Get_Last_Error(); SMB_Get_Error_Msg(smberr, errstr, 1000); if (handle == NULL) { /* couldn't connect */ debug("Couldn't connect to SMB Server. Error:%s\n", errstr); return 1; } if (SMB_Negotiate(handle, SMB_Prots) < 0) { /* An error */ debug("Error negotiating protocol with SMB Server\n"); SMB_Discon(handle, 0); handle = NULL; return 2; } if (handle->Security == 0) { /* share-level security, unuseable */ debug("SMB Server uses share-level security .. we need user security.\n"); SMB_Discon(handle, 0); handle = NULL; return 3; } memcpy(challenge, handle->Encrypt_Key, NONCE_LEN); SMBencrypt((unsigned char *)"",challenge,lmencoded_empty_pass); SMBNTencrypt((unsigned char *)"",challenge,ntencoded_empty_pass); return 0; }
int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, char *lnm_session_key) { int i; int rc; char password_with_pad[CIFS_ENCPWD_SIZE]; memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); if (password) strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) { memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE); return 0; } /* calculate old style session key */ /* calling toupper is less broken than repeatedly calling nls_toupper would be since that will never work for UTF8, but neither handles multibyte code pages but the only alternative would be converting to UCS-16 (Unicode) (using a routine something like UniStrupr) then uppercasing and then converting back from Unicode - which would only worth doing it if we knew it were utf8. Basically utf8 and other multibyte codepages each need their own strupper function since a byte at a time will ont work. */ for (i = 0; i < CIFS_ENCPWD_SIZE; i++) password_with_pad[i] = toupper(password_with_pad[i]); rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key); return rc; }
static PyObject *py_auth_smbd(PyObject *self, PyObject *args, PyObject *kw) { static char *kwlist[] = {"username", "password", "use_lm_hash", "use_nt_hash", NULL }; struct winbindd_request request; struct winbindd_response response; char *username, *password; int use_lm_hash = 1, use_nt_hash = 1; if (!PyArg_ParseTupleAndKeywords( args, kw, "ss|ii", kwlist, &username, &password, &use_lm_hash, &use_nt_hash)) return NULL; ZERO_STRUCT(request); ZERO_STRUCT(response); if (push_utf8_fstring(request.data.auth_crap.user, username) == -1) { PyErr_SetString("unable to create utf8 string"); return NULL; } generate_random_buffer(request.data.smbd_auth_crap.chal, 8); if (use_lm_hash) { SMBencrypt((uchar *)password, request.data.smbd_auth_crap.chal, (uchar *)request.data.smbd_auth_crap.lm_resp); request.data.smbd_auth_crap.lm_resp_len = 24; } if (use_nt_hash) { SMBNTencrypt((uchar *)password, request.data.smbd_auth_crap.chal, (uchar *)request.data.smbd_auth_crap.nt_resp); request.data.smbd_auth_crap.nt_resp_len = 24; } if (!secrets_fetch_trust_account_password( lp_workgroup(), request.data.smbd_auth_crap.proof, NULL)) { PyErr_SetString( winbind_error, "unable to fetch domain secret"); return NULL; } if (winbindd_request(WINBINDD_SMBD_AUTH_CRAP, &request, &response) != NSS_STATUS_SUCCESS) { PyErr_SetString(winbind_error, "lookup failed"); return NULL; } return PyInt_FromLong(response.data.auth.nt_status); }
/* wrapper around smb_raw_tcon() */ NTSTATUS smbcli_tconX(struct smbcli_state *cli, const char *sharename, const char *devtype, const char *password) { union smb_tcon tcon; TALLOC_CTX *mem_ctx; NTSTATUS status; cli->tree = smbcli_tree_init(cli->session, cli, true); if (!cli->tree) return NT_STATUS_UNSUCCESSFUL; mem_ctx = talloc_init("tcon"); if (!mem_ctx) { return NT_STATUS_NO_MEMORY; } /* setup a tree connect */ tcon.generic.level = RAW_TCON_TCONX; tcon.tconx.in.flags = TCONX_FLAG_EXTENDED_RESPONSE; tcon.tconx.in.flags |= TCONX_FLAG_EXTENDED_SIGNATURES; if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) { tcon.tconx.in.password = data_blob(NULL, 0); } else if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { tcon.tconx.in.password = data_blob_talloc(mem_ctx, NULL, 24); if (cli->transport->negotiate.secblob.length < 8) { return NT_STATUS_INVALID_PARAMETER; } SMBencrypt(password, cli->transport->negotiate.secblob.data, tcon.tconx.in.password.data); } else { tcon.tconx.in.password = data_blob_talloc(mem_ctx, password, strlen(password)+1); } tcon.tconx.in.path = sharename; tcon.tconx.in.device = devtype; status = smb_raw_tcon(cli->tree, mem_ctx, &tcon); cli->tree->tid = tcon.tconx.out.tid; if (tcon.tconx.out.options & SMB_EXTENDED_SIGNATURES) { smb1cli_session_protect_session_key(cli->tree->session->smbXcli); } talloc_free(mem_ctx); return status; }
void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key) { int i; char password_with_pad[CIFS_ENCPWD_SIZE]; if (ses->server == NULL) return; memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); if (ses->password) strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0) if (extended_security & CIFSSEC_MAY_PLNTXT) { memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE); return; } /* calculate old style session key */ /* calling toupper is less broken than repeatedly calling nls_toupper would be since that will never work for UTF8, but neither handles multibyte code pages but the only alternative would be converting to UCS-16 (Unicode) (using a routine something like UniStrupr) then uppercasing and then converting back from Unicode - which would only worth doing it if we knew it were utf8. Basically utf8 and other multibyte codepages each need their own strupper function since a byte at a time will ont work. */ for (i = 0; i < CIFS_ENCPWD_SIZE; i++) { password_with_pad[i] = toupper(password_with_pad[i]); } SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key); /* clear password before we return/free memory */ memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); }
enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) { NTSTATUS result; fstring name_domain, name_user; unsigned char trust_passwd[16]; time_t last_change_time; uint32 sec_channel_type; NET_USER_INFO_3 info3; struct cli_state *cli = NULL; uchar chal[8]; TALLOC_CTX *mem_ctx = NULL; DATA_BLOB lm_resp; DATA_BLOB nt_resp; DOM_CRED ret_creds; int attempts = 0; unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; struct winbindd_domain *contact_domain; BOOL retry; /* Ensure null termination */ state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; /* Ensure null termination */ state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0'; DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid, state->request.data.auth.user)); if (!(mem_ctx = talloc_init("winbind pam auth for %s", state->request.data.auth.user))) { DEBUG(0, ("winbindd_pam_auth: could not talloc_init()!\n")); result = NT_STATUS_NO_MEMORY; goto done; } /* Parse domain and username */ parse_domain_user(state->request.data.auth.user, name_domain, name_user); /* do password magic */ generate_random_buffer(chal, 8); SMBencrypt(state->request.data.auth.pass, chal, local_lm_response); SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response)); nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response)); /* what domain should we contact? */ if ( IS_DC ) { if (!(contact_domain = find_domain_from_name(name_domain))) { DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", state->request.data.auth.user, name_domain, name_user, name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } } else { if (is_myname(name_domain)) { DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } if (!(contact_domain = find_our_domain())) { DEBUG(1, ("Authentication for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n", state->request.data.auth.user, name_domain, name_user)); result = NT_STATUS_NO_SUCH_USER; goto done; } } if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) { result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; goto done; } /* check authentication loop */ do { ZERO_STRUCT(info3); ZERO_STRUCT(ret_creds); retry = False; /* Don't shut this down - it belongs to the connection cache code */ result = cm_get_netlogon_cli(contact_domain, trust_passwd, sec_channel_type, False, &cli); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("could not open handle to NETLOGON pipe\n")); goto done; } result = cli_netlogon_sam_network_logon(cli, mem_ctx, &ret_creds, name_user, name_domain, global_myname(), chal, lm_resp, nt_resp, &info3); attempts += 1; /* We have to try a second time as cm_get_netlogon_cli might not yet have noticed that the DC has killed our connection. */ if ( cli->fd == -1 ) { retry = True; continue; } /* if we get access denied, a possible cuase was that we had and open connection to the DC, but someone changed our machine account password out from underneath us using 'net rpc changetrustpw' */ if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) { DEBUG(3,("winbindd_pam_auth: sam_logon returned ACCESS_DENIED. Maybe the trust account " "password was changed and we didn't know it. Killing connections to domain %s\n", name_domain)); winbindd_cm_flush(); retry = True; cli = NULL; } } while ( (attempts < 2) && retry ); if (cli != NULL) { /* We might have come out of the loop above with cli == NULL, so don't dereference that. */ clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); } if (NT_STATUS_IS_OK(result)) { netsamlogon_cache_store( cli->mem_ctx, &info3 ); wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); /* Check if the user is in the right group */ if (!NT_STATUS_IS_OK(result = check_info3_in_group(mem_ctx, &info3, state->request.data.auth.required_membership_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", state->request.data.auth.user, state->request.data.auth.required_membership_sid)); } } done: /* give us a more useful (more correct?) error code */ if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { result = NT_STATUS_NO_LOGON_SERVERS; } state->response.data.auth.nt_status = NT_STATUS_V(result); fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); /* we might have given a more useful error above */ if (!*state->response.data.auth.error_string) fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); state->response.data.auth.pam_error = nt_status_to_pam(result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", state->request.data.auth.user, state->response.data.auth.nt_status_string, state->response.data.auth.pam_error)); if ( NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_AFS_TOKEN) ) { char *afsname = strdup(lp_afs_username_map()); char *cell; if (afsname == NULL) goto no_token; afsname = realloc_string_sub(afsname, "%D", name_domain); afsname = realloc_string_sub(afsname, "%u", name_user); afsname = realloc_string_sub(afsname, "%U", name_user); if (afsname == NULL) goto no_token; strlower_m(afsname); cell = strchr(afsname, '@'); if (cell == NULL) goto no_token; *cell = '\0'; cell += 1; /* Append an AFS token string */ state->response.extra_data = afs_createtoken_str(afsname, cell); if (state->response.extra_data != NULL) state->response.length += strlen(state->response.extra_data)+1; no_token: SAFE_FREE(afsname); } if (mem_ctx) talloc_destroy(mem_ctx); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; }
bool make_user_info_for_reply(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const uint8 chal[8], DATA_BLOB plaintext_password) { DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; char *plaintext_password_string; /* * Not encrypted - do so. */ DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted " "format.\n")); if (plaintext_password.data && plaintext_password.length) { unsigned char local_lm_response[24]; #ifdef DEBUG_PASSWORD DEBUG(10,("Unencrypted password (len %d):\n", (int)plaintext_password.length)); dump_data(100, plaintext_password.data, plaintext_password.length); #endif SMBencrypt( (const char *)plaintext_password.data, (const uchar*)chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); /* We can't do an NT hash here, as the password needs to be case insensitive */ local_nt_blob = data_blob_null; } else { local_lm_blob = data_blob_null; local_nt_blob = data_blob_null; } plaintext_password_string = talloc_strndup(talloc_tos(), (const char *)plaintext_password.data, plaintext_password.length); if (!plaintext_password_string) { return False; } ret = make_user_info_map( user_info, smb_name, client_domain, get_remote_machine_name(), local_lm_blob.data ? &local_lm_blob : NULL, local_nt_blob.data ? &local_nt_blob : NULL, NULL, NULL, plaintext_password_string, AUTH_PASSWORD_PLAIN); if (plaintext_password_string) { memset(plaintext_password_string, '\0', strlen(plaintext_password_string)); talloc_free(plaintext_password_string); } data_blob_free(&local_lm_blob); return NT_STATUS_IS_OK(ret) ? True : False; }
static int ejs_cli_tree_connect(MprVarHandle eid, int argc, MprVar **argv) { struct smbcli_session *session; struct smbcli_tree *tree; union smb_tcon tcon; TALLOC_CTX *mem_ctx; NTSTATUS status; const char *password = ""; /* Argument parsing */ if (argc != 2) { ejsSetErrorMsg(eid, "tree_connect invalid arguments"); return -1; } if (!mprVarIsPtr(argv[0]->type)) { ejsSetErrorMsg(eid, "first arg is not a session handle"); return -1; } session = argv[0]->ptr; tree = smbcli_tree_init(session, session, False); if (!tree) { ejsSetErrorMsg(eid, "tree init failed"); return -1; } mem_ctx = talloc_init("tcon"); if (!mem_ctx) { ejsSetErrorMsg(eid, "talloc_init failed"); return -1; } /* Do tree connect */ tcon.generic.level = RAW_TCON_TCONX; tcon.tconx.in.flags = 0; if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) { tcon.tconx.in.password = data_blob(NULL, 0); } else if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { tcon.tconx.in.password = data_blob_talloc(mem_ctx, NULL, 24); if (session->transport->negotiate.secblob.length < 8) { ejsSetErrorMsg(eid, "invalid security blob"); return -1; } SMBencrypt(password, session->transport->negotiate.secblob.data, tcon.tconx.in.password.data); } else { tcon.tconx.in.password = data_blob_talloc(mem_ctx, password, strlen(password)+1); } tcon.tconx.in.path = argv[1]->string; tcon.tconx.in.device = "?????"; status = smb_tree_connect(tree, mem_ctx, &tcon); if (!NT_STATUS_IS_OK(status)) { ejsSetErrorMsg(eid, "tree_connect: %s", nt_errstr(status)); return -1; } tree->tid = tcon.tconx.out.tid; talloc_free(mem_ctx); mpr_Return(eid, mprCreatePtrVar(tree)); return 0; }
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; }
int SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName, char *PassWord) { struct RFCNB_Pkt *pkt; int param_len, pkt_len, pass_len; char *p, pword[256]; /* First we need a packet etc ... but we need to know what protocol has */ /* been negotiated to figure out if we can do it and what SMB format to */ /* use ... */ if (Con_Handle -> protocol < SMB_P_LanMan1) { SMBlib_errno = SMBlibE_ProtLow; return(SMBlibE_BAD); } strcpy(pword, PassWord); if (Con_Handle -> encrypt_passwords) { pass_len=24; SMBencrypt((uchar *) PassWord, (uchar *)Con_Handle -> Encrypt_Key,(uchar *)pword); } else pass_len=strlen(pword); /* Now build the correct structure */ if (Con_Handle -> protocol < SMB_P_NT1) { param_len = strlen(UserName) + 1 + pass_len + 1 + strlen(Con_Handle -> PDomain) + 1 + strlen(Con_Handle -> OSName) + 1; pkt_len = SMB_ssetpLM_len + param_len; pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); if (pkt == NULL) { SMBlib_errno = SMBlibE_NoSpace; return(SMBlibE_BAD); /* Should handle the error */ } bzero(SMB_Hdr(pkt), SMB_ssetpLM_len); SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid); *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10; *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */ SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT); SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2); SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle -> pid); SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, pass_len + 1); SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len); /* Now copy the param strings in with the right stuff */ p = (char *)(SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset); /* Copy in password, then the rest. Password has a null at end */ memcpy(p, pword, pass_len); p = p + pass_len + 1; strcpy(p, UserName); p = p + strlen(UserName); *p = 0; p = p + 1; strcpy(p, Con_Handle -> PDomain); p = p + strlen(Con_Handle -> PDomain); *p = 0; p = p + 1; strcpy(p, Con_Handle -> OSName); p = p + strlen(Con_Handle -> OSName); *p = 0; } else { /* We don't admit to UNICODE support ... */ param_len = strlen(UserName) + 1 + pass_len + strlen(Con_Handle -> PDomain) + 1 + strlen(Con_Handle -> OSName) + 1 + strlen(Con_Handle -> LMType) + 1; pkt_len = SMB_ssetpNTLM_len + param_len; pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); if (pkt == NULL) { SMBlib_errno = SMBlibE_NoSpace; return(-1); /* Should handle the error */ } bzero(SMB_Hdr(pkt), SMB_ssetpNTLM_len); SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid); *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13; *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */ SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT); SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0); SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, pass_len); SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0); SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0); SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0); SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len); /* Now copy the param strings in with the right stuff */ p = (char *)(SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset); /* Copy in password, then the rest. Password has no null at end */ memcpy(p, pword, pass_len); p = p + pass_len; strcpy(p, UserName); p = p + strlen(UserName); *p = 0; p = p + 1; strcpy(p, Con_Handle -> PDomain); p = p + strlen(Con_Handle -> PDomain); *p = 0; p = p + 1; strcpy(p, Con_Handle -> OSName); p = p + strlen(Con_Handle -> OSName); *p = 0; p = p + 1; strcpy(p, Con_Handle -> LMType); p = p + strlen(Con_Handle -> LMType); *p = 0; } /* Now send it and get a response */ if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0){ #ifdef DEBUG fprintf(stderr, "Error sending SessSetupX request\n"); #endif RFCNB_Free_Pkt(pkt); SMBlib_errno = SMBlibE_SendFailed; return(SMBlibE_BAD); } /* Now get the response ... */ if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) { #ifdef DEBUG fprintf(stderr, "Error receiving response to SessSetupAndX\n"); #endif RFCNB_Free_Pkt(pkt); SMBlib_errno = SMBlibE_RecvFailed; return(SMBlibE_BAD); } /* Check out the response type ... */ if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ #ifdef DEBUG fprintf(stderr, "SMB_SessSetupAndX failed with errorclass = %i, Error Code = %i\n", CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset), SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset)); #endif SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); RFCNB_Free_Pkt(pkt); SMBlib_errno = SMBlibE_Remote; return(SMBlibE_BAD); } /** @@@ mdz: check for guest login { **/ if (SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset) & 0x1) { /* do we allow guest login? NO! */ return(SMBlibE_BAD); } /** @@@ mdz: } **/ #ifdef DEBUG fprintf(stderr, "SessSetupAndX response. Action = %i\n", SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset)); #endif /* Now pick up the UID for future reference ... */ Con_Handle -> uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset); RFCNB_Free_Pkt(pkt); return(0); }
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; }
BOOL cli_session_setup(struct cli_state *cli, char *_user, char *pass, int passlen, char *ntpass, int ntpasslen, char *_workgroup) { fstring pword, ntpword; fstring user; fstring workgroup; uint8 protocol; SMB_HDR hdr; Q_SESSION_SETUP_ANDX qw; R_SESSION_SETUP_ANDX rw; Q_SESSION_SETUP_ANDX_D qd; R_SESSION_SETUP_ANDX_D rd; ZERO_STRUCT(qw); ZERO_STRUCT(rw); ZERO_STRUCT(qd); ZERO_STRUCT(rd); ZERO_STRUCT(pword); ZERO_STRUCT(ntpword); if (!smb_get_protocol(cli->hnd, &protocol)) return False; if (protocol < PROTOCOL_LANMAN1) return True; if (passlen > sizeof(pword) - 1 || ntpasslen > sizeof(ntpword) - 1) { return False; } if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) { /* Null session connect. */ pword[0] = '\0'; ntpword[0] = '\0'; passlen = 1; _user = ""; } else if ((cli->sec_mode & 2) && passlen != 24) { /* * Encrypted mode needed, and non encrypted password supplied. */ passlen = 24; ntpasslen = 24; fstrcpy(pword, pass); unix_to_dos(pword, True); fstrcpy(ntpword, ntpass);; unix_to_dos(ntpword, True); SMBencrypt((uchar *) pword, (uchar *) cli->cryptkey, (uchar *) pword); SMBNTencrypt((uchar *) ntpword, (uchar *) cli->cryptkey, (uchar *) ntpword); } else if ((cli->sec_mode & 2) && passlen == 24) { /* * Encrypted mode needed, and encrypted password supplied. */ memcpy(pword, pass, passlen); if (ntpasslen == 24) { memcpy(ntpword, ntpass, ntpasslen); } else { fstrcpy(ntpword, ""); ntpasslen = 0; } } else { /* * Plaintext mode needed, assume plaintext supplied. */ fstrcpy(pword, pass); unix_to_dos(pword, True); fstrcpy(ntpword, ""); ntpasslen = 0; } /* if in share level security then don't send a password now */ if (!(cli->sec_mode & 1)) { fstrcpy(pword, ""); passlen = 1; fstrcpy(ntpword, ""); ntpasslen = 1; } fstrcpy(user, _user); fstrcpy(workgroup, _workgroup); /* send a session setup command */ if (protocol < PROTOCOL_NT1) { Q_SESSION_SETUP_ANDX_D_10 *q10 = &qd.ctr.q10; Q_SESSION_SETUP_ANDX_10 *qs = &qw.ctr.q10; qw.wcount = 10; qd.wcount = 10; qs->andx.cmd = 0xff; qs->bufsize = cli->max_xmit; qs->max_mpx = 2; qs->vc = 1; qs->sess_key = cli->sesskey; qs->pwlen = passlen; q10->password = pword; q10->pwlen = passlen; smbstr_initA(&q10->user, user, 0); smbstr_initA(&q10->domain, workgroup, 0); smbstr_initA(&q10->os, "Unix", 0); smbstr_initA(&q10->server, "Samba", 0); smbstr_initA(&q10->pad1, "", 0); smbstr_initA(&q10->pad2, "", 0); } else { Q_SESSION_SETUP_ANDX_D_13 *q13 = &qd.ctr.q13; Q_SESSION_SETUP_ANDX_13 *qs = &qw.ctr.q13; qw.wcount = 13; qd.wcount = 13; qs->andx.cmd = 0xff; qs->bufsize = CLI_BUFFER_SIZE; qs->max_mpx = 2; smb_get_pid(cli->hnd, &qs->vc); qs->sess_key = cli->sesskey; qs->pwlen = passlen; qs->upwlen = ntpasslen; qs->capabilities = 0; q13->password = pword; q13->upassword = ntpword; q13->pwlen = passlen; q13->upwlen = ntpasslen; smbstr_initA(&q13->user, user, 0); smbstr_initA(&q13->domain, workgroup, 0); smbstr_initA(&q13->os, "Unix", 0); smbstr_initA(&q13->server, "Samba", 0); smbstr_initA(&q13->pad1, "", 0); smbstr_initA(&q13->pad2, "", 0); } cli->nterr = cli_SMBsesssetupX(cli->hnd, &qw, &rw, &qd, &rd, NULL, NULL); if (cli->nterr != 0) return False; if (!smb_get_hdr(cli->hnd, &hdr)) return False; /* * Save off some of the connected server * info. */ if (protocol >= PROTOCOL_NT1 && rw.wcount == 3) { R_SESSION_SETUP_ANDX_D_3 *sd = &rd.ctr.d3; fstrcpy(cli->server_os, smbstrA(&sd->os)); fstrcpy(cli->server_type, smbstrA(&sd->server)); fstrcpy(cli->server_domain, smbstrA(&sd->domain)); } fstrcpy(cli->user_name, user); dos_to_unix(cli->user_name, True); return True; }
/**************************************************************************** send a tconX ****************************************************************************/ BOOL cli_send_tconX(struct cli_state *cli, char *share, char *_dev, char *pass, int passlen) { fstring fullshare, pword, dos_pword, dev; uint8 protocol; SMB_HDR hdr; Q_TCON_ANDX qw; R_TCON_ANDX rw; Q_TCON_ANDX_D qd; R_TCON_ANDX_D rd; Q_TCON_ANDX_D_4 *q4 = &qd.ctr.q4; Q_TCON_ANDX_4 *qs = &qw.ctr.q4; ZERO_STRUCT(qw); ZERO_STRUCT(rw); ZERO_STRUCT(qd); ZERO_STRUCT(rd); if (!smb_get_protocol(cli->hnd, &protocol)) return False; fstrcpy(cli->share, share); /* in user level security don't send a password now */ if (cli->sec_mode & 1) { passlen = 1; pass = ""; } if ((cli->sec_mode & 2) && *pass && passlen != 24) { /* * Non-encrypted passwords - convert to DOS codepage before encryption. */ passlen = 24; fstrcpy(dos_pword, pass); SMBencrypt((uchar *) dos_pword, (uchar *) cli->cryptkey, (uchar *) pword); } else { if (!(cli->sec_mode & 2)) { /* * Non-encrypted passwords - convert to DOS codepage before using. */ fstrcpy(pword, pass); } else { memcpy(pword, pass, passlen); } } slprintf(fullshare, sizeof(fullshare) - 1, "\\\\%s\\%s", cli->desthost, share); strupper(fullshare); fstrcpy(dev, _dev); qw.wcount = 4; qd.wcount = 4; qs->andx.cmd = 0xff; qs->vwv2 = 0; qs->passlen = passlen; q4->plen = passlen; q4->password = pword; smbstr_initA(&q4->path, fullshare, 0); smbstr_initA(&q4->device, dev, 0); cli->nterr = cli_SMBtconX(cli->hnd, &qw, &rw, &qd, &rd, NULL, NULL); if (cli->nterr != 0) return False; if (!smb_get_hdr(cli->hnd, &hdr)) return False; fstrcpy(cli->dev, "A:"); if (protocol >= PROTOCOL_NT1 && rw.wcount == 3) { R_TCON_ANDX_D_3 *r3 = &rd.ctr.d3; fstrcpy(cli->dev, r3->service); } else if (rw.wcount == 2) { R_TCON_ANDX_D_2 *r2 = &rd.ctr.d2; fstrcpy(cli->dev, r2->service); } if (strcasecmp(share, "IPC$") == 0) { fstrcpy(cli->dev, "IPC"); } /* only grab the device if we have a recent protocol level */ if (protocol >= PROTOCOL_NT1 && rd.datalen == 3) { /* almost certainly win95 - enable bug fixes */ cli->win95 = True; } return True; }
static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user, const char *pass, int passlen) { fstring pword; char *p; if (passlen > sizeof(pword)-1) { return False; } /* if in share level security then don't send a password now */ if (!(cli->sec_mode & 1)) { passlen = 0; } if (passlen > 0 && (cli->sec_mode & 2) && passlen != 24) { /* Encrypted mode needed, and non encrypted password supplied. */ passlen = 24; clistr_push(cli, pword, pass, -1, STR_CONVERT|STR_TERMINATE); SMBencrypt((uchar *)pword,cli->cryptkey,(uchar *)pword); } else if ((cli->sec_mode & 2) && passlen == 24) { /* Encrypted mode needed, and encrypted password supplied. */ memcpy(pword, pass, passlen); } else if (passlen > 0) { /* Plaintext mode needed, assume plaintext supplied. */ passlen = clistr_push(cli, pword, pass, -1, STR_CONVERT|STR_TERMINATE); } /* send a session setup command */ memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,10, 0, True); SCVAL(cli->outbuf,smb_com,SMBsesssetupX); cli_setup_packet(cli); SCVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit); SSVAL(cli->outbuf,smb_vwv3,2); SSVAL(cli->outbuf,smb_vwv4,1); SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,passlen); p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; p += clistr_push(cli, p, user, -1, STR_TERMINATE); cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; show_msg(cli->inbuf); if (cli_is_error(cli)) { return False; } /* use the returned vuid from now on */ cli->vuid = SVAL(cli->inbuf,smb_uid); fstrcpy(cli->user_name, user); return True; }
BOOL cli_send_tconX(struct cli_state *cli, const char *share, const char *dev, const char *pass, int passlen) { fstring fullshare, pword, dos_pword; char *p; memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); fstrcpy(cli->share, share); /* in user level security don't send a password now */ if (cli->sec_mode & 1) { passlen = 1; pass = ""; } if ((cli->sec_mode & 2) && *pass && passlen != 24) { /* * Non-encrypted passwords - convert to DOS codepage before encryption. */ passlen = 24; clistr_push(cli, dos_pword, pass, -1, STR_CONVERT|STR_TERMINATE); SMBencrypt((uchar *)dos_pword,cli->cryptkey,(uchar *)pword); } else { if((cli->sec_mode & 3) == 0) { /* * Non-encrypted passwords - convert to DOS codepage before using. */ passlen = clistr_push(cli, pword, pass, -1, STR_CONVERT|STR_TERMINATE); } else { memcpy(pword, pass, passlen); } } slprintf(fullshare, sizeof(fullshare)-1, "\\\\%s\\%s", cli->desthost, share); set_message(cli->outbuf,4, 0, True); SCVAL(cli->outbuf,smb_com,SMBtconX); cli_setup_packet(cli); SSVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv3,passlen); p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; p += clistr_push(cli, p, fullshare, -1, STR_CONVERT|STR_TERMINATE|STR_UPPER); fstrcpy(p, dev); p += strlen(dev)+1; cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; if (cli_is_error(cli)) { return False; } fstrcpy(cli->dev, "A:"); if (cli->protocol >= PROTOCOL_NT1) { clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE); } if (strcasecmp(share,"IPC$")==0) { fstrcpy(cli->dev, "IPC"); } /* only grab the device if we have a recent protocol level */ if (cli->protocol >= PROTOCOL_NT1 && smb_buflen(cli->inbuf) == 3) { /* almost certainly win95 - enable bug fixes */ cli->win95 = True; } cli->cnum = SVAL(cli->inbuf,smb_tid); return True; }
static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, const char *pass, int passlen, const char *ntpass, int ntpasslen, const char *workgroup) { uint32 capabilities = cli_session_setup_capabilities(cli); fstring pword, ntpword; char *p; if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) { return False; } if (passlen != 24) { /* non encrypted password supplied. */ passlen = 24; ntpasslen = 24; clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE|STR_CONVERT); clistr_push(cli, ntpword, ntpass, sizeof(ntpword), STR_TERMINATE|STR_CONVERT); SMBencrypt((uchar *)pword,cli->cryptkey,(uchar *)pword); SMBNTencrypt((uchar *)ntpword,cli->cryptkey,(uchar *)ntpword); } else { memcpy(pword, pass, passlen); memcpy(ntpword, ntpass, ntpasslen); } /* send a session setup command */ memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,13,0,True); SCVAL(cli->outbuf,smb_com,SMBsesssetupX); cli_setup_packet(cli); SCVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); SSVAL(cli->outbuf,smb_vwv3,2); SSVAL(cli->outbuf,smb_vwv4,cli->pid); SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,passlen); SSVAL(cli->outbuf,smb_vwv8,ntpasslen); SIVAL(cli->outbuf,smb_vwv11,capabilities); p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; memcpy(p,ntpword,ntpasslen); p += ntpasslen; p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER|STR_CONVERT); p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER|STR_CONVERT); p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE|STR_CONVERT); p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE|STR_CONVERT); cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; show_msg(cli->inbuf); if (cli_is_error(cli)) { return False; } /* use the returned vuid from now on */ cli->vuid = SVAL(cli->inbuf,smb_uid); p = smb_buf(cli->inbuf); p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE); p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE); p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE); fstrcpy(cli->user_name, user); return True; }
static bool test_lm_ntlm_broken(enum ntlm_break break_which) { bool pass = True; NTSTATUS nt_status; uint32 flags = 0; DATA_BLOB lm_response = data_blob(NULL, 24); DATA_BLOB nt_response = data_blob(NULL, 24); DATA_BLOB session_key = data_blob(NULL, 16); uchar lm_key[8]; uchar user_session_key[16]; uchar lm_hash[16]; uchar nt_hash[16]; DATA_BLOB chall = get_challenge(); char *error_string; ZERO_STRUCT(lm_key); ZERO_STRUCT(user_session_key); flags |= WBFLAG_PAM_LMKEY; flags |= WBFLAG_PAM_USER_SESSION_KEY; SMBencrypt(opt_password,chall.data,lm_response.data); E_deshash(opt_password, lm_hash); SMBNTencrypt(opt_password,chall.data,nt_response.data); E_md4hash(opt_password, nt_hash); SMBsesskeygen_ntv1(nt_hash, session_key.data); switch (break_which) { case BREAK_NONE: break; case BREAK_LM: lm_response.data[0]++; break; case BREAK_NT: nt_response.data[0]++; break; case NO_LM: data_blob_free(&lm_response); break; case NO_NT: data_blob_free(&nt_response); break; } nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, &chall, &lm_response, &nt_response, flags, lm_key, user_session_key, &error_string, NULL); data_blob_free(&lm_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 (memcmp(lm_hash, lm_key, sizeof(lm_key)) != 0) { DEBUG(1, ("LM Key does not match expectations!\n")); DEBUG(1, ("lm_key:\n")); dump_data(1, lm_key, 8); DEBUG(1, ("expected:\n")); dump_data(1, lm_hash, 8); pass = False; } if (break_which == NO_NT) { if (memcmp(lm_hash, user_session_key, 8) != 0) { DEBUG(1, ("NT Session Key does not match expectations (should be LM hash)!\n")); DEBUG(1, ("user_session_key:\n")); dump_data(1, user_session_key, sizeof(user_session_key)); DEBUG(1, ("expected:\n")); dump_data(1, lm_hash, sizeof(lm_hash)); pass = False; } } else { if (memcmp(session_key.data, user_session_key, sizeof(user_session_key)) != 0) { DEBUG(1, ("NT 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, session_key.data, session_key.length); pass = False; } } return pass; }
_PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, int *flags, DATA_BLOB challenge, const NTTIME *server_timestamp, DATA_BLOB target_info, DATA_BLOB *_lm_response, DATA_BLOB *_nt_response, DATA_BLOB *_lm_session_key, DATA_BLOB *_session_key) { const char *user, *domain; DATA_BLOB lm_response, nt_response; DATA_BLOB lm_session_key, session_key; const struct samr_Password *nt_hash; lm_session_key = data_blob(NULL, 0); /* We may already have an NTLM response we prepared earlier. * This is used for NTLM pass-though authentication */ if (cred->nt_response.data || cred->lm_response.data) { *_nt_response = cred->nt_response; *_lm_response = cred->lm_response; if (!cred->lm_response.data) { *flags = *flags & ~CLI_CRED_LANMAN_AUTH; } *_lm_session_key = data_blob(NULL, 0); *_session_key = data_blob(NULL, 0); return NT_STATUS_OK; } nt_hash = cli_credentials_get_nt_hash(cred, mem_ctx); cli_credentials_get_ntlm_username_domain(cred, mem_ctx, &user, &domain); /* If we are sending a username@realm login (see function * above), then we will not send LM, it will not be * accepted */ if (cred->principal_obtained > cred->username_obtained) { *flags = *flags & ~CLI_CRED_LANMAN_AUTH; } /* Likewise if we are a machine account (avoid protocol downgrade attacks) */ if (cred->machine_account) { *flags = *flags & ~CLI_CRED_LANMAN_AUTH; } if (cred->use_kerberos == CRED_MUST_USE_KERBEROS) { return NT_STATUS_ACCESS_DENIED; } if (!nt_hash) { static const uint8_t zeros[16]; /* do nothing - blobs are zero length */ /* session key is all zeros */ session_key = data_blob_talloc(mem_ctx, zeros, 16); lm_session_key = data_blob_talloc(mem_ctx, zeros, 16); lm_response = data_blob(NULL, 0); nt_response = data_blob(NULL, 0); /* not doing NTLM2 without a password */ *flags &= ~CLI_CRED_NTLM2; } else if (*flags & CLI_CRED_NTLMv2_AUTH) { if (!target_info.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_hash(mem_ctx, user, domain, nt_hash->hash, &challenge, server_timestamp, &target_info, &lm_response, &nt_response, NULL, &session_key)) { return NT_STATUS_NO_MEMORY; } /* LM Key is incompatible... */ *flags &= ~CLI_CRED_LANMAN_AUTH; if (lm_response.length != 0) { /* * We should not expose the lm key. */ memset(lm_response.data, 0, lm_response.length); } } else if (*flags & CLI_CRED_NTLM2) { MD5_CTX md5_session_nonce_ctx; uint8_t session_nonce[16]; uint8_t session_nonce_hash[16]; uint8_t user_session_key[16]; lm_response = data_blob_talloc(mem_ctx, NULL, 24); generate_random_buffer(lm_response.data, 8); memset(lm_response.data+8, 0, 16); memcpy(session_nonce, challenge.data, 8); memcpy(&session_nonce[8], lm_response.data, 8); MD5Init(&md5_session_nonce_ctx); MD5Update(&md5_session_nonce_ctx, challenge.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, session_nonce_hash, 8); nt_response = data_blob_talloc(mem_ctx, NULL, 24); SMBOWFencrypt(nt_hash->hash, session_nonce_hash, nt_response.data); session_key = data_blob_talloc(mem_ctx, NULL, 16); SMBsesskeygen_ntv1(nt_hash->hash, 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); /* LM Key is incompatible... */ *flags &= ~CLI_CRED_LANMAN_AUTH; } else { uint8_t lm_hash[16]; nt_response = data_blob_talloc(mem_ctx, NULL, 24); SMBOWFencrypt(nt_hash->hash, challenge.data, nt_response.data); session_key = data_blob_talloc(mem_ctx, NULL, 16); SMBsesskeygen_ntv1(nt_hash->hash, session_key.data); dump_data_pw("NT session key:\n", session_key.data, session_key.length); /* lanman auth is insecure, it may be disabled. We may also not have a password */ if (*flags & CLI_CRED_LANMAN_AUTH) { const char *password; password = cli_credentials_get_password(cred); if (!password) { lm_response = nt_response; } else { lm_response = data_blob_talloc(mem_ctx, NULL, 24); if (!SMBencrypt(password,challenge.data, lm_response.data)) { /* If the LM password was too long (and therefore the LM hash being of the first 14 chars only), don't send it. We don't have any better options but to send the NT response */ data_blob_free(&lm_response); lm_response = nt_response; /* LM Key is incompatible with 'long' passwords */ *flags &= ~CLI_CRED_LANMAN_AUTH; } else if (E_deshash(password, lm_hash)) { lm_session_key = data_blob_talloc(mem_ctx, NULL, 16); memcpy(lm_session_key.data, lm_hash, 8); memset(&lm_session_key.data[8], '\0', 8); if (!(*flags & CLI_CRED_NTLM_AUTH)) { session_key = lm_session_key; } } } } else { const char *password; /* LM Key is incompatible... */ lm_response = nt_response; *flags &= ~CLI_CRED_LANMAN_AUTH; password = cli_credentials_get_password(cred); if (password && E_deshash(password, lm_hash)) { lm_session_key = data_blob_talloc(mem_ctx, NULL, 16); memcpy(lm_session_key.data, lm_hash, 8); memset(&lm_session_key.data[8], '\0', 8); } } } if (_lm_response) { *_lm_response = lm_response; } if (_nt_response) { *_nt_response = nt_response; } if (_lm_session_key) { *_lm_session_key = lm_session_key; } if (_session_key) { *_session_key = session_key; } return NT_STATUS_OK; }
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; }
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); }
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; }