[PATCH] asn1_XXXX error check fixups.

Jeremy Allison jra at samba.org
Fri Sep 19 17:01:56 MDT 2014


Here are more fixes to ensure we *always*
check asn1_XXX() returns, as discovered
at SNIA-SDC.

Only two modules left to do:

libcli/ldap/ldap_message.c
source4/libcli/ldap/ldap_controls.c

and then we'll have full coverage here.
I'll try and get to those next week !

Review and possibly push appreciated.

Cheers,

	Jeremy.
-------------- next part --------------
From d7786641933874a53f5e77f13f11f9210f40fabf Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 19 Sep 2014 12:39:19 -0700
Subject: [PATCH 1/8] lib: util: asn1 fixes - check all returns.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 lib/krb5_wrap/krb5_samba.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c
index 39926a6..5f0378b 100644
--- a/lib/krb5_wrap/krb5_samba.c
+++ b/lib/krb5_wrap/krb5_samba.c
@@ -296,23 +296,22 @@ bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx,
 		return false;
 	}
 
-	asn1_load(data, *edata);
-	asn1_start_tag(data, ASN1_SEQUENCE(0));
-	asn1_start_tag(data, ASN1_CONTEXT(1));
-	asn1_read_Integer(data, &edata_type);
+	if (!asn1_load(data, *edata)) goto err;
+	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto err;
+	if (!asn1_start_tag(data, ASN1_CONTEXT(1))) goto err;
+	if (!asn1_read_Integer(data, &edata_type)) goto err;
 
 	if (edata_type != KRB5_PADATA_PW_SALT) {
 		DEBUG(0,("edata is not of required type %d but of type %d\n",
 			KRB5_PADATA_PW_SALT, edata_type));
-		asn1_free(data);
-		return false;
+		goto err;
 	}
 
-	asn1_start_tag(data, ASN1_CONTEXT(2));
-	asn1_read_OctetString(data, talloc_tos(), &edata_contents);
-	asn1_end_tag(data);
-	asn1_end_tag(data);
-	asn1_end_tag(data);
+	if (!asn1_start_tag(data, ASN1_CONTEXT(2))) goto err;
+	if (!asn1_read_OctetString(data, talloc_tos(), &edata_contents)) goto err;
+	if (!asn1_end_tag(data)) goto err;
+	if (!asn1_end_tag(data)) goto err;
+	if (!asn1_end_tag(data)) goto err;
 	asn1_free(data);
 
 	*edata_out = data_blob_talloc(mem_ctx, edata_contents.data, edata_contents.length);
@@ -320,6 +319,11 @@ bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx,
 	data_blob_free(&edata_contents);
 
 	return true;
+
+  err:
+
+	asn1_free(data);
+	return false;
 }
 
 
-- 
2.1.0.rc2.206.gedb03e5


From 656df7171c6631113506fb51977f3ef9656ef579 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 19 Sep 2014 12:41:22 -0700
Subject: [PATCH 2/8] auth: gensec: asn1 fixes - check all returns.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 auth/gensec/gensec_util.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c
index 568128a..b8e38b7 100644
--- a/auth/gensec/gensec_util.c
+++ b/auth/gensec/gensec_util.c
@@ -188,19 +188,20 @@ NTSTATUS gensec_packet_full_request(struct gensec_security *gensec_security,
 */
 static bool gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
 {
-	bool ret;
+	bool ret = false;
 	struct asn1_data *data = asn1_init(NULL);
 
 	if (!data) return false;
 
-	asn1_load(data, *blob);
-	asn1_start_tag(data, ASN1_APPLICATION(0));
-	asn1_check_OID(data, oid);
+	if (!asn1_load(data, *blob)) goto err;
+	if (!asn1_start_tag(data, ASN1_APPLICATION(0))) goto err;
+	if (!asn1_check_OID(data, oid)) goto err;
 
 	ret = !data->has_error;
 
-	asn1_free(data);
+  err:
 
+	asn1_free(data);
 	return ret;
 }
 
-- 
2.1.0.rc2.206.gedb03e5


From a51a49ee54897d44a10e2eff0d5727bfd6189bac Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 19 Sep 2014 12:46:49 -0700
Subject: [PATCH 3/8] lib: util: asn1 tests. Check every asn1 return.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 lib/util/tests/asn1_tests.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/lib/util/tests/asn1_tests.c b/lib/util/tests/asn1_tests.c
index 93ffbad..2c68cb4 100644
--- a/lib/util/tests/asn1_tests.c
+++ b/lib/util/tests/asn1_tests.c
@@ -321,6 +321,7 @@ static bool test_asn1_Integer(struct torture_context *tctx)
 {
 	int i;
 	TALLOC_CTX *mem_ctx;
+	bool ret = false;
 
 	mem_ctx = talloc_new(tctx);
 
@@ -331,25 +332,28 @@ static bool test_asn1_Integer(struct torture_context *tctx)
 
 		data = asn1_init(mem_ctx);
 		if (!data) {
-			return -1;
+			goto err;
 		}
 
-		asn1_write_Integer(data, integer_tests[i].value);
+		if (!asn1_write_Integer(data, integer_tests[i].value)) goto err;
 
 		blob.data = data->data;
 		blob.length = data->length;
 		torture_assert_data_blob_equal(tctx, blob, integer_tests[i].blob, "asn1_write_Integer gave incorrect result");
 
-		asn1_load(data, blob);
+		if (!asn1_load(data, blob)) goto err;
 		torture_assert(tctx, asn1_read_Integer(data, &val), "asn1_write_Integer output could not be read by asn1_read_Integer()");
 
 		torture_assert_int_equal(tctx, val, integer_tests[i].value,
 			"readback of asn1_write_Integer output by asn1_read_Integer() failed");
 	}
 
-	talloc_free(mem_ctx);
+	ret = true;
 
-	return true;
+  err:
+
+	talloc_free(mem_ctx);
+	return ret;
 }
 
 
-- 
2.1.0.rc2.206.gedb03e5


From 5e7f03d7f95343ad069c678d963457271508037a Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 19 Sep 2014 13:42:39 -0700
Subject: [PATCH 4/8] libcli: auth: Ensure all asn1_XX returns are checked.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 libcli/auth/spnego_parse.c | 214 ++++++++++++++++++++++++---------------------
 1 file changed, 112 insertions(+), 102 deletions(-)

diff --git a/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c
index b1ca07d..d4c5bdc 100644
--- a/libcli/auth/spnego_parse.c
+++ b/libcli/auth/spnego_parse.c
@@ -29,12 +29,13 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 {
 	ZERO_STRUCTP(token);
 
-	asn1_start_tag(asn1, ASN1_CONTEXT(0));
-	asn1_start_tag(asn1, ASN1_SEQUENCE(0));
+	if (!asn1_start_tag(asn1, ASN1_CONTEXT(0))) return false;
+	if (!asn1_start_tag(asn1, ASN1_SEQUENCE(0))) return false;
 
 	while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
 		int i;
 		uint8_t context;
+
 		if (!asn1_peek_uint8(asn1, &context)) {
 			asn1->has_error = true;
 			break;
@@ -45,8 +46,8 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 		case ASN1_CONTEXT(0): {
 			const char **mechTypes;
 
-			asn1_start_tag(asn1, ASN1_CONTEXT(0));
-			asn1_start_tag(asn1, ASN1_SEQUENCE(0));
+			if (!asn1_start_tag(asn1, ASN1_CONTEXT(0))) return false;
+			if (!asn1_start_tag(asn1, ASN1_SEQUENCE(0))) return false;
 
 			mechTypes = talloc(mem_ctx, const char *);
 			if (mechTypes == NULL) {
@@ -67,7 +68,7 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 				}
 				mechTypes = p;
 
-				asn1_read_OID(asn1, mechTypes, &oid);
+				if (!asn1_read_OID(asn1, mechTypes, &oid)) return false;
 				mechTypes[i] = oid;
 			}
 			mechTypes[i] = NULL;
@@ -79,42 +80,42 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 		}
 		/* Read reqFlags */
 		case ASN1_CONTEXT(1):
-			asn1_start_tag(asn1, ASN1_CONTEXT(1));
-			asn1_read_BitString(asn1, mem_ctx, &token->reqFlags,
-					    &token->reqFlagsPadding);
-			asn1_end_tag(asn1);
+			if (!asn1_start_tag(asn1, ASN1_CONTEXT(1))) return false;
+			if (!asn1_read_BitString(asn1, mem_ctx, &token->reqFlags,
+					    &token->reqFlagsPadding)) return false;
+			if (!asn1_end_tag(asn1)) return false;
 			break;
                 /* Read mechToken */
 		case ASN1_CONTEXT(2):
-			asn1_start_tag(asn1, ASN1_CONTEXT(2));
-			asn1_read_OctetString(asn1, mem_ctx, &token->mechToken);
-			asn1_end_tag(asn1);
+			if (!asn1_start_tag(asn1, ASN1_CONTEXT(2))) return false;
+			if (!asn1_read_OctetString(asn1, mem_ctx, &token->mechToken)) return false;
+			if (!asn1_end_tag(asn1)) return false;
 			break;
 		/* Read mecListMIC */
 		case ASN1_CONTEXT(3):
 		{
 			uint8_t type_peek;
-			asn1_start_tag(asn1, ASN1_CONTEXT(3));
+			if (!asn1_start_tag(asn1, ASN1_CONTEXT(3))) return false;
 			if (!asn1_peek_uint8(asn1, &type_peek)) {
 				asn1->has_error = true;
 				break;
 			}
 			if (type_peek == ASN1_OCTET_STRING) {
-				asn1_read_OctetString(asn1, mem_ctx,
-						      &token->mechListMIC);
+				if (!asn1_read_OctetString(asn1, mem_ctx,
+						      &token->mechListMIC)) return false;
 			} else {
 				/* RFC 2478 says we have an Octet String here,
 				   but W2k sends something different... */
 				char *mechListMIC;
-				asn1_start_tag(asn1, ASN1_SEQUENCE(0));
-				asn1_start_tag(asn1, ASN1_CONTEXT(0));
-				asn1_read_GeneralString(asn1, mem_ctx, &mechListMIC);
-				asn1_end_tag(asn1);
-				asn1_end_tag(asn1);
+				if (!asn1_start_tag(asn1, ASN1_SEQUENCE(0))) return false;
+				if (!asn1_start_tag(asn1, ASN1_CONTEXT(0))) return false;
+				if (!asn1_read_GeneralString(asn1, mem_ctx, &mechListMIC)) return false;
+				if (!asn1_end_tag(asn1)) return false;
+				if (!asn1_end_tag(asn1)) return false;
 
 				token->targetPrincipal = mechListMIC;
 			}
-			asn1_end_tag(asn1);
+			if (!asn1_end_tag(asn1)) return false;
 			break;
 		}
 		default:
@@ -123,50 +124,50 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 		}
 	}
 
