svn commit: samba r23923 - in branches/SAMBA_3_2_0/source: include libads

metze at samba.org metze at samba.org
Tue Jul 17 10:14:16 GMT 2007


Author: metze
Date: 2007-07-17 10:14:15 +0000 (Tue, 17 Jul 2007)
New Revision: 23923

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

Log:
merge from SAMBA_3_2:
implement buffer handling for the SASL read wrapper

metze
Modified:
   branches/SAMBA_3_2_0/source/include/ads.h
   branches/SAMBA_3_2_0/source/libads/sasl_wrapping.c


Changeset:
Modified: branches/SAMBA_3_2_0/source/include/ads.h
===================================================================
--- branches/SAMBA_3_2_0/source/include/ads.h	2007-07-17 10:13:53 UTC (rev 23922)
+++ branches/SAMBA_3_2_0/source/include/ads.h	2007-07-17 10:14:15 UTC (rev 23923)
@@ -15,7 +15,31 @@
 	WB_POSIX_MAP_UNIXINFO	= 4
 };
 
-typedef struct {	
+/* there are 5 possible types of errors the ads subsystem can produce */
+enum ads_error_type {ENUM_ADS_ERROR_KRB5, ENUM_ADS_ERROR_GSS, 
+		     ENUM_ADS_ERROR_LDAP, ENUM_ADS_ERROR_SYSTEM, ENUM_ADS_ERROR_NT};
+
+typedef struct {
+	enum ads_error_type error_type;
+	union err_state{		
+		int rc;
+		NTSTATUS nt_status;
+	} err;
+	/* For error_type = ENUM_ADS_ERROR_GSS minor_status describe GSS API error */
+	/* Where rc represents major_status of GSS API error */
+	int minor_status;
+} ADS_STATUS;
+
+struct ads_struct;
+
+struct ads_saslwrap_ops {
+	const char *name;
+	ADS_STATUS (*wrap)(struct ads_struct *);
+	ADS_STATUS (*unwrap)(struct ads_struct *);
+	ADS_STATUS (*disconnect)(struct ads_struct *);
+};
+
+typedef struct ads_struct {
 	int is_mine;	/* do I own this structure's memory? */
 	
 	/* info needed to find the server */
@@ -63,6 +87,27 @@
 
 #ifdef HAVE_LDAP_SASL_WRAPPING
 		Sockbuf_IO_Desc *sbiod; /* lowlevel state for LDAP wrapping */
+		TALLOC_CTX *mem_ctx;
+		const struct ads_saslwrap_ops *wrap_ops;
+		void *wrap_private_data;
+		struct {
+			uint32 ofs;
+			uint32 needed;
+			uint32 left;
+			uint32 max;
+			uint32 min;
+			uint32 size;
+			uint8 *buf;
+		} in;
+		struct {
+			uint32 ofs;
+			uint32 needed;
+			uint32 left;
+			uint32 max;
+			uint32 min;
+			uint32 size;
+			uint8 *buf;
+		} out;
 #endif /* HAVE_LDAP_SASL_WRAPPING */
 	} ldap;
 #endif /* HAVE_LDAP */
@@ -80,21 +125,7 @@
 };
 
 
-/* there are 5 possible types of errors the ads subsystem can produce */
-enum ads_error_type {ENUM_ADS_ERROR_KRB5, ENUM_ADS_ERROR_GSS, 
-		     ENUM_ADS_ERROR_LDAP, ENUM_ADS_ERROR_SYSTEM, ENUM_ADS_ERROR_NT};
 
-typedef struct {
-	enum ads_error_type error_type;
-	union err_state{		
-		int rc;
-		NTSTATUS nt_status;
-	} err;
-	/* For error_type = ENUM_ADS_ERROR_GSS minor_status describe GSS API error */
-	/* Where rc represents major_status of GSS API error */
-	int minor_status;
-} ADS_STATUS;
-
 #ifdef HAVE_ADS
 typedef LDAPMod **ADS_MODLIST;
 #else

Modified: branches/SAMBA_3_2_0/source/libads/sasl_wrapping.c
===================================================================
--- branches/SAMBA_3_2_0/source/libads/sasl_wrapping.c	2007-07-17 10:13:53 UTC (rev 23922)
+++ branches/SAMBA_3_2_0/source/libads/sasl_wrapping.c	2007-07-17 10:14:15 UTC (rev 23923)
@@ -37,9 +37,137 @@
 	return 0;
 }
 
