summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-02-28 00:35:58 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:18:14 -0500
commit3e12cf85ace31638d2dd924cc202c9d2f31f7890 (patch)
treeeffd0289d7a44eaa11581f5603b857aecf717cde
parent8c5846acf241307ebd82b41fd454f0f50825a37a (diff)
downloadsamba-3e12cf85ace31638d2dd924cc202c9d2f31f7890.tar.gz
samba-3e12cf85ace31638d2dd924cc202c9d2f31f7890.tar.bz2
samba-3e12cf85ace31638d2dd924cc202c9d2f31f7890.zip
r21576: Patch based on work from Todd Stecher <todd.stecher@isilon.com>
to allow client to fragment large SPNEGO blobs (large krb5 tickets). Tested against W2K3R2. Should fix bug #4400. Jeremy. (This used to be commit b81c5c6adce51cec06df0e993534064b20666a8e)
-rw-r--r--source3/libsmb/cliconnect.c90
-rw-r--r--source3/libsmb/clierror.c9
2 files changed, 83 insertions, 16 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 2742d70194..886f19b3df 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -517,19 +517,78 @@ static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
}
#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
+
+/* The following is calculated from :
+ * (smb_size-4) = 35
+ * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
+ * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
+ * end of packet.
+ */
+
+#define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
+
+static BOOL cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob, DATA_BLOB session_key_krb5)
{
- 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);
+ int32 max_blob_size = 0;
+
+ if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
+ DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
+ "(was %u, need minimum %u)\n",
+ (unsigned int)cli->max_xmit,
+ BASE_SESSSETUP_BLOB_PACKET_SIZE));
+ cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
+ return False;
}
-
- return cli_session_setup_blob_receive(cli);
+
+ max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
+
+ while ( remaining > 0) {
+ if (remaining >= max_blob_size) {
+ send_blob.length = max_blob_size;
+ remaining -= max_blob_size;
+ } else {
+ DATA_BLOB null_blob = data_blob(NULL, 0);
+
+ send_blob.length = remaining;
+ remaining = 0;
+
+ /* This is the last packet in the sequence - turn signing on. */
+ cli_simple_set_signing(cli, session_key_krb5, null_blob);
+ }
+
+ send_blob.data = &blob.data[cur];
+ cur += send_blob.length;
+
+ DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
+ (unsigned int)remaining,
+ (unsigned int)send_blob.length,
+ (unsigned int)cur ));
+
+ 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 (%s)\n",
+ nt_errstr(cli_get_nt_error(cli)) ));
+ return False;
+ }
+ }
+
+ return True;
}
/****************************************************************************
@@ -546,9 +605,8 @@ static void use_in_memory_ccache(void) {
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);
int rc;
DEBUG(2,("Doing kerberos session setup\n"));
@@ -557,7 +615,8 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *
rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
if (rc) {
- DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));
+ DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
+ error_message(rc)));
return ADS_ERROR_KRB5(rc);
}
@@ -565,12 +624,11 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *
file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
#endif
- cli_simple_set_signing(cli, session_key_krb5, null_blob);
-
- blob2 = cli_session_setup_blob(cli, negTokenTarg);
-
- /* we don't need this blob for kerberos */
- data_blob_free(&blob2);
+ if (!cli_session_setup_blob(cli, negTokenTarg, session_key_krb5)) {
+ data_blob_free(&negTokenTarg);
+ data_blob_free(&session_key_krb5);
+ ADS_ERROR_NT(cli_nt_error(cli));
+ }
cli_set_session_key(cli, session_key_krb5);
diff --git a/source3/libsmb/clierror.c b/source3/libsmb/clierror.c
index fcedc3bdab..f85fc5c552 100644
--- a/source3/libsmb/clierror.c
+++ b/source3/libsmb/clierror.c
@@ -451,3 +451,12 @@ NTSTATUS cli_get_nt_error(struct cli_state *cli)
return NT_STATUS_UNSUCCESSFUL;
}
}
+
+/* Push an error code into the inbuf to be returned on the next
+ * query. */
+
+void cli_set_nt_error(struct cli_state *cli, NTSTATUS status)
+{
+ SSVAL(cli->inbuf,smb_flg2, SVAL(cli->inbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES);
+ SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status));
+}