-	asn1_end_tag(asn1);
-	asn1_end_tag(asn1);
+	if (!asn1_end_tag(asn1)) return false;
+	if (!asn1_end_tag(asn1)) return false;
 
 	return !asn1->has_error;
 }
 
 static bool write_negTokenInit(struct asn1_data *asn1, struct spnego_negTokenInit *token)
 {
-	asn1_push_tag(asn1, ASN1_CONTEXT(0));
-	asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+	if (!asn1_push_tag(asn1, ASN1_CONTEXT(0))) return false;
+	if (!asn1_push_tag(asn1, ASN1_SEQUENCE(0))) return false;
 
 	/* Write mechTypes */
 	if (token->mechTypes && *token->mechTypes) {
 		int i;
 
-		asn1_push_tag(asn1, ASN1_CONTEXT(0));
-		asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(0))) return false;
+		if (!asn1_push_tag(asn1, ASN1_SEQUENCE(0))) return false;
 		for (i = 0; token->mechTypes[i]; i++) {
-			asn1_write_OID(asn1, token->mechTypes[i]);
+			if (!asn1_write_OID(asn1, token->mechTypes[i])) return false;
 		}
-		asn1_pop_tag(asn1);
-		asn1_pop_tag(asn1);
+		if (!asn1_pop_tag(asn1)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
 	}
 
 	/* write reqFlags */
 	if (token->reqFlags.length > 0) {
-		asn1_push_tag(asn1, ASN1_CONTEXT(1));
-		asn1_write_BitString(asn1, token->reqFlags.data,
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(1))) return false;
+		if (!asn1_write_BitString(asn1, token->reqFlags.data,
 				     token->reqFlags.length,
-				     token->reqFlagsPadding);
-		asn1_pop_tag(asn1);
+				     token->reqFlagsPadding)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
 	}
 
 	/* write mechToken */
 	if (token->mechToken.data) {
-		asn1_push_tag(asn1, ASN1_CONTEXT(2));
-		asn1_write_OctetString(asn1, token->mechToken.data,
-				       token->mechToken.length);
-		asn1_pop_tag(asn1);
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(2))) return false;
+		if (!asn1_write_OctetString(asn1, token->mechToken.data,
+				       token->mechToken.length)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
 	}
 
 	/* write mechListMIC */
 	if (token->mechListMIC.data) {
-		asn1_push_tag(asn1, ASN1_CONTEXT(3));
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(3))) return false;
 #if 0
 		/* This is what RFC 2478 says ... */
 		asn1_write_OctetString(asn1, token->mechListMIC.data,
@@ -174,20 +175,20 @@ static bool write_negTokenInit(struct asn1_data *asn1, struct spnego_negTokenIni
 #else
 		/* ... but unfortunately this is what Windows
 		   sends/expects */
-		asn1_push_tag(asn1, ASN1_SEQUENCE(0));
-		asn1_push_tag(asn1, ASN1_CONTEXT(0));
-		asn1_push_tag(asn1, ASN1_GENERAL_STRING);
-		asn1_write(asn1, token->mechListMIC.data,
-			   token->mechListMIC.length);
-		asn1_pop_tag(asn1);
-		asn1_pop_tag(asn1);
-		asn1_pop_tag(asn1);
+		if (!asn1_push_tag(asn1, ASN1_SEQUENCE(0))) return false;
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(0))) return false;
+		if (!asn1_push_tag(asn1, ASN1_GENERAL_STRING)) return false;
+		if (!asn1_write(asn1, token->mechListMIC.data,
+			   token->mechListMIC.length)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
 #endif
-		asn1_pop_tag(asn1);
+		if (!asn1_pop_tag(asn1)) return false;
 	}
 
-	asn1_pop_tag(asn1);
-	asn1_pop_tag(asn1);
+	if (!asn1_pop_tag(asn1)) return false;
+	if (!asn1_pop_tag(asn1)) return false;
 
 	return !asn1->has_error;
 }
@@ -197,8 +198,8 @@ static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 {
 	ZERO_STRUCTP(token);
 
-	asn1_start_tag(asn1, ASN1_CONTEXT(1));
-	asn1_start_tag(asn1, ASN1_SEQUENCE(0));
+	if (!asn1_start_tag(asn1, ASN1_CONTEXT(1))) return false;
+	if (!asn1_start_tag(asn1, ASN1_SEQUENCE(0))) return false;
 
 	while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
 		uint8_t context;
@@ -210,27 +211,27 @@ static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 
 		switch (context) {
 		case ASN1_CONTEXT(0):
-			asn1_start_tag(asn1, ASN1_CONTEXT(0));
-			asn1_start_tag(asn1, ASN1_ENUMERATED);
-			asn1_read_uint8(asn1, &token->negResult);
-			asn1_end_tag(asn1);
-			asn1_end_tag(asn1);
+			if (!asn1_start_tag(asn1, ASN1_CONTEXT(0))) return false;
+			if (!asn1_start_tag(asn1, ASN1_ENUMERATED)) return false;
+			if (!asn1_read_uint8(asn1, &token->negResult)) return false;
+			if (!asn1_end_tag(asn1)) return false;
+			if (!asn1_end_tag(asn1)) return false;
 			break;
 		case ASN1_CONTEXT(1):
-			asn1_start_tag(asn1, ASN1_CONTEXT(1));
-			asn1_read_OID(asn1, mem_ctx, &oid);
+			if (!asn1_start_tag(asn1, ASN1_CONTEXT(1))) return false;
+			if (!asn1_read_OID(asn1, mem_ctx, &oid)) return false;
 			token->supportedMech = oid;
-			asn1_end_tag(asn1);
+			if (!asn1_end_tag(asn1)) return false;
 			break;
 		case ASN1_CONTEXT(2):
-			asn1_start_tag(asn1, ASN1_CONTEXT(2));
-			asn1_read_OctetString(asn1, mem_ctx, &token->responseToken);
-			asn1_end_tag(asn1);
+			if (!asn1_start_tag(asn1, ASN1_CONTEXT(2))) return false;
+			if (!asn1_read_OctetString(asn1, mem_ctx, &token->responseToken)) return false;
+			if (!asn1_end_tag(asn1)) return false;
 			break;
 		case ASN1_CONTEXT(3):
-			asn1_start_tag(asn1, ASN1_CONTEXT(3));
-			asn1_read_OctetString(asn1, mem_ctx, &token->mechListMIC);
-			asn1_end_tag(asn1);
+			if (!asn1_start_tag(asn1, ASN1_CONTEXT(3))) return false;
+			if (!asn1_read_OctetString(asn1, mem_ctx, &token->mechListMIC)) return false;
+			if (!asn1_end_tag(asn1)) return false;
 			break;
 		default:
 			asn1->has_error = true;
@@ -238,45 +239,45 @@ static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
 		}
 	}
 
-	asn1_end_tag(asn1);
-	asn1_end_tag(asn1);
+	if (!asn1_end_tag(asn1)) return false;
+	if (!asn1_end_tag(asn1)) return false;
 
 	return !asn1->has_error;
 }
 
 static bool write_negTokenTarg(struct asn1_data *asn1, struct spnego_negTokenTarg *token)
 {
-	asn1_push_tag(asn1, ASN1_CONTEXT(1));
-	asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+	if (!asn1_push_tag(asn1, ASN1_CONTEXT(1))) return false;
+	if (!asn1_push_tag(asn1, ASN1_SEQUENCE(0))) return false;
 
 	if (token->negResult != SPNEGO_NONE_RESULT) {
-		asn1_push_tag(asn1, ASN1_CONTEXT(0));
-		asn1_write_enumerated(asn1, token->negResult);
-		asn1_pop_tag(asn1);
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(0))) return false;
+		if (!asn1_write_enumerated(asn1, token->negResult)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
 	}
 
 	if (token->supportedMech) {
-		asn1_push_tag(asn1, ASN1_CONTEXT(1));
-		asn1_write_OID(asn1, token->supportedMech);
-		asn1_pop_tag(asn1);
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(1))) return false;
+		if (!asn1_write_OID(asn1, token->supportedMech)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
 	}
 
 	if (token->responseToken.data) {
-		asn1_push_tag(asn1, ASN1_CONTEXT(2));
-		asn1_write_OctetString(asn1, token->responseToken.data,
-				       token->responseToken.length);
-		asn1_pop_tag(asn1);
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(2))) return false;
+		if (!asn1_write_OctetString(asn1, token->responseToken.data,
+				       token->responseToken.length)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
 	}
 
 	if (token->mechListMIC.data) {
-		asn1_push_tag(asn1, ASN1_CONTEXT(3));
-		asn1_write_OctetString(asn1, token->mechListMIC.data,
-				      token->mechListMIC.length);
-		asn1_pop_tag(asn1);
+		if (!asn1_push_tag(asn1, ASN1_CONTEXT(3))) return false;
+		if (!asn1_write_OctetString(asn1, token->mechListMIC.data,
+				      token->mechListMIC.length)) return false;
+		if (!asn1_pop_tag(asn1)) return false;
 	}
 
