svn commit: samba r21576 - in branches: SAMBA_3_0/source/libsmb SAMBA_3_0_25/source/libsmb

jra at samba.org jra at samba.org
Wed Feb 28 00:36:00 GMT 2007


Author: jra
Date: 2007-02-28 00:35:58 +0000 (Wed, 28 Feb 2007)
New Revision: 21576

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=21576

Log:
Patch based on work from Todd Stecher <todd.stecher at isilon.com>
to allow client to fragment large SPNEGO blobs (large krb5
tickets). Tested against W2K3R2. Should fix bug #4400.
Jeremy.

Modified:
   branches/SAMBA_3_0/source/libsmb/cliconnect.c
   branches/SAMBA_3_0/source/libsmb/clierror.c
   branches/SAMBA_3_0_25/source/libsmb/cliconnect.c
   branches/SAMBA_3_0_25/source/libsmb/clierror.c


Changeset:
Modified: branches/SAMBA_3_0/source/libsmb/cliconnect.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/cliconnect.c	2007-02-28 00:35:21 UTC (rev 21575)
+++ branches/SAMBA_3_0/source/libsmb/cliconnect.c	2007-02-28 00:35:58 UTC (rev 21576)
@@ -517,19 +517,78 @@
 }
 
 #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 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 @@
 	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,13 +624,12 @@
 	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);
+	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));
+	}
 
-	/* we don't need this blob for kerberos */
-	data_blob_free(&blob2);
-
 	cli_set_session_key(cli, session_key_krb5);
 
 	data_blob_free(&negTokenTarg);

Modified: branches/SAMBA_3_0/source/libsmb/clierror.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/clierror.c	2007-02-28 00:35:21 UTC (rev 21575)
+++ branches/SAMBA_3_0/source/libsmb/clierror.c	2007-02-28 00:35:58 UTC (rev 21576)
@@ -451,3 +451,12 @@
 		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));
+}

Modified: branches/SAMBA_3_0_25/source/libsmb/cliconnect.c
===================================================================
--- branches/SAMBA_3_0_25/source/libsmb/cliconnect.c	2007-02-28 00:35:21 UTC (rev 21575)
+++ branches/SAMBA_3_0_25/source/libsmb/cliconnect.c	2007-02-28 00:35:58 UTC (rev 21576)
@@ -517,19 +517,78 @@
 }
 
 #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 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 @@
 	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,13 +624,12 @@
 	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);
+	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));
+	}
 
-	/* we don't need this blob for kerberos */
-	data_blob_free(&blob2);
-
 	cli_set_session_key(cli, session_key_krb5);
 
 	data_blob_free(&negTokenTarg);

Modified: branches/SAMBA_3_0_25/source/libsmb/clierror.c
===================================================================
--- branches/SAMBA_3_0_25/source/libsmb/clierror.c	2007-02-28 00:35:21 UTC (rev 21575)
+++ branches/SAMBA_3_0_25/source/libsmb/clierror.c	2007-02-28 00:35:58 UTC (rev 21576)
@@ -451,3 +451,12 @@
 		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));
+}



More information about the samba-cvs mailing list