+static ber_slen_t ads_saslwrap_prepare_inbuf(ADS_STRUCT *ads)
+{
+	ads->ldap.in.ofs	= 0;
+	ads->ldap.in.needed	= 0;
+	ads->ldap.in.left	= 0;
+	ads->ldap.in.size	= 4 + ads->ldap.in.min;
+	ads->ldap.in.buf	= talloc_array(ads->ldap.mem_ctx,
+					       uint8, ads->ldap.in.size);
+	if (!ads->ldap.in.buf) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static ber_slen_t ads_saslwrap_grow_inbuf(ADS_STRUCT *ads)
+{
+	if (ads->ldap.in.size == (4 + ads->ldap.in.needed)) {
+		return 0;
+	}
+
+	ads->ldap.in.size	= 4 + ads->ldap.in.needed;
+	ads->ldap.in.buf	= talloc_realloc(ads->ldap.mem_ctx,
+						 ads->ldap.in.buf,
+						 uint8, ads->ldap.in.size);
+	if (!ads->ldap.in.buf) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static void ads_saslwrap_shrink_inbuf(ADS_STRUCT *ads)
+{
+	talloc_free(ads->ldap.in.buf);
+
+	ads->ldap.in.buf	= NULL;
+	ads->ldap.in.size	= 0;
+	ads->ldap.in.ofs	= 0;
+	ads->ldap.in.needed	= 0;
+	ads->ldap.in.left	= 0;
+}
+
 static ber_slen_t ads_saslwrap_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
 {
-	return LBER_SBIOD_READ_NEXT(sbiod, buf, len);
+	ADS_STRUCT *ads = (ADS_STRUCT *)sbiod->sbiod_pvt;
+	ber_slen_t ret;
+
+	/* If ofs < 4 it means we don't have read the length header yet */
+	if (ads->ldap.in.ofs < 4) {
+		ret = ads_saslwrap_prepare_inbuf(ads);
+		if (ret < 0) return ret;
+
+		ret = LBER_SBIOD_READ_NEXT(sbiod,
+					   ads->ldap.in.buf + ads->ldap.in.ofs,
+					   4 - ads->ldap.in.ofs);
+		if (ret < 0) return ret;
+		ads->ldap.in.ofs += ret;
+
+		if (ads->ldap.in.ofs < 4) goto eagain;
+
+		ads->ldap.in.needed = RIVAL(ads->ldap.in.buf, 4);
+		if (ads->ldap.in.needed > ads->ldap.in.max) {
+			errno = EINVAL;
+			return -1;
+		}
+		if (ads->ldap.in.needed < ads->ldap.in.min) {
+			errno = EINVAL;
+			return -1;
+		}
+
+		ret = ads_saslwrap_grow_inbuf(ads);
+		if (ret < 0) return ret;
+	}
+
+	/*
+	 * if there's more data needed from the remote end,
+	 * we need to read more
+	 */
+	if (ads->ldap.in.needed > 0) {
+		ret = LBER_SBIOD_READ_NEXT(sbiod,
+					   ads->ldap.in.buf + ads->ldap.in.ofs,
+					   ads->ldap.in.needed);
+		if (ret < 0) return ret;
+		ads->ldap.in.ofs += ret;
+		ads->ldap.in.needed -= ret;
+
+		if (ads->ldap.in.needed > 0) goto eagain;
+	}
+
+	/*
+	 * if we have a complete packet and have not yet unwrapped it
+	 * we need to call the mech specific unwrap() hook
+	 */
+	if (ads->ldap.in.needed == 0 && ads->ldap.in.left == 0) {
+		ADS_STATUS status;
+		status = ads->ldap.wrap_ops->unwrap(ads);
+		if (!ADS_ERR_OK(status)) {
+			errno = EACCES;
+			return -1;
+		}
+	}
+
+	/*
+	 * if we have unwrapped data give it to the caller
+	 */
+	if (ads->ldap.in.left > 0) {
+		ret = MIN(ads->ldap.in.left, len);
+		memcpy(buf, ads->ldap.in.buf + ads->ldap.in.ofs, ret);
+		ads->ldap.in.ofs += ret;
+		ads->ldap.in.left -= ret;
+
+		/*
+		 * if no more is left shrink the inbuf,
+		 * this will trigger reading a new SASL packet
+		 * from the remote stream in the next call
+		 */
+		if (ads->ldap.in.left == 0) {
+			ads_saslwrap_shrink_inbuf(ads);
+		}
+
+		return ret;
+	}
+
+	/*
+	 * if we don't have anything for the caller yet,
+	 * tell him to ask again
+	 */
+eagain:
+	errno = EAGAIN;
+	return -1;
 }
 
 static ber_slen_t ads_saslwrap_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
@@ -47,7 +175,6 @@
 	return LBER_SBIOD_WRITE_NEXT(sbiod, buf, len);
 }
 
-
 static int ads_saslwrap_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
 {
 	return LBER_SBIOD_CTRL_NEXT(sbiod, opt, arg);



More information about the samba-cvs mailing list