-	asn1_pop_tag(asn1);
-	asn1_pop_tag(asn1);
+	if (!asn1_pop_tag(asn1)) return false;
+	if (!asn1_pop_tag(asn1)) return false;
 
 	return !asn1->has_error;
 }
@@ -298,19 +299,19 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data
 		return -1;
 	}
 
-	asn1_load(asn1, data);
+	if (!asn1_load(asn1, data)) goto err;
 
 	if (!asn1_peek_uint8(asn1, &context)) {
 		asn1->has_error = true;
 	} else {
 		switch (context) {
 		case ASN1_APPLICATION(0):
-			asn1_start_tag(asn1, ASN1_APPLICATION(0));
-			asn1_check_OID(asn1, OID_SPNEGO);
+			if (!asn1_start_tag(asn1, ASN1_APPLICATION(0))) goto err;
+			if (!asn1_check_OID(asn1, OID_SPNEGO)) goto err;
 			if (read_negTokenInit(asn1, mem_ctx, &token->negTokenInit)) {
 				token->type = SPNEGO_NEG_TOKEN_INIT;
 			}
-			asn1_end_tag(asn1);
+			if (!asn1_end_tag(asn1)) goto err;
 			break;
 		case ASN1_CONTEXT(1):
 			if (read_negTokenTarg(asn1, mem_ctx, &token->negTokenTarg)) {
@@ -324,6 +325,9 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data
 	}
 
 	if (!asn1->has_error) ret = asn1->ofs;
+
+  err:
+
 	asn1_free(asn1);
 
 	return ret;
@@ -340,10 +344,10 @@ ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_da
 
 	switch (spnego->type) {
 	case SPNEGO_NEG_TOKEN_INIT:
-		asn1_push_tag(asn1, ASN1_APPLICATION(0));
-		asn1_write_OID(asn1, OID_SPNEGO);
-		write_negTokenInit(asn1, &spnego->negTokenInit);
-		asn1_pop_tag(asn1);
+		if (!asn1_push_tag(asn1, ASN1_APPLICATION(0))) goto err;
+		if (!asn1_write_OID(asn1, OID_SPNEGO)) goto err;
+		if (!write_negTokenInit(asn1, &spnego->negTokenInit)) goto err;
+		if (!asn1_pop_tag(asn1)) goto err;
 		break;
 	case SPNEGO_NEG_TOKEN_TARG:
 		write_negTokenTarg(asn1, &spnego->negTokenTarg);
@@ -357,6 +361,9 @@ ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_da
 		*blob = data_blob_talloc(mem_ctx, asn1->data, asn1->length);
 		ret = asn1->ofs;
 	}
+
+  err:
+
 	asn1_free(asn1);
 
 	return ret;
@@ -398,6 +405,7 @@ bool spnego_write_mech_types(TALLOC_CTX *mem_ctx,
 			     const char * const *mech_types,
 			     DATA_BLOB *blob)
 {
+	bool ret = false;
 	struct asn1_data *asn1 = asn1_init(mem_ctx);
 
 	if (asn1 == NULL) {
@@ -408,25 +416,27 @@ bool spnego_write_mech_types(TALLOC_CTX *mem_ctx,
 	if (mech_types && *mech_types) {
 		int i;
 
-		asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+		if (!asn1_push_tag(asn1, ASN1_SEQUENCE(0))) goto err;
 		for (i = 0; mech_types[i]; i++) {
-			asn1_write_OID(asn1, mech_types[i]);
+			if (!asn1_write_OID(asn1, mech_types[i])) goto err;
 		}
-		asn1_pop_tag(asn1);
+		if (!asn1_pop_tag(asn1)) goto err;
 	}
 
 	if (asn1->has_error) {
-		asn1_free(asn1);
-		return false;
+		goto err;
 	}
 
 	*blob = data_blob_talloc(mem_ctx, asn1->data, asn1->length);
 	if (blob->length != asn1->length) {
-		asn1_free(asn1);
-		return false;
+		goto err;
 	}
 
+	ret = true;
+
+  err:
+
 	asn1_free(asn1);
 
-	return true;
+	return ret;
 }
-- 
2.1.0.rc2.206.gedb03e5


From ffa4a6064c5964b3a4c04e9c64267cd6117fb74c Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 19 Sep 2014 14:27:58 -0700
Subject: [PATCH 5/8] s3: libsmb: Ensure all asn1_XX returns are checked.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/libsmb/clispnego.c | 253 ++++++++++++++++++++++++---------------------
 1 file changed, 137 insertions(+), 116 deletions(-)

diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index 9b4f8f9..ec8d1ee 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -37,53 +37,56 @@ DATA_BLOB spnego_gen_negTokenInit(TALLOC_CTX *ctx,
 {
 	int i;
 	ASN1_DATA *data;
-	DATA_BLOB ret;
+	DATA_BLOB ret = data_blob_null;
 
 	data = asn1_init(talloc_tos());
 	if (data == NULL) {
 		return data_blob_null;
 	}
 
-	asn1_push_tag(data,ASN1_APPLICATION(0));
-	asn1_write_OID(data,OID_SPNEGO);
-	asn1_push_tag(data,ASN1_CONTEXT(0));
-	asn1_push_tag(data,ASN1_SEQUENCE(0));
+	if (!asn1_push_tag(data,ASN1_APPLICATION(0))) goto err;
+	if (!asn1_write_OID(data,OID_SPNEGO)) goto err;
+	if (!asn1_push_tag(data,ASN1_CONTEXT(0))) goto err;
+	if (!asn1_push_tag(data,ASN1_SEQUENCE(0))) goto err;
 
-	asn1_push_tag(data,ASN1_CONTEXT(0));
-	asn1_push_tag(data,ASN1_SEQUENCE(0));
+	if (!asn1_push_tag(data,ASN1_CONTEXT(0))) goto err;
+	if (!asn1_push_tag(data,ASN1_SEQUENCE(0))) goto err;
 	for (i=0; OIDs[i]; i++) {
-		asn1_write_OID(data,OIDs[i]);
+		if (!asn1_write_OID(data,OIDs[i])) goto err;
 	}
-	asn1_pop_tag(data);
-	asn1_pop_tag(data);
+	if (!asn1_pop_tag(data)) goto err;
+	if (!asn1_pop_tag(data)) goto err;
 
 	if (psecblob && psecblob->length && psecblob->data) {
-		asn1_push_tag(data, ASN1_CONTEXT(2));
-		asn1_write_OctetString(data,psecblob->data,
-			psecblob->length);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT(2))) goto err;
+		if (!asn1_write_OctetString(data,psecblob->data,
+			psecblob->length)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 	}
 
 	if (principal) {
-		asn1_push_tag(data, ASN1_CONTEXT(3));
-		asn1_push_tag(data, ASN1_SEQUENCE(0));
-		asn1_push_tag(data, ASN1_CONTEXT(0));
-		asn1_write_GeneralString(data,principal);
-		asn1_pop_tag(data);
-		asn1_pop_tag(data);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT(3))) goto err;
+		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
+		if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err;
+		if (!asn1_write_GeneralString(data,principal)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 	}
 
-	asn1_pop_tag(data);
-	asn1_pop_tag(data);
+	if (!asn1_pop_tag(data)) goto err;
+	if (!asn1_pop_tag(data)) goto err;
 
-	asn1_pop_tag(data);
+	if (!asn1_pop_tag(data)) goto err;
+
+	ret = data_blob_talloc(ctx, data->data, data->length);
+
+  err:
 
 	if (data->has_error) {
 		DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data->ofs));
 	}
 
-	ret = data_blob_talloc(ctx, data->data, data->length);
 	asn1_free(data);
 
 	return ret;
@@ -100,53 +103,53 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
 			       DATA_BLOB *secblob)
 {
 	int i;
-	bool ret;
+	bool ret = false;
 	ASN1_DATA *data;
 
 	for (i = 0; i < ASN1_MAX_OIDS; i++) {
 		OIDs[i] = NULL;
 	}
 
+	if (principal) {
+		*principal = NULL;
+	}
+	if (secblob) {
+		*secblob = data_blob_null;
+	}
+
 	data = asn1_init(talloc_tos());
 	if (data == NULL) {
 		return false;
 	}
 
-	asn1_load(data, blob);
+	if (!asn1_load(data, blob)) goto err;
 
-	asn1_start_tag(data,ASN1_APPLICATION(0));
+	if (!asn1_start_tag(data,ASN1_APPLICATION(0))) goto err;
 
-	asn1_check_OID(data,OID_SPNEGO);
+	if (!asn1_check_OID(data,OID_SPNEGO)) goto err;
 
 	/* negTokenInit  [0]  NegTokenInit */
-	asn1_start_tag(data,ASN1_CONTEXT(0));
-	asn1_start_tag(data,ASN1_SEQUENCE(0));
+	if (!asn1_start_tag(data,ASN1_CONTEXT(0))) goto err;
+	if (!asn1_start_tag(data,ASN1_SEQUENCE(0))) goto err;
 
 	/* mechTypes [0] MechTypeList  OPTIONAL */
 
 	/* Not really optional, we depend on this to decide
 	 * what mechanisms we have to work with. */
 
-	asn1_start_tag(data,ASN1_CONTEXT(0));
-	asn1_start_tag(data,ASN1_SEQUENCE(0));
+	if (!asn1_start_tag(data,ASN1_CONTEXT(0))) goto err;
+	if (!asn1_start_tag(data,ASN1_SEQUENCE(0))) goto err;
 	for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) {
 		if (!asn1_read_OID(data,ctx, &OIDs[i])) {
-			break;
+			goto err;
 		}
 		if (data->has_error) {
-			break;
+			goto err;
 		}
 	}
 	OIDs[i] = NULL;
-	asn1_end_tag(data);
-	asn1_end_tag(data);
-
-	if (principal) {
-		*principal = NULL;
-	}
-	if (secblob) {
-		*secblob = data_blob_null;
-	}
+	if (!asn1_end_tag(data)) goto err;
+	if (!asn1_end_tag(data)) goto err;
 
 	/*
 	  Win7 + Live Sign-in Assistant attaches a mechToken
@@ -159,21 +162,24 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
 		uint8 flags;
 
 		/* reqFlags [1] ContextFlags  OPTIONAL */
-		asn1_start_tag(data, ASN1_CONTEXT(1));
-		asn1_start_tag(data, ASN1_BIT_STRING);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(1))) goto err;
+		if (!asn1_start_tag(data, ASN1_BIT_STRING)) goto err;
 		while (asn1_tag_remaining(data) > 0) {
-			asn1_read_uint8(data, &flags);
+			if (!asn1_read_uint8(data, &flags)) goto err;
 		}
