diff options
Diffstat (limited to 'source3/libsmb/cliconnect.c')
-rw-r--r-- | source3/libsmb/cliconnect.c | 313 |
1 files changed, 148 insertions, 165 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 487b184dd6..389b7a1733 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. client connect/disconnect routines Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Andrew Barteltt 2001-2003 + Copyright (C) Andrew Barteltt 2001-2002 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +45,7 @@ static const struct { ****************************************************************************/ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user, - const char *pass, size_t passlen, const char *workgroup) + const char *pass, int passlen, const char *workgroup) { fstring pword; char *p; @@ -228,7 +228,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user, return True; } -static void set_signing_on_cli (struct cli_state *cli, uint8 user_session_key[16], DATA_BLOB response) +static void set_signing_on_cli (struct cli_state *cli, const char* pass, uint8 response[24]) { uint8 zero_sig[8]; ZERO_STRUCT(zero_sig); @@ -242,18 +242,12 @@ static void set_signing_on_cli (struct cli_state *cli, uint8 user_session_key[16 DEBUG(3, ("smb signing enabled!\n")); cli->sign_info.use_smb_signing = True; - cli_calculate_mac_key(cli, user_session_key, response); + cli_calculate_mac_key(cli, pass, response); } else { DEBUG(5, ("smb signing NOT enabled!\n")); } } -static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key) -{ - memcpy(cli->user_session_key, session_key.data, MIN(session_key.length, sizeof(cli->user_session_key))); -} - - static void set_temp_signing_on_cli(struct cli_state *cli) { if (cli->sign_info.negotiated_smb_signing) @@ -271,54 +265,37 @@ static void set_temp_signing_on_cli(struct cli_state *cli) ****************************************************************************/ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, - const char *pass, size_t passlen, - const char *ntpass, size_t ntpasslen, + const char *pass, int passlen, + const char *ntpass, int ntpasslen, const char *workgroup) { uint32 capabilities = cli_session_setup_capabilities(cli); - DATA_BLOB lm_response = data_blob(NULL, 0); - DATA_BLOB nt_response = data_blob(NULL, 0); - DATA_BLOB session_key = data_blob(NULL, 0); - BOOL ret = False; + uchar pword[24]; + uchar ntpword[24]; char *p; + BOOL have_plaintext = False; - if (passlen != 24) { - if (lp_client_ntlmv2_auth()) { - DATA_BLOB server_chal; - - server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); - - if (!SMBNTLMv2encrypt(user, workgroup, pass, server_chal, - &lm_response, &nt_response, &session_key)) { - data_blob_free(&server_chal); - return False; - } - data_blob_free(&server_chal); - - } else { - uchar nt_hash[16]; - E_md4hash(pass, nt_hash); - - /* non encrypted password supplied. Ignore ntpass. */ - if (lp_client_lanman_auth()) { - lm_response = data_blob(NULL, 24); - SMBencrypt(pass,cli->secblob.data,lm_response.data); - } + if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword)) + return False; - nt_response = data_blob(NULL, 24); - SMBNTencrypt(pass,cli->secblob.data,nt_response.data); - session_key = data_blob(NULL, 16); - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); - } + if (passlen != 24) { + /* non encrypted password supplied. Ignore ntpass. */ + passlen = 24; + ntpasslen = 24; + SMBencrypt(pass,cli->secblob.data,pword); + SMBNTencrypt(pass,cli->secblob.data,ntpword); + have_plaintext = True; set_temp_signing_on_cli(cli); } else { /* pre-encrypted password supplied. Only used for security=server, can't do signing becouse we don't have oringial key */ - - lm_response = data_blob(pass, passlen); - nt_response = data_blob(ntpass, ntpasslen); + memcpy(pword, pass, 24); + if (ntpasslen == 24) + memcpy(ntpword, ntpass, 24); + else + ZERO_STRUCT(ntpword); } /* send a session setup command */ @@ -333,33 +310,28 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, 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,lm_response.length); - SSVAL(cli->outbuf,smb_vwv8,nt_response.length); + SSVAL(cli->outbuf,smb_vwv7,passlen); + SSVAL(cli->outbuf,smb_vwv8,ntpasslen); SIVAL(cli->outbuf,smb_vwv11,capabilities); p = smb_buf(cli->outbuf); - if (lm_response.length) { - memcpy(p,lm_response.data, lm_response.length); p += lm_response.length; - } - if (nt_response.length) { - memcpy(p,nt_response.data, nt_response.length); p += nt_response.length; - } + memcpy(p,pword,passlen); p += passlen; + memcpy(p,ntpword,ntpasslen); p += ntpasslen; p += clistr_push(cli, p, user, -1, STR_TERMINATE); p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); cli_setup_bcc(cli, p); - if (!cli_send_smb(cli) || !cli_receive_smb(cli)) { - ret = False; - goto end; - } + if (!cli_send_smb(cli)) + return False; + + if (!cli_receive_smb(cli)) + return False; show_msg(cli->inbuf); - if (cli_is_error(cli)) { - ret = False; - goto end; - } + if (cli_is_error(cli)) + return False; /* use the returned vuid from now on */ cli->vuid = SVAL(cli->inbuf,smb_uid); @@ -371,16 +343,11 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, fstrcpy(cli->user_name, user); - if (session_key.data) { + if (have_plaintext) { /* Have plaintext orginal */ - set_cli_session_key(cli, session_key); - set_signing_on_cli(cli, session_key.data, nt_response); + set_signing_on_cli(cli, pass, ntpword); } - -end: - data_blob_free(&lm_response); - data_blob_free(&nt_response); - data_blob_free(&session_key); + return True; } @@ -392,9 +359,11 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob) { uint32 capabilities = cli_session_setup_capabilities(cli); char *p; - DATA_BLOB blob2 = data_blob(NULL, 0); + DATA_BLOB blob2; uint32 len; + blob2 = data_blob(NULL, 0); + capabilities |= CAP_EXTENDED_SECURITY; /* send a session setup command */ @@ -451,13 +420,6 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob) #ifdef HAVE_KRB5 /**************************************************************************** - Use in-memory credentials cache -****************************************************************************/ -static void use_in_memory_ccache() { - setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1); -} - -/**************************************************************************** Do a spnego/kerberos encrypted session setup. ****************************************************************************/ @@ -494,87 +456,126 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *princi static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, const char *pass, const char *workgroup) { - struct ntlmssp_client_state *ntlmssp_state; - NTSTATUS nt_status; - int turn = 1; - DATA_BLOB msg1; - DATA_BLOB blob; - DATA_BLOB blob_in = data_blob(NULL, 0); - DATA_BLOB blob_out; + DATA_BLOB msg1, struct_blob; + DATA_BLOB blob, chal1, chal2, auth, challenge_blob; + uint8 challenge[8]; + uint8 nthash[24], lmhash[24], sess_key[16]; + uint32 neg_flags, chal_flags, ntlmssp_command, unkn1, unkn2; + pstring server_domain; /* FIX THIS, SHOULD be UCS2-LE */ + + neg_flags = NTLMSSP_NEGOTIATE_UNICODE | + NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_REQUEST_TARGET; + + memset(sess_key, 0, 16); + + DEBUG(10, ("sending NTLMSSP_NEGOTIATE\n")); + + /* generate the ntlmssp negotiate packet */ + msrpc_gen(&blob, "CddAA", + "NTLMSSP", + NTLMSSP_NEGOTIATE, + neg_flags, + workgroup, + cli->calling.name); + DEBUG(10, ("neg_flags: %0X, workgroup: %s, calling name %s\n", + neg_flags, workgroup, cli->calling.name)); + /* and wrap it in a SPNEGO wrapper */ + msg1 = gen_negTokenInit(OID_NTLMSSP, blob); + data_blob_free(&blob); - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) { + /* now send that blob on its way */ + blob = cli_session_setup_blob(cli, msg1); + + data_blob_free(&msg1); + + if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED)) return False; - } - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) { +#if 0 + file_save("chal.dat", blob.data, blob.length); +#endif + + /* the server gives us back two challenges */ + if (!spnego_parse_challenge(blob, &chal1, &chal2)) { + DEBUG(3,("Failed to parse challenges\n")); return False; } - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, workgroup))) { - return False; + + data_blob_free(&blob); + + /* + * Ok, chal1 and chal2 are actually two identical copies of + * the NTLMSSP Challenge BLOB, and they contain, encoded in them + * the challenge to use. + */ + + if (!msrpc_parse(&chal1, "CdUdbddB", + "NTLMSSP", + &ntlmssp_command, + &server_domain, + &chal_flags, + &challenge_blob, 8, + &unkn1, &unkn2, + &struct_blob)) { + DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n")); + return False; } - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) { + + if (ntlmssp_command != NTLMSSP_CHALLENGE) { + DEBUG(0, ("NTLMSSP Response != NTLMSSP_CHALLENGE. Got %0X\n", + ntlmssp_command)); return False; } + + DEBUG(10, ("Challenge:\n")); + dump_data(10, challenge_blob.data, 8); - ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth(); - - do { - nt_status = ntlmssp_client_update(ntlmssp_state, - blob_in, &blob_out); - data_blob_free(&blob_in); - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - if (turn == 1) { - /* and wrap it in a SPNEGO wrapper */ - msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out); - } else { - /* wrap it in SPNEGO */ - msg1 = spnego_gen_auth(blob_out); - } - - /* now send that blob on its way */ - blob = cli_session_setup_blob(cli, msg1); - data_blob_free(&msg1); - nt_status = cli_nt_error(cli); - } - - if (!blob.length) { - if (NT_STATUS_IS_OK(nt_status)) { - nt_status = NT_STATUS_UNSUCCESSFUL; - } - } else if ((turn == 1) && - NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - DATA_BLOB tmp_blob = data_blob(NULL, 0); - /* the server might give us back two challenges */ - if (!spnego_parse_challenge(blob, &blob_in, - &tmp_blob)) { - DEBUG(3,("Failed to parse challenges\n")); - nt_status = NT_STATUS_INVALID_PARAMETER; - } - data_blob_free(&tmp_blob); - } else { - /* the server might give us back two challenges */ - if (!spnego_parse_auth_response(blob, nt_status, - &blob_in)) { - DEBUG(3,("Failed to parse auth response\n")); - if (NT_STATUS_IS_OK(nt_status) - || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) - nt_status = NT_STATUS_INVALID_PARAMETER; - } - } - data_blob_free(&blob); - data_blob_free(&blob_out); - turn++; - } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)); + /* encrypt the password with the challenge which is in the blob */ + memcpy(challenge, challenge_blob.data, 8); + SMBencrypt(pass, challenge,lmhash); + SMBNTencrypt(pass, challenge,nthash); + data_blob_free(&challenge_blob); - if (NT_STATUS_IS_OK(nt_status)) { - set_cli_session_key(cli, ntlmssp_state->session_key); - } +#if 0 + file_save("nthash.dat", nthash, 24); + file_save("lmhash.dat", lmhash, 24); + file_save("chal1.dat", chal1.data, chal1.length); +#endif + + data_blob_free(&chal1); + data_blob_free(&chal2); + + /* this generates the actual auth packet */ + msrpc_gen(&blob, "CdBBUUUBd", + "NTLMSSP", + NTLMSSP_AUTH, + lmhash, 24, + nthash, 24, + workgroup, + user, + cli->calling.name, + sess_key, 0, + neg_flags); + + /* wrap it in SPNEGO */ + auth = spnego_gen_auth(blob); + + data_blob_free(&blob); - if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) { + /* now send the auth packet and we should be done */ + blob = cli_session_setup_blob(cli, auth); + + data_blob_free(&auth); + data_blob_free(&blob); + + if (cli_is_error(cli)) return False; - } - return (NT_STATUS_IS_OK(nt_status)); + set_signing_on_cli(cli, pass, nthash); + + return True; } /**************************************************************************** @@ -627,21 +628,6 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, fstrcpy(cli->user_name, user); #ifdef HAVE_KRB5 - /* If password is set we reauthenticate to kerberos server - * and do not store results */ - - if (*pass) { - int ret; - - use_in_memory_ccache(); - ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */); - - if (ret){ - DEBUG(0, ("Kinit failed: %s\n", error_message(ret))); - return False; - } - } - if (got_kerberos_mechanism && cli->use_kerberos) { return cli_session_setup_kerberos(cli, principal, workgroup); } @@ -956,10 +942,7 @@ BOOL cli_negprot(struct cli_state *cli) smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN); } - if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) - cli->sign_info.negotiated_smb_signing = True; - - if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing) + if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) cli->sign_info.negotiated_smb_signing = True; } else if (cli->protocol >= PROTOCOL_LANMAN1) { |