Index: libsmb/clientgen.c =================================================================== --- libsmb/clientgen.c (revision 21402) +++ libsmb/clientgen.c (working copy) @@ -116,7 +116,7 @@ return ret; } - if (!cli_check_sign_mac(cli)) { + if (cli->key_exchange_complete && !cli_check_sign_mac(cli)) { DEBUG(0, ("SMB Signature verification failed on incoming packet!\n")); cli->smb_rw_error = READ_BAD_SIG; close(cli->fd); @@ -155,7 +155,8 @@ if (cli->fd == -1) return False; - cli_calculate_sign_mac(cli); + if (cli->key_exchange_complete) + cli_calculate_sign_mac(cli); len = smb_len(cli->outbuf) + 4; @@ -293,6 +294,7 @@ cli->smb_rw_error = 0; cli->use_spnego = lp_client_use_spnego(); + cli->key_exchange_complete = True; cli->capabilities = CAP_UNICODE | CAP_STATUS32 | CAP_DFS; Index: libsmb/cliconnect.c =================================================================== --- libsmb/cliconnect.c (revision 21402) +++ libsmb/cliconnect.c (working copy) @@ -517,19 +517,56 @@ } #ifdef HAVE_KRB5 - /**************************************************************************** Send a extended security session setup blob, returning a reply blob. ****************************************************************************/ -static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob) +#define MAX_SESSION_SECURITY_BLOB 4000 + +static BOOL cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob) { - DATA_BLOB blob2 = data_blob(NULL, 0); - if (!cli_session_setup_blob_send(cli, blob)) { - return blob2; + int32 remaining = blob.length; + int32 cur = 0; + DATA_BLOB send_blob = data_blob(NULL, 0); + + while ( remaining > 0) { + + if (remaining >= MAX_SESSION_SECURITY_BLOB) { + send_blob.length = MAX_SESSION_SECURITY_BLOB; + cli->key_exchange_complete = False; + remaining -= MAX_SESSION_SECURITY_BLOB; + + } else { + send_blob.length = remaining; + cli->key_exchange_complete = True; + remaining = 0; + } + + send_blob.data = &blob.data[cur]; + cur += send_blob.length; + + DEBUG(10, ("Remaining (%d) sending (%d) current (%d) - %p\n", + remaining, send_blob.length, cur, send_blob.data)); + + if (!cli_session_setup_blob_send(cli, send_blob)) { + DEBUG(0, ("cli_session_setup_blob: send failed\n")); + return False; + } + + cli_session_setup_blob_receive(cli); + + if (cli_is_error(cli) && + !NT_STATUS_EQUAL( cli_get_nt_error(cli), + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + + DEBUG(0, ("cli_session_setup_blob: recieve failed \n")); + return False; + } } + + + return True; - return cli_session_setup_blob_receive(cli); } /**************************************************************************** @@ -546,9 +583,10 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup) { - DATA_BLOB blob2, negTokenTarg; + DATA_BLOB negTokenTarg; DATA_BLOB session_key_krb5; DATA_BLOB null_blob = data_blob(NULL, 0); + BOOL fProcessed = False; int rc; DEBUG(2,("Doing kerberos session setup\n")); @@ -567,17 +605,14 @@ cli_simple_set_signing(cli, session_key_krb5, null_blob); - blob2 = cli_session_setup_blob(cli, negTokenTarg); + fProcessed = cli_session_setup_blob(cli, negTokenTarg); - /* we don't need this blob for kerberos */ - data_blob_free(&blob2); - cli_set_session_key(cli, session_key_krb5); data_blob_free(&negTokenTarg); data_blob_free(&session_key_krb5); - if (cli_is_error(cli)) { + if (cli_is_error(cli) || fProcessed) { if (NT_STATUS_IS_OK(cli_nt_error(cli))) { return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); } Index: include/client.h =================================================================== --- include/client.h (revision 21402) +++ include/client.h (working copy) @@ -162,6 +162,7 @@ BOOL use_kerberos; BOOL fallback_after_kerberos; BOOL use_spnego; + BOOL key_exchange_complete; BOOL use_oplocks; /* should we use oplocks? */ BOOL use_level_II_oplocks; /* should we use level II oplocks? */