-		asn1_end_tag(data);
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto err;
+		if (!asn1_end_tag(data)) goto err;
 	}
 
 	if (asn1_peek_tag(data, ASN1_CONTEXT(2))) {
 		DATA_BLOB sblob = data_blob_null;
 		/* mechToken [2] OCTET STRING  OPTIONAL */
-		asn1_start_tag(data, ASN1_CONTEXT(2));
-		asn1_read_OctetString(data, ctx, &sblob);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(2))) goto err;
+		if (!asn1_read_OctetString(data, ctx, &sblob)) goto err;
+		if (!asn1_end_tag(data)) {
+			data_blob_free(&sblob);
+			goto err;
+		}
 		if (secblob) {
 			*secblob = sblob;
 		} else {
@@ -184,13 +190,13 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
 	if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
 		char *princ = NULL;
 		/* mechListMIC [3] OCTET STRING  OPTIONAL */
-		asn1_start_tag(data, ASN1_CONTEXT(3));
-		asn1_start_tag(data, ASN1_SEQUENCE(0));
-		asn1_start_tag(data, ASN1_CONTEXT(0));
-		asn1_read_GeneralString(data, ctx, &princ);
-		asn1_end_tag(data);
-		asn1_end_tag(data);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto err;
+		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto err;
+		if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto err;
+		if (!asn1_read_GeneralString(data, ctx, &princ)) goto err;
+		if (!asn1_end_tag(data)) goto err;
+		if (!asn1_end_tag(data)) goto err;
+		if (!asn1_end_tag(data)) goto err;
 		if (principal) {
 			*principal = princ;
 		} else {
@@ -198,12 +204,15 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
 		}
 	}
 
-	asn1_end_tag(data);
-	asn1_end_tag(data);
+	if (!asn1_end_tag(data)) goto err;
+	if (!asn1_end_tag(data)) goto err;
 
-	asn1_end_tag(data);
+	if (!asn1_end_tag(data)) goto err;
 
 	ret = !data->has_error;
+
+  err:
+
 	if (data->has_error) {
 		int j;
 		if (principal) {
@@ -227,25 +236,28 @@ bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
 DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const uint8 tok_id[2])
 {
 	ASN1_DATA *data;
-	DATA_BLOB ret;
+	DATA_BLOB ret = data_blob_null;
 
 	data = asn1_init(talloc_tos());
 	if (data == NULL) {
 		return data_blob_null;
 	}
 
-	asn1_push_tag(data, ASN1_APPLICATION(0));
-	asn1_write_OID(data, OID_KERBEROS5);
+	if (!asn1_push_tag(data, ASN1_APPLICATION(0))) goto err;
+	if (!asn1_write_OID(data, OID_KERBEROS5)) goto err;
 
-	asn1_write(data, tok_id, 2);
-	asn1_write(data, ticket.data, ticket.length);
-	asn1_pop_tag(data);
+	if (!asn1_write(data, tok_id, 2)) goto err;
+	if (!asn1_write(data, ticket.data, ticket.length)) goto err;
+	if (!asn1_pop_tag(data)) goto err;
+
+	ret = data_blob_talloc(ctx, data->data, data->length);
+
+  err:
 
 	if (data->has_error) {
 		DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data->ofs));
 	}
 
-	ret = data_blob_talloc(ctx, data->data, data->length);
 	asn1_free(data);
 
 	return ret;
@@ -293,7 +305,7 @@ int spnego_gen_krb5_negTokenInit(TALLOC_CTX *ctx,
 bool spnego_parse_challenge(TALLOC_CTX *ctx, const DATA_BLOB blob,
 			    DATA_BLOB *chal1, DATA_BLOB *chal2)
 {
-	bool ret;
+	bool ret = false;
 	ASN1_DATA *data;
 
 	ZERO_STRUCTP(chal1);
@@ -304,34 +316,36 @@ bool spnego_parse_challenge(TALLOC_CTX *ctx, const DATA_BLOB blob,
 		return false;
 	}
 
-	asn1_load(data, blob);
-	asn1_start_tag(data,ASN1_CONTEXT(1));
-	asn1_start_tag(data,ASN1_SEQUENCE(0));
+	if (!asn1_load(data, blob)) goto err;
+	if (!asn1_start_tag(data,ASN1_CONTEXT(1))) goto err;
+	if (!asn1_start_tag(data,ASN1_SEQUENCE(0))) goto err;
 
-	asn1_start_tag(data,ASN1_CONTEXT(0));
-	asn1_check_enumerated(data,1);
-	asn1_end_tag(data);
+	if (!asn1_start_tag(data,ASN1_CONTEXT(0))) goto err;
+	if (!asn1_check_enumerated(data,1)) goto err;
+	if (!asn1_end_tag(data)) goto err;
 
-	asn1_start_tag(data,ASN1_CONTEXT(1));
-	asn1_check_OID(data, OID_NTLMSSP);
-	asn1_end_tag(data);
+	if (!asn1_start_tag(data,ASN1_CONTEXT(1))) goto err;
+	if (!asn1_check_OID(data, OID_NTLMSSP)) goto err;
+	if (!asn1_end_tag(data)) goto err;
 
-	asn1_start_tag(data,ASN1_CONTEXT(2));
-	asn1_read_OctetString(data, ctx, chal1);
-	asn1_end_tag(data);
+	if (!asn1_start_tag(data,ASN1_CONTEXT(2))) goto err;
+	if (!asn1_read_OctetString(data, ctx, chal1)) goto err;
+	if (!asn1_end_tag(data)) goto err;
 
 	/* the second challenge is optional (XP doesn't send it) */
 	if (asn1_tag_remaining(data)) {
-		asn1_start_tag(data,ASN1_CONTEXT(3));
-		asn1_read_OctetString(data, ctx, chal2);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data,ASN1_CONTEXT(3))) goto err;
+		if (!asn1_read_OctetString(data, ctx, chal2)) goto err;
+		if (!asn1_end_tag(data)) goto err;
 	}
 
-	asn1_end_tag(data);
-	asn1_end_tag(data);
+	if (!asn1_end_tag(data)) goto err;
+	if (!asn1_end_tag(data)) goto err;
 
 	ret = !data->has_error;
 
