svn commit: samba r23946 - in branches/SAMBA_3_2/source: include libads

metze at samba.org metze at samba.org
Wed Jul 18 08:15:46 GMT 2007


Author: metze
Date: 2007-07-18 08:15:42 +0000 (Wed, 18 Jul 2007)
New Revision: 23946

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

Log:
add support for NTLMSSP sign and seal

NOTE: windows servers are broken with sign only...

metze
Modified:
   branches/SAMBA_3_2/source/include/ads.h
   branches/SAMBA_3_2/source/libads/sasl.c


Changeset:
Modified: branches/SAMBA_3_2/source/include/ads.h
===================================================================
--- branches/SAMBA_3_2/source/include/ads.h	2007-07-18 07:45:16 UTC (rev 23945)
+++ branches/SAMBA_3_2/source/include/ads.h	2007-07-18 08:15:42 UTC (rev 23946)
@@ -36,7 +36,7 @@
 	const char *name;
 	ADS_STATUS (*wrap)(struct ads_struct *, uint8 *buf, uint32 len);
 	ADS_STATUS (*unwrap)(struct ads_struct *);
-	ADS_STATUS (*disconnect)(struct ads_struct *);
+	void (*disconnect)(struct ads_struct *);
 };
 
 enum ads_saslwrap_type {

Modified: branches/SAMBA_3_2/source/libads/sasl.c
===================================================================
--- branches/SAMBA_3_2/source/libads/sasl.c	2007-07-18 07:45:16 UTC (rev 23945)
+++ branches/SAMBA_3_2/source/libads/sasl.c	2007-07-18 08:15:42 UTC (rev 23946)
@@ -21,6 +21,95 @@
 
 #ifdef HAVE_LDAP
 
+static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
+{
+	struct ntlmssp_state *ntlmssp_state = ads->ldap.wrap_private_data;
+	ADS_STATUS status;
+	NTSTATUS nt_status;
+	DATA_BLOB sig;
+	uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE);
+
+	/* copy the data to the right location */
+	memcpy(dptr, buf, len);
+
+	/* create the signature and may encrypt the data */
+	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+		nt_status = ntlmssp_seal_packet(ntlmssp_state,
+						dptr, len,
+						dptr, len,
+						&sig);
+	} else {
+		nt_status = ntlmssp_sign_packet(ntlmssp_state,
+						dptr, len,
+						dptr, len,
+						&sig);
+	}
+	status = ADS_ERROR_NT(nt_status);
+	if (!ADS_ERR_OK(status)) return status;
+
+	/* copy the signature to the right location */
+	memcpy(ads->ldap.out.buf + 4,
+	       sig.data, NTLMSSP_SIG_SIZE);
+
+	data_blob_free(&sig);
+
+	/* set how many bytes must be written to the underlying socket */
+	ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
+
+	return ADS_SUCCESS;
+}
+
+static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
+{
+	struct ntlmssp_state *ntlmssp_state = ads->ldap.wrap_private_data;
+	ADS_STATUS status;
+	NTSTATUS nt_status;
+	DATA_BLOB sig;
+	uint8 *dptr = ads->ldap.in.buf + (4 + NTLMSSP_SIG_SIZE);
+	uint32 dlen = ads->ldap.in.ofs - (4 + NTLMSSP_SIG_SIZE);
+
+	/* wrap the signature into a DATA_BLOB */
+	sig = data_blob_const(ads->ldap.in.buf + 4, NTLMSSP_SIG_SIZE);
+
+	/* verify the signature and maybe decrypt the data */
+	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+		nt_status = ntlmssp_unseal_packet(ntlmssp_state,
+						  dptr, dlen,
+						  dptr, dlen,
+						  &sig);
+	} else {
+		nt_status = ntlmssp_check_packet(ntlmssp_state,
+						 dptr, dlen,
+						 dptr, dlen,
+						 &sig);
+	}
+	status = ADS_ERROR_NT(nt_status);
+	if (!ADS_ERR_OK(status)) return status;
+
+	/* set the amount of bytes for the upper layer and set the ofs to the data */
+	ads->ldap.in.left	= dlen;
+	ads->ldap.in.ofs	= 4 + NTLMSSP_SIG_SIZE;
+
+	return ADS_SUCCESS;
+}
+
+static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
+{
+	struct ntlmssp_state *ntlmssp_state = ads->ldap.wrap_private_data;
+
+	ntlmssp_end(&ntlmssp_state);
+
+	ads->ldap.wrap_ops = NULL;
+	ads->ldap.wrap_private_data = NULL;
+}
+
+static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops = {
+	.name		= "ntlmssp",
+	.wrap		= ads_sasl_ntlmssp_wrap,
+	.unwrap		= ads_sasl_ntlmssp_unwrap,
+	.disconnect	= ads_sasl_ntlmssp_disconnect
+};
+
 /* 
    perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
    we fit on one socket??)
@@ -35,6 +124,7 @@
 	int rc;
 	NTSTATUS nt_status;
 	int turn = 1;
+	uint32 features = 0;
 
 	struct ntlmssp_state *ntlmssp_state;
 
@@ -53,6 +143,28 @@
 		return ADS_ERROR_NT(nt_status);
 	}
 
+	switch (ads->ldap.wrap_type) {
+	case ADS_SASLWRAP_TYPE_SEAL:
+		features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
+		break;
+	case ADS_SASLWRAP_TYPE_SIGN:
+		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
+			features = NTLMSSP_FEATURE_SIGN;
+		} else {
+			/*
+			 * windows servers are broken with sign only,
+			 * so we need to use seal here too
+			 */
+			features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
+			ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
+		}
+		break;
+	case ADS_SASLWRAP_TYPE_PLAIN:
+		break;
+	}
+
+	ntlmssp_want_feature(ntlmssp_state, features);
+
 	blob_in = data_blob_null;
 
 	do {
@@ -130,7 +242,16 @@
 	/* we have a reference conter on ntlmssp_state, if we are signing
 	   then the state will be kept by the signing engine */
 
-	ntlmssp_end(&ntlmssp_state);
+	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
+		ads->ldap.out.min = 4;
+		ads->ldap.out.max = 0x0FFFFFFF - NTLMSSP_SIG_SIZE;
+		ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
+		ads->ldap.in.min = 4;
+		ads->ldap.in.max = 0x0FFFFFFF;
+		ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
+	} else {
+		ntlmssp_end(&ntlmssp_state);
+	}
 
 	return ADS_ERROR(rc);
 }



More information about the samba-cvs mailing list