+  err:
+
 	if (data->has_error) {
 		data_blob_free(chal1);
 		data_blob_free(chal2);
@@ -348,23 +362,25 @@ bool spnego_parse_challenge(TALLOC_CTX *ctx, const DATA_BLOB blob,
 DATA_BLOB spnego_gen_auth(TALLOC_CTX *ctx, DATA_BLOB blob)
 {
 	ASN1_DATA *data;
-	DATA_BLOB ret;
+	DATA_BLOB ret = data_blob_null;
 
 	data = asn1_init(talloc_tos());
 	if (data == NULL) {
 		return data_blob_null;
 	}
 
-	asn1_push_tag(data, ASN1_CONTEXT(1));
-	asn1_push_tag(data, ASN1_SEQUENCE(0));
-	asn1_push_tag(data, ASN1_CONTEXT(2));
-	asn1_write_OctetString(data,blob.data,blob.length);
-	asn1_pop_tag(data);
-	asn1_pop_tag(data);
-	asn1_pop_tag(data);
+	if (!asn1_push_tag(data, ASN1_CONTEXT(1))) goto err;
+	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
+	if (!asn1_push_tag(data, ASN1_CONTEXT(2))) goto err;
+	if (!asn1_write_OctetString(data,blob.data,blob.length)) goto err;
+	if (!asn1_pop_tag(data)) goto err;
+	if (!asn1_pop_tag(data)) goto err;
+	if (!asn1_pop_tag(data)) goto err;
 
 	ret = data_blob_talloc(ctx, data->data, data->length);
 
+ err:
+
 	asn1_free(data);
 
 	return ret;
@@ -380,6 +396,7 @@ bool spnego_parse_auth_response(TALLOC_CTX *ctx,
 {
 	ASN1_DATA *data;
 	uint8 negResult;
+	bool ret = false;
 
 	if (NT_STATUS_IS_OK(nt_status)) {
 		negResult = SPNEGO_ACCEPT_COMPLETED;
@@ -394,27 +411,28 @@ bool spnego_parse_auth_response(TALLOC_CTX *ctx,
 		return false;
 	}
 
-	asn1_load(data, blob);
-	asn1_start_tag(data, ASN1_CONTEXT(1));
-	asn1_start_tag(data, ASN1_SEQUENCE(0));
-	asn1_start_tag(data, ASN1_CONTEXT(0));
-	asn1_check_enumerated(data, negResult);
-	asn1_end_tag(data);
-
 	*auth = data_blob_null;
 
+	if (!asn1_load(data, blob)) goto err;
+	if (!asn1_start_tag(data, ASN1_CONTEXT(1))) goto err;
+	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto err;
+	if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto err;
+	if (!asn1_check_enumerated(data, negResult)) goto err;
+	if (!asn1_end_tag(data)) goto err;
+
 	if (asn1_tag_remaining(data)) {
-		asn1_start_tag(data,ASN1_CONTEXT(1));
-		asn1_check_OID(data, mechOID);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data,ASN1_CONTEXT(1))) goto err;
+		if (!asn1_check_OID(data, mechOID)) goto err;
+		if (!asn1_end_tag(data)) goto err;
 
 		if (asn1_tag_remaining(data)) {
-			asn1_start_tag(data,ASN1_CONTEXT(2));
-			asn1_read_OctetString(data, ctx, auth);
-			asn1_end_tag(data);
+			if (!asn1_start_tag(data,ASN1_CONTEXT(2))) goto err;
+			if (!asn1_read_OctetString(data, ctx, auth)) goto err;
+			if (!asn1_end_tag(data)) goto err;
 		}
 	} else if (negResult == SPNEGO_ACCEPT_INCOMPLETE) {
 		data->has_error = 1;
+		goto err;
 	}
 
 	/* Binding against Win2K DC returns a duplicate of the responseToken in
@@ -423,25 +441,28 @@ bool spnego_parse_auth_response(TALLOC_CTX *ctx,
 	 * which point we need to implement the integrity checking. */
 	if (asn1_tag_remaining(data)) {
 		DATA_BLOB mechList = data_blob_null;
-		asn1_start_tag(data, ASN1_CONTEXT(3));
-		asn1_read_OctetString(data, ctx, &mechList);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto err;
+		if (!asn1_read_OctetString(data, ctx, &mechList)) goto err;
 		data_blob_free(&mechList);
+		if (!asn1_end_tag(data)) goto err;
 		DEBUG(5,("spnego_parse_auth_response received mechListMIC, "
 		    "ignoring.\n"));
 	}
 
-	asn1_end_tag(data);
-	asn1_end_tag(data);
+	if (!asn1_end_tag(data)) goto err;
+	if (!asn1_end_tag(data)) goto err;
+
+	ret = !data->has_error;
+
+  err:
 
 	if (data->has_error) {
 		DEBUG(3,("spnego_parse_auth_response failed at %d\n", (int)data->ofs));
 		asn1_free(data);
 		data_blob_free(auth);
-		return False;
+		return false;
 	}
 
 	asn1_free(data);
-	return True;
+	return ret;
 }
-
-- 
2.1.0.rc2.206.gedb03e5


From c1572b3a68b878b484dd96770965f72de2a4fb7a Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 19 Sep 2014 15:10:46 -0700
Subject: [PATCH 6/8] s3: tldap: Ensure all asn1_XX returns are checked.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/lib/tldap.c | 315 ++++++++++++++++++++++++++++------------------------
 1 file changed, 172 insertions(+), 143 deletions(-)

diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
index b15ee73..5d3773e 100644
--- a/source3/lib/tldap.c
+++ b/source3/lib/tldap.c
@@ -356,33 +356,33 @@ struct tldap_msg_state {
 	uint8_t *inbuf;
 };
 
-static void tldap_push_controls(struct asn1_data *data,
+static bool tldap_push_controls(struct asn1_data *data,
 				struct tldap_control *sctrls,
 				int num_sctrls)
 {
 	int i;
 
 	if ((sctrls == NULL) || (num_sctrls == 0)) {
-		return;
+		return true;
 	}
 
-	asn1_push_tag(data, ASN1_CONTEXT(0));
+	if (!asn1_push_tag(data, ASN1_CONTEXT(0))) return false;
 
 	for (i=0; i<num_sctrls; i++) {
 		struct tldap_control *c = &sctrls[i];
-		asn1_push_tag(data, ASN1_SEQUENCE(0));
-		asn1_write_OctetString(data, c->oid, strlen(c->oid));
+		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
+		if (!asn1_write_OctetString(data, c->oid, strlen(c->oid))) return false;
 		if (c->critical) {
-			asn1_write_BOOLEAN(data, true);
+			if (!asn1_write_BOOLEAN(data, true)) return false;
 		}
 		if (c->value.data != NULL) {
-			asn1_write_OctetString(data, c->value.data,
-					       c->value.length);
+			if (!asn1_write_OctetString(data, c->value.data,
+					       c->value.length)) return false;
 		}
-		asn1_pop_tag(data); /* ASN1_SEQUENCE(0) */
+		if (!asn1_pop_tag(data)) return false; /* ASN1_SEQUENCE(0) */
 	}
 
-	asn1_pop_tag(data); /* ASN1_CONTEXT(0) */
+	return asn1_pop_tag(data); /* ASN1_CONTEXT(0) */
 }
 
 static void tldap_msg_sent(struct tevent_req *subreq);
@@ -415,9 +415,16 @@ static struct tevent_req *tldap_msg_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
-	tldap_push_controls(data, sctrls, num_sctrls);
+	if (!tldap_push_controls(data, sctrls, num_sctrls)) {
+		tevent_req_error(req, TLDAP_ENCODING_ERROR);
+		return tevent_req_post(req, ev);
+	}
+
 
-	asn1_pop_tag(data);
+	if (!asn1_pop_tag(data)) {
+		tevent_req_error(req, TLDAP_ENCODING_ERROR);
+		return tevent_req_post(req, ev);
+	}
 
 	if (!asn1_blob(data, &blob)) {
 		tevent_req_error(req, TLDAP_ENCODING_ERROR);
@@ -719,17 +726,21 @@ static struct tevent_req *tldap_req_create(TALLOC_CTX *mem_ctx,
 	ZERO_STRUCTP(state);
 	state->out = asn1_init(state);
 	if (state->out == NULL) {
-		TALLOC_FREE(req);
-		return NULL;
+		goto err;
 	}
 	state->result = NULL;
 	state->id = tldap_next_msgid(ld);
 
-	asn1_push_tag(state->out, ASN1_SEQUENCE(0));
-	asn1_write_Integer(state->out, state->id);
+	if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
+	if (!asn1_write_Integer(state->out, state->id)) goto err;
 
 	*pstate = state;
 	return req;
+
+  err:
+
+	TALLOC_FREE(req);
+	return NULL;
 }
 
 static void tldap_save_msg(struct tldap_context *ld, struct tevent_req *req)
@@ -786,6 +797,7 @@ static bool tldap_decode_response(struct tldap_req_state *state)
 	ok &= asn1_read_OctetString_talloc(msg, data, &msg->res_matcheddn);
 	ok &= asn1_read_OctetString_talloc(msg, data,
 					   &msg->res_diagnosticmessage);
+	if (!ok) return ok;
 	if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
 		ok &= asn1_start_tag(data, ASN1_CONTEXT(3));
 		ok &= asn1_read_OctetString_talloc(msg, data,
@@ -823,29 +835,26 @@ struct tevent_req *tldap_sasl_bind_send(TALLOC_CTX *mem_ctx,
 		dn = "";
 	}
 
-	asn1_push_tag(state->out, TLDAP_REQ_BIND);
-	asn1_write_Integer(state->out, ld->ld_version);
-	asn1_write_OctetString(state->out, dn, strlen(dn));
+	if (!asn1_push_tag(state->out, TLDAP_REQ_BIND)) goto err;
+	if (!asn1_write_Integer(state->out, ld->ld_version)) goto err;
+	if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
 
 	if (mechanism == NULL) {
-		asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0));
-		asn1_write(state->out, creds->data, creds->length);
-		asn1_pop_tag(state->out);
+		if (!asn1_push_tag(state->out, ASN1_CONTEXT_SIMPLE(0))) goto err;
+		if (!asn1_write(state->out, creds->data, creds->length)) goto err;
+		if (!asn1_pop_tag(state->out)) goto err;
 	} else {
-		asn1_push_tag(state->out, ASN1_CONTEXT(3));
-		asn1_write_OctetString(state->out, mechanism,
-				       strlen(mechanism));
+		if (!asn1_push_tag(state->out, ASN1_CONTEXT(3))) goto err;
+		if (!asn1_write_OctetString(state->out, mechanism,
+				       strlen(mechanism))) goto err;
 		if ((creds != NULL) && (creds->data != NULL)) {
-			asn1_write_OctetString(state->out, creds->data,
-					       creds->length);
+			if (!asn1_write_OctetString(state->out, creds->data,
+					       creds->length)) goto err;
 		}
-		asn1_pop_tag(state->out);
+		if (!asn1_pop_tag(state->out)) goto err;
 	}
 
-	if (!asn1_pop_tag(state->out)) {
-		tevent_req_error(req, TLDAP_ENCODING_ERROR);
-		return tevent_req_post(req, ev);
-	}
+	if (!asn1_pop_tag(state->out)) goto err;
 
 	subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
 				sctrls, num_sctrls);
@@ -854,6 +863,11 @@ struct tevent_req *tldap_sasl_bind_send(TALLOC_CTX *mem_ctx,
 	}
 	tevent_req_set_callback(subreq, tldap_sasl_bind_done, req);
 	return req;
+
+  err:
+
+	tevent_req_error(req, TLDAP_ENCODING_ERROR);
+	return tevent_req_post(req, ev);
 }
 
 static void tldap_sasl_bind_done(struct tevent_req *subreq)
@@ -1231,25 +1245,25 @@ static bool tldap_push_filter_int(struct tldap_context *ld,
 	switch (*s) {
 	case '&':
 		tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: AND\n");
-		asn1_push_tag(data, TLDAP_FILTER_AND);
+		if (!asn1_push_tag(data, TLDAP_FILTER_AND)) return false;
 		s++;
 		break;
 
 	case '|':
 		tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: OR\n");
-		asn1_push_tag(data, TLDAP_FILTER_OR);
+		if (!asn1_push_tag(data, TLDAP_FILTER_OR)) return false;
 		s++;
 		break;
 
 	case '!':
 		tldap_debug(ld, TLDAP_DEBUG_TRACE, "Filter op: NOT\n");
-		asn1_push_tag(data, TLDAP_FILTER_NOT);
+		if (!asn1_push_tag(data, TLDAP_FILTER_NOT)) return false;
 		s++;
 		ret = tldap_push_filter_int(ld, data, &s);
 		if (!ret) {
 			return false;
 		}
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) return false;
 		goto done;
 
 	case '(':
@@ -1276,7 +1290,7 @@ static bool tldap_push_filter_int(struct tldap_context *ld,
 
 	if (*s == ')') {
 		/* RFC 4526: empty and/or */
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) return false;
 		goto done;
 	}
 
@@ -1288,7 +1302,7 @@ static bool tldap_push_filter_int(struct tldap_context *ld,
 
 		if (*s == ')') {
 			/* end of list, return */
-			asn1_pop_tag(data);
+			if (!asn1_pop_tag(data)) return false;
 			break;
 		}
 	}
@@ -1341,19 +1355,19 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 
 	switch (*e) {
 	case '<':
-		asn1_push_tag(data, TLDAP_FILTER_LE);
+		if (!asn1_push_tag(data, TLDAP_FILTER_LE)) return false;
 		break;
 
 	case '>':
-		asn1_push_tag(data, TLDAP_FILTER_GE);
+		if (!asn1_push_tag(data, TLDAP_FILTER_GE)) return false;
 		break;
 
 	case '~':
-		asn1_push_tag(data, TLDAP_FILTER_APX);
+		if (!asn1_push_tag(data, TLDAP_FILTER_APX)) return false;
 		break;
 
 	case ':':
-		asn1_push_tag(data, TLDAP_FILTER_EXT);
+		if (!asn1_push_tag(data, TLDAP_FILTER_EXT)) return false;
 		write_octect = false;
 
 		type = NULL;
@@ -1425,9 +1439,9 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 			if (!ret) {
 				return false;
 			}
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
-			asn1_write(data, rule, e - rule);
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) return false;
+			if (!asn1_write(data, rule, e - rule)) return false;
+			if (!asn1_pop_tag(data)) return false;
 		}
 
 		/* check and add type */
@@ -1436,9 +1450,9 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 			if (!ret) {
 				return false;
 			}
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
-			asn1_write(data, type, type_len);
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2))) return false;
+			if (!asn1_write(data, type, type_len)) return false;
+			if (!asn1_pop_tag(data)) return false;
 		}
 
 		uval = tldap_get_val(tmpctx, val, _s);
@@ -1451,13 +1465,13 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 			return false;
 		}
 
-		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
-		asn1_write(data, uval, uval_len);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3))) return false;
+		if (!asn1_write(data, uval, uval_len)) return false;
+		if (!asn1_pop_tag(data)) return false;
 
-		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
-		asn1_write_uint8(data, dn?1:0);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4))) return false;
+		if (!asn1_write_uint8(data, dn?1:0)) return false;
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	default:
@@ -1470,8 +1484,8 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 
 		if (strncmp(val, "*)", 2) == 0) {
 			/* presence */
-			asn1_push_tag(data, TLDAP_FILTER_PRES);
-			asn1_write(data, s, e - s);
+			if (!asn1_push_tag(data, TLDAP_FILTER_PRES)) return false;
+			if (!asn1_write(data, s, e - s)) return false;
 			*_s = val + 1;
 			write_octect = false;
 			break;
@@ -1483,8 +1497,8 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 		}
 		if (*star == '*') {
 			/* substring */
-			asn1_push_tag(data, TLDAP_FILTER_SUB);
-			asn1_write_OctetString(data, s, e - s);
+			if (!asn1_push_tag(data, TLDAP_FILTER_SUB)) return false;
+			if (!asn1_write_OctetString(data, s, e - s)) return false;
 			ret = tldap_push_filter_substring(ld, data, val, &s);
 			if (!ret) {
 				return false;
@@ -1495,7 +1509,7 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 		}
 
 		/* if nothing else, then it is just equality */
-		asn1_push_tag(data, TLDAP_FILTER_EQ);
+		if (!asn1_push_tag(data, TLDAP_FILTER_EQ)) return false;
 		write_octect = true;
 		break;
 	}
@@ -1511,15 +1525,14 @@ static bool tldap_push_filter_basic(struct tldap_context *ld,
 			return false;
 		}
 
-		asn1_write_OctetString(data, s, e - s);
-		asn1_write_OctetString(data, uval, uval_len);
+		if (!asn1_write_OctetString(data, s, e - s)) return false;
+		if (!asn1_write_OctetString(data, uval, uval_len)) return false;
 	}
 
 	if (data->has_error) {
 		return false;
 	}
-	asn1_pop_tag(data);
-	return true;
+	return asn1_pop_tag(data);
 }
 
 static bool tldap_push_filter_substring(struct tldap_context *ld,
@@ -1543,7 +1556,7 @@ static bool tldap_push_filter_substring(struct tldap_context *ld,
 			  any     [1] LDAPString,
 			  final   [2] LDAPString } }
 	*/
-	asn1_push_tag(data, ASN1_SEQUENCE(0));
+	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
 
 	do {
 		ret = tldap_find_first_star(val, &star);
@@ -1588,21 +1601,21 @@ static bool tldap_push_filter_substring(struct tldap_context *ld,
 		switch (*star) {
 		case '*':
 			if (initial) {
-				asn1_push_tag(data, TLDAP_SUB_INI);
+				if (!asn1_push_tag(data, TLDAP_SUB_INI)) return false;
 				initial = false;
 			} else {
-				asn1_push_tag(data, TLDAP_SUB_ANY);
+				if (!asn1_push_tag(data, TLDAP_SUB_ANY)) return false;
 			}
 			break;
 		case ')':
-			asn1_push_tag(data, TLDAP_SUB_FIN);
+			if (!asn1_push_tag(data, TLDAP_SUB_FIN)) return false;
 			break;
 		default:
 			/* ?? */
 			return false;
 		}
-		asn1_write(data, chunk, chunk_len);
-		asn1_pop_tag(data);
+		if (!asn1_write(data, chunk, chunk_len)) return false;
+		if (!asn1_pop_tag(data)) return false;
 
 		val = star + 1;
 
@@ -1611,8 +1624,7 @@ static bool tldap_push_filter_substring(struct tldap_context *ld,
 	*_s = star;
 
 	/* end of sequence */
-	asn1_pop_tag(data);
-	return true;
+	return asn1_pop_tag(data);
 }
 
 /* NOTE: although openldap libraries allow for spaces in some places, mosly
@@ -1665,24 +1677,24 @@ struct tevent_req *tldap_search_send(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	asn1_push_tag(state->out, TLDAP_REQ_SEARCH);
-	asn1_write_OctetString(state->out, base, strlen(base));
-	asn1_write_enumerated(state->out, scope);
-	asn1_write_enumerated(state->out, deref);
-	asn1_write_Integer(state->out, sizelimit);
-	asn1_write_Integer(state->out, timelimit);
-	asn1_write_BOOLEAN(state->out, attrsonly);
+	if (!asn1_push_tag(state->out, TLDAP_REQ_SEARCH)) goto encoding_error;
+	if (!asn1_write_OctetString(state->out, base, strlen(base))) goto encoding_error;
+	if (!asn1_write_enumerated(state->out, scope)) goto encoding_error;
+	if (!asn1_write_enumerated(state->out, deref)) goto encoding_error;
+	if (!asn1_write_Integer(state->out, sizelimit)) goto encoding_error;
+	if (!asn1_write_Integer(state->out, timelimit)) goto encoding_error;
+	if (!asn1_write_BOOLEAN(state->out, attrsonly)) goto encoding_error;
 
 	if (!tldap_push_filter(ld, state->out, filter)) {
 		goto encoding_error;
 	}
 
-	asn1_push_tag(state->out, ASN1_SEQUENCE(0));
+	if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto encoding_error;
 	for (i=0; i<num_attrs; i++) {
-		asn1_write_OctetString(state->out, attrs[i], strlen(attrs[i]));
+		if (!asn1_write_OctetString(state->out, attrs[i], strlen(attrs[i]))) goto encoding_error;
 	}
-	asn1_pop_tag(state->out);
-	asn1_pop_tag(state->out);
+	if (!asn1_pop_tag(state->out)) goto encoding_error;
+	if (!asn1_pop_tag(state->out)) goto encoding_error;
 
 	subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
 				sctrls, num_sctrls);
@@ -1890,11 +1902,12 @@ static bool tldap_parse_search_entry(struct tldap_message *msg)
 {
 	int num_attribs = 0;
 
-	asn1_start_tag(msg->data, msg->type);
+	if (!asn1_start_tag(msg->data, msg->type)) return false;
 
 	/* dn */
 
-	asn1_read_OctetString_talloc(msg, msg->data, &msg->dn);
+	if (!asn1_read_OctetString_talloc(msg, msg->data, &msg->dn)) return false;
+
 	if (msg->dn == NULL) {
 		return false;
 	}
@@ -1910,7 +1923,7 @@ static bool tldap_parse_search_entry(struct tldap_message *msg)
 		return false;
 	}
 
-	asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
+	if (!asn1_start_tag(msg->data, ASN1_SEQUENCE(0))) return false;
 	while (asn1_peek_tag(msg->data, ASN1_SEQUENCE(0))) {
 		struct tldap_attribute *attrib;
 		int num_values = 0;
@@ -1920,14 +1933,14 @@ static bool tldap_parse_search_entry(struct tldap_message *msg)
 		if (attrib->values == NULL) {
 			return false;
 		}
-		asn1_start_tag(msg->data, ASN1_SEQUENCE(0));
-		asn1_read_OctetString_talloc(msg->attribs, msg->data,
-					     &attrib->name);
-		asn1_start_tag(msg->data, ASN1_SET);
+		if (!asn1_start_tag(msg->data, ASN1_SEQUENCE(0))) return false;
+		if (!asn1_read_OctetString_talloc(msg->attribs, msg->data,
+					     &attrib->name)) return false;
+		if (!asn1_start_tag(msg->data, ASN1_SET)) return false;
 
 		while (asn1_peek_tag(msg->data, ASN1_OCTET_STRING)) {
-			asn1_read_OctetString(msg->data, msg,
-					      &attrib->values[num_values]);
+			if (!asn1_read_OctetString(msg->data, msg,
+					      &attrib->values[num_values])) return false;
 
 			attrib->values = talloc_realloc(
 				msg->attribs, attrib->values, DATA_BLOB,
@@ -1941,8 +1954,8 @@ static bool tldap_parse_search_entry(struct tldap_message *msg)
 						DATA_BLOB, num_values);
 		attrib->num_values = num_values;
 
-		asn1_end_tag(msg->data); /* ASN1_SET */
-		asn1_end_tag(msg->data); /* ASN1_SEQUENCE(0) */
+		if (!asn1_end_tag(msg->data)) return false; /* ASN1_SET */
+		if (!asn1_end_tag(msg->data)) return false; /* ASN1_SEQUENCE(0) */
 		msg->attribs = talloc_realloc(
 			msg, msg->attribs, struct tldap_attribute,
 			num_attribs + 2);
@@ -1953,11 +1966,7 @@ static bool tldap_parse_search_entry(struct tldap_message *msg)
 	}
 	msg->attribs = talloc_realloc(
 		msg, msg->attribs, struct tldap_attribute, num_attribs);
-	asn1_end_tag(msg->data);
-	if (msg->data->has_error) {
-		return false;
-	}
-	return true;
+	return asn1_end_tag(msg->data);
 }
 
 bool tldap_entry_dn(struct tldap_message *msg, char **dn)
@@ -1987,6 +1996,7 @@ static bool tldap_decode_controls(struct tldap_req_state *state)
 	struct asn1_data *data = msg->data;
 	struct tldap_control *sctrls = NULL;
 	int num_controls = 0;
+	bool ret = false;
 
 	msg->res_sctrls = NULL;
 
@@ -1994,7 +2004,7 @@ static bool tldap_decode_controls(struct tldap_req_state *state)
 		return true;
 	}
 
-	asn1_start_tag(data, ASN1_CONTEXT(0));
+	if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto out;
 
 	while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
 		struct tldap_control *c;
@@ -2003,39 +2013,43 @@ static bool tldap_decode_controls(struct tldap_req_state *state)
 		sctrls = talloc_realloc(msg, sctrls, struct tldap_control,
 					num_controls + 1);
 		if (sctrls == NULL) {
-			return false;
+			goto out;
 		}
 		c = &sctrls[num_controls];
 
-		asn1_start_tag(data, ASN1_SEQUENCE(0));
-		asn1_read_OctetString_talloc(msg, data, &oid);
+		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto out;
+		if (!asn1_read_OctetString_talloc(msg, data, &oid)) goto out;
 		if ((data->has_error) || (oid == NULL)) {
-			return false;
+			goto out;
 		}
 		c->oid = oid;
 		if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
-			asn1_read_BOOLEAN(data, &c->critical);
+			if (!asn1_read_BOOLEAN(data, &c->critical)) goto out;
 		} else {
 			c->critical = false;
 		}
 		c->value = data_blob_null;
 		if (asn1_peek_tag(data, ASN1_OCTET_STRING) &&
 		    !asn1_read_OctetString(data, msg, &c->value)) {
-			return false;
+			goto out;
 		}
-		asn1_end_tag(data); /* ASN1_SEQUENCE(0) */
+		if (!asn1_end_tag(data)) goto out; /* ASN1_SEQUENCE(0) */
 
 		num_controls += 1;
 	}
 
-	asn1_end_tag(data); 	/* ASN1_CONTEXT(0) */
+	if (!asn1_end_tag(data)) goto out; 	/* ASN1_CONTEXT(0) */
 
-	if (data->has_error) {
+	ret = true;
+
+ out:
+
+	if (ret == false) {
 		TALLOC_FREE(sctrls);
-		return false;
+	} else {
+		msg->res_sctrls = sctrls;
 	}
-	msg->res_sctrls = sctrls;
-	return true;
+	return ret;
 }
 
 static void tldap_simple_done(struct tevent_req *subreq, int type)
@@ -2101,27 +2115,27 @@ struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	asn1_push_tag(state->out, TLDAP_REQ_ADD);
-	asn1_write_OctetString(state->out, dn, strlen(dn));
-	asn1_push_tag(state->out, ASN1_SEQUENCE(0));
+	if (!asn1_push_tag(state->out, TLDAP_REQ_ADD)) goto err;
+	if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
+	if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
 
 	for (i=0; i<num_attributes; i++) {
 		struct tldap_mod *attrib = &attributes[i];
-		asn1_push_tag(state->out, ASN1_SEQUENCE(0));
-		asn1_write_OctetString(state->out, attrib->attribute,
-				       strlen(attrib->attribute));
-		asn1_push_tag(state->out, ASN1_SET);
+		if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
+		if (!asn1_write_OctetString(state->out, attrib->attribute,
+				       strlen(attrib->attribute))) goto err;
+		if (!asn1_push_tag(state->out, ASN1_SET)) goto err;
 		for (j=0; j<attrib->num_values; j++) {
-			asn1_write_OctetString(state->out,
+			if (!asn1_write_OctetString(state->out,
 					       attrib->values[j].data,
-					       attrib->values[j].length);
+					       attrib->values[j].length)) goto err;
 		}
-		asn1_pop_tag(state->out);
-		asn1_pop_tag(state->out);
+		if (!asn1_pop_tag(state->out)) goto err;
+		if (!asn1_pop_tag(state->out)) goto err;
 	}
 
-	asn1_pop_tag(state->out);
-	asn1_pop_tag(state->out);
+	if (!asn1_pop_tag(state->out)) goto err;
+	if (!asn1_pop_tag(state->out)) goto err;
 
 	subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
 				sctrls, num_sctrls);
@@ -2130,6 +2144,11 @@ struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx,
 	}
 	tevent_req_set_callback(subreq, tldap_add_done, req);
 	return req;
+
+  err:
+
+	tevent_req_error(req, TLDAP_ENCODING_ERROR);
+	return tevent_req_post(req, ev);
 }
 
 static void tldap_add_done(struct tevent_req *subreq)
@@ -2198,30 +2217,30 @@ struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	asn1_push_tag(state->out, TLDAP_REQ_MODIFY);
-	asn1_write_OctetString(state->out, dn, strlen(dn));
-	asn1_push_tag(state->out, ASN1_SEQUENCE(0));
+	if (!asn1_push_tag(state->out, TLDAP_REQ_MODIFY)) goto err;
+	if (!asn1_write_OctetString(state->out, dn, strlen(dn))) goto err;
+	if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
 
 	for (i=0; i<num_mods; i++) {
 		struct tldap_mod *mod = &mods[i];
-		asn1_push_tag(state->out, ASN1_SEQUENCE(0));
-		asn1_write_enumerated(state->out, mod->mod_op),
-		asn1_push_tag(state->out, ASN1_SEQUENCE(0));
-		asn1_write_OctetString(state->out, mod->attribute,
-				       strlen(mod->attribute));
-		asn1_push_tag(state->out, ASN1_SET);
+		if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
+		if (!asn1_write_enumerated(state->out, mod->mod_op)) goto err;
+		if (!asn1_push_tag(state->out, ASN1_SEQUENCE(0))) goto err;
+		if (!asn1_write_OctetString(state->out, mod->attribute,
+				       strlen(mod->attribute))) goto err;
+		if (!asn1_push_tag(state->out, ASN1_SET)) goto err;
 		for (j=0; j<mod->num_values; j++) {
-			asn1_write_OctetString(state->out,
+			if (!asn1_write_OctetString(state->out,
 					       mod->values[j].data,
-					       mod->values[j].length);
+					       mod->values[j].length)) goto err;
 		}
-		asn1_pop_tag(state->out);
-		asn1_pop_tag(state->out);
-		asn1_pop_tag(state->out);
+		if (!asn1_pop_tag(state->out)) goto err;
+		if (!asn1_pop_tag(state->out)) goto err;
+		if (!asn1_pop_tag(state->out)) goto err;
 	}
 
-	asn1_pop_tag(state->out);
-	asn1_pop_tag(state->out);
+	if (!asn1_pop_tag(state->out)) goto err;
+	if (!asn1_pop_tag(state->out)) goto err;
 
 	subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
 				sctrls, num_sctrls);
@@ -2230,6 +2249,11 @@ struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx,
 	}
 	tevent_req_set_callback(subreq, tldap_modify_done, req);
 	return req;
+
+  err:
+
+	tevent_req_error(req, TLDAP_ENCODING_ERROR);
+	return tevent_req_post(req, ev);
 }
 
 static void tldap_modify_done(struct tevent_req *subreq)
@@ -2296,9 +2320,9 @@ struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
-	asn1_push_tag(state->out, TLDAP_REQ_DELETE);
-	asn1_write(state->out, dn, strlen(dn));
-	asn1_pop_tag(state->out);
+	if (!asn1_push_tag(state->out, TLDAP_REQ_DELETE)) goto err;
+	if (!asn1_write(state->out, dn, strlen(dn))) goto err;
+	if (!asn1_pop_tag(state->out)) goto err;
 
 	subreq = tldap_msg_send(state, ev, ld, state->id, state->out,
 				sctrls, num_sctrls);
@@ -2307,6 +2331,11 @@ struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx,
 	}
 	tevent_req_set_callback(subreq, tldap_delete_done, req);
 	return req;
+
+  err:
+
+	tevent_req_error(req, TLDAP_ENCODING_ERROR);
+	return tevent_req_post(req, ev);
 }
 
 static void tldap_delete_done(struct tevent_req *subreq)
-- 
2.1.0.rc2.206.gedb03e5


From b1095a02faedab2c003fd6c1f7b4a87b51a1b217 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 19 Sep 2014 15:16:38 -0700
Subject: [PATCH 7/8] s4: auth: gensec: asn1 fixes - check all returns.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source4/auth/gensec/gensec_krb5.c | 41 +++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index 237a263..c34c434 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -403,30 +403,31 @@ static NTSTATUS gensec_fake_gssapi_krb5_client_start(struct gensec_security *gen
 static DATA_BLOB gensec_gssapi_gen_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *ticket, const uint8_t tok_id[2])
 {
 	struct asn1_data *data;
-	DATA_BLOB ret;
+	DATA_BLOB ret = data_blob_null;
 
 	data = asn1_init(mem_ctx);
 	if (!data || !ticket->data) {
-		return data_blob(NULL,0);
+		return ret;
 	}
 
-	asn1_push_tag(data, ASN1_APPLICATION(0));
-	asn1_write_OID(data, GENSEC_OID_KERBEROS5);
+	if (!asn1_push_tag(data, ASN1_APPLICATION(0))) goto err;
+	if (!asn1_write_OID(data, GENSEC_OID_KERBEROS5)) goto err;
 
-	asn1_write(data, tok_id, 2);
-	asn1_write(data, ticket->data, ticket->length);
-	asn1_pop_tag(data);
+	if (!asn1_write(data, tok_id, 2)) goto err;
+	if (!asn1_write(data, ticket->data, ticket->length)) goto err;
+	if (!asn1_pop_tag(data)) goto err;
 
-	if (data->has_error) {
-		DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data->ofs));
-		asn1_free(data);
-		return data_blob(NULL,0);
-	}
 
 	ret = data_blob_talloc(mem_ctx, data->data, data->length);
 	asn1_free(data);
 
 	return ret;
+
+  err:
+
+	DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data->ofs));
+	asn1_free(data);
+	return ret;
 }
 
 /*
@@ -434,7 +435,7 @@ static DATA_BLOB gensec_gssapi_gen_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLO
 */
 static bool gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, DATA_BLOB *ticket, uint8_t tok_id[2])
 {
-	bool ret;
+	bool ret = false;
 	struct asn1_data *data = asn1_init(mem_ctx);
 	int data_remaining;
 
@@ -442,25 +443,27 @@ static bool gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *
 		return false;
 	}
 
-	asn1_load(data, *blob);
-	asn1_start_tag(data, ASN1_APPLICATION(0));
-	asn1_check_OID(data, GENSEC_OID_KERBEROS5);
+	if (!asn1_load(data, *blob)) goto err;
+	if (!asn1_start_tag(data, ASN1_APPLICATION(0))) goto err;
+	if (!asn1_check_OID(data, GENSEC_OID_KERBEROS5)) goto err;
 
 	data_remaining = asn1_tag_remaining(data);
 
 	if (data_remaining < 3) {
 		data->has_error = true;
 	} else {
-		asn1_read(data, tok_id, 2);
+		if (!asn1_read(data, tok_id, 2)) goto err;
 		data_remaining -= 2;
 		*ticket = data_blob_talloc(mem_ctx, NULL, data_remaining);
-		asn1_read(data, ticket->data, ticket->length);
+		if (!asn1_read(data, ticket->data, ticket->length)) goto err;
 	}
 
-	asn1_end_tag(data);
+	if (!asn1_end_tag(data)) goto err;
 
 	ret = !data->has_error;
 
+  err:
+
 	asn1_free(data);
 
 	return ret;
-- 
2.1.0.rc2.206.gedb03e5


From 56c341de29aac856f5dd8bf219ac86353e7e21d7 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 19 Sep 2014 15:21:06 -0700
Subject: [PATCH 8/8] s3: tldap_util: Ensure all asn1_XX returns are checked.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/lib/tldap_util.c | 43 +++++++++++++++++++++++--------------------
 1 file changed, 23 insertions(+), 20 deletions(-)

diff --git a/source3/lib/tldap_util.c b/source3/lib/tldap_util.c
index 1ffb264..45bf19f 100644
--- a/source3/lib/tldap_util.c
+++ b/source3/lib/tldap_util.c
@@ -635,28 +635,23 @@ static struct tevent_req *tldap_ship_paged_search(
 	struct tldap_search_paged_state *state)
 {
 	struct tldap_control *pgctrl;
-	struct asn1_data *asn1;
+	struct asn1_data *asn1 = NULL;
 
 	asn1 = asn1_init(state);
 	if (asn1 == NULL) {
 		return NULL;
 	}
-	asn1_push_tag(asn1, ASN1_SEQUENCE(0));
-	asn1_write_Integer(asn1, state->page_size);
-	asn1_write_OctetString(asn1, state->cookie.data, state->cookie.length);
-	asn1_pop_tag(asn1);
-	if (asn1->has_error) {
-		TALLOC_FREE(asn1);
-		return NULL;
-	}
+	if (!asn1_push_tag(asn1, ASN1_SEQUENCE(0))) goto err;
+	if (!asn1_write_Integer(asn1, state->page_size)) goto err;
+	if (!asn1_write_OctetString(asn1, state->cookie.data, state->cookie.length)) goto err;
+	if (!asn1_pop_tag(asn1)) goto err;
 	state->asn1 = asn1;
 
 	pgctrl = &state->sctrls[state->num_sctrls-1];
 	pgctrl->oid = TLDAP_CONTROL_PAGEDRESULTS;
 	pgctrl->critical = true;
 	if (!asn1_blob(state->asn1, &pgctrl->value)) {
-		TALLOC_FREE(asn1);
-		return NULL;
+		goto err;
 	}
 	return tldap_search_send(mem_ctx, state->ev, state->ld, state->base,
 				 state->scope, state->filter, state->attrs,
@@ -665,6 +660,11 @@ static struct tevent_req *tldap_ship_paged_search(
 				 state->cctrls, state->num_cctrls,
 				 state->timelimit, state->sizelimit,
 				 state->deref);
+
+  err:
+
+	TALLOC_FREE(asn1);
+	return NULL;
 }
 
 static void tldap_search_paged_done(struct tevent_req *subreq);
@@ -737,7 +737,7 @@ static void tldap_search_paged_done(struct tevent_req *subreq)
 		subreq, struct tevent_req);
 	struct tldap_search_paged_state *state = tevent_req_data(
 		req, struct tldap_search_paged_state);
-	struct asn1_data *asn1;
+	struct asn1_data *asn1 = NULL;
 	struct tldap_control *pgctrl;
 	int rc, size;
 
@@ -784,14 +784,11 @@ static void tldap_search_paged_done(struct tevent_req *subreq)
 	}
 
 	asn1_load_nocopy(asn1, pgctrl->value.data, pgctrl->value.length);
-	asn1_start_tag(asn1, ASN1_SEQUENCE(0));
-	asn1_read_Integer(asn1, &size);
-	asn1_read_OctetString(asn1, state, &state->cookie);
-	asn1_end_tag(asn1);
-	if (asn1->has_error) {
-		tevent_req_error(req, TLDAP_DECODING_ERROR);
-		return;
-	}
+	if (!asn1_start_tag(asn1, ASN1_SEQUENCE(0))) goto err;
+	if (!asn1_read_Integer(asn1, &size)) goto err;
+	if (!asn1_read_OctetString(asn1, state, &state->cookie)) goto err;
+	if (!asn1_end_tag(asn1)) goto err;
+
 	TALLOC_FREE(asn1);
 
 	if (state->cookie.length == 0) {
@@ -807,6 +804,12 @@ static void tldap_search_paged_done(struct tevent_req *subreq)
 		return;
 	}
 	tevent_req_set_callback(subreq, tldap_search_paged_done, req);
+
+  err:
+
+	TALLOC_FREE(asn1);
+	tevent_req_error(req, TLDAP_DECODING_ERROR);
+	return;
 }
 
 int tldap_search_paged_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
-- 
2.1.0.rc2.206.gedb03e5



More information about the samba-technical mailing list