[PATCH] asn1_XXXX error check fixups.

Jeremy Allison jra at samba.org
Tue Sep 23 13:47:34 MDT 2014


On Fri, Sep 19, 2014 at 04:01:56PM -0700, Jeremy Allison wrote:
> 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.

Finished version - completely protects
*all* uses of asn1_XXXX().

Review and push most appreciated !

Jeremy.
-------------- next part --------------
From 0c84df1ea4f2d94d7a65ea59cb64d067efebf245 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 01/10] 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 5a9f218dd1727f828c82ec4fdfcbfb651c9a2126 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 02/10] 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 97371bf7401fa570e7dae8a4d242657392f5a799 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 03/10] 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 3438f9b54ba2f042b68cf3568522b66e898e56b7 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 04/10] 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 12683680daa926e2d22bf12d9170f308d2dd0b86 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 05/10] 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 03de51af3e99a9155a74146890bea6f6dce192e8 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 06/10] 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 1535111418e3b6bed035c32c2b66d742b91e9b88 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 07/10] 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 ec94f0aa48f63a7feb871dafe0d52960ab640b38 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 08/10] 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


From 5c8ddc4957a36a168d0089a1f4b07e988216c50b Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 22 Sep 2014 13:28:18 -0700
Subject: [PATCH 09/10] s4: libcli: ldap controls - Ensure all asn1_XX returns
 are checked.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source4/libcli/ldap/ldap_controls.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/source4/libcli/ldap/ldap_controls.c b/source4/libcli/ldap/ldap_controls.c
index 17d96f6..1e67a01 100644
--- a/source4/libcli/ldap/ldap_controls.c
+++ b/source4/libcli/ldap/ldap_controls.c
@@ -1129,10 +1129,16 @@ static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
 			}
 		}
 		
-		asn1_pop_tag(data);
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) {
+			return false;
+		}
+		if (!asn1_pop_tag(data)) {
+			return false;
+		}
+	}
+	if (!asn1_pop_tag(data)) {
+		return false;
 	}
-	asn1_pop_tag(data);
 
 	*out = data_blob_talloc(mem_ctx, data->data, data->length);
 	if (out->data == NULL) {
@@ -1181,8 +1187,12 @@ static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
 			return false;
 		}
 		
-		asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute);
-		asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn);
+		if (!asn1_read_OctetString_talloc(r[i], data, &r[i]->source_attribute)) {
+			return false;
+		}
+		if (!asn1_read_OctetString_talloc(r[i], data, &r[i]->dereferenced_dn)) {
+			return false;
+		}
 		if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
 			if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
 				return false;
-- 
2.1.0.rc2.206.gedb03e5


From f2e19113f886d1d9c252f8afcabd67107fd6a13c Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 22 Sep 2014 16:08:26 -0700
Subject: [PATCH 10/10] s4: libcli: ldap message - Ensure all asn1_XX returns
 are checked.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 libcli/ldap/ldap_message.c          | 786 ++++++++++++++++++------------------
 libcli/ldap/ldap_message.h          |   2 +-
 source4/libcli/ldap/ldap_controls.c |   8 +-
 3 files changed, 401 insertions(+), 395 deletions(-)

diff --git a/libcli/ldap/ldap_message.c b/libcli/ldap/ldap_message.c
index 1c5542c..ba94f4c 100644
--- a/libcli/ldap/ldap_message.c
+++ b/libcli/ldap/ldap_message.c
@@ -229,31 +229,31 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
 	switch (tree->operation) {
 	case LDB_OP_AND:
 	case LDB_OP_OR:
-		asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1));
+		if (!asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1))) return false;
 		for (i=0; i<tree->u.list.num_elements; i++) {
 			if (!ldap_push_filter(data, tree->u.list.elements[i])) {
 				return false;
 			}
 		}
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	case LDB_OP_NOT:
-		asn1_push_tag(data, ASN1_CONTEXT(2));
+		if (!asn1_push_tag(data, ASN1_CONTEXT(2))) return false;
 		if (!ldap_push_filter(data, tree->u.isnot.child)) {
 			return false;
 		}
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	case LDB_OP_EQUALITY:
 		/* equality test */
-		asn1_push_tag(data, ASN1_CONTEXT(3));
-		asn1_write_OctetString(data, tree->u.equality.attr,
-				      strlen(tree->u.equality.attr));
-		asn1_write_OctetString(data, tree->u.equality.value.data,
-				      tree->u.equality.value.length);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false;
+		if (!asn1_write_OctetString(data, tree->u.equality.attr,
+				      strlen(tree->u.equality.attr))) return false;
+		if (!asn1_write_OctetString(data, tree->u.equality.value.data,
+				      tree->u.equality.value.length)) return false;
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	case LDB_OP_SUBSTRING:
@@ -266,16 +266,16 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
 				  any     [1] LDAPString,
 				  final   [2] LDAPString } }
 		*/
-		asn1_push_tag(data, ASN1_CONTEXT(4));
-		asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr));
-		asn1_push_tag(data, ASN1_SEQUENCE(0));
+		if (!asn1_push_tag(data, ASN1_CONTEXT(4))) return false;
+		if (!asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr))) return false;
+		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false;
 
 		if (tree->u.substring.chunks && tree->u.substring.chunks[0]) {
 			i = 0;
 			if (!tree->u.substring.start_with_wildcard) {
-				asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
-				asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
-				asn1_pop_tag(data);
+				if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) return false;
+				if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false;
+				if (!asn1_pop_tag(data)) return false;
 				i++;
 			}
 			while (tree->u.substring.chunks[i]) {
@@ -287,51 +287,51 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
 				} else {
 					ctx = 1;
 				}
-				asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx));
-				asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]);
-				asn1_pop_tag(data);
+				if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx))) return false;
+				if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false;
+				if (!asn1_pop_tag(data)) return false;
 				i++;
 			}
 		}
-		asn1_pop_tag(data);
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) return false;
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	case LDB_OP_GREATER:
 		/* greaterOrEqual test */
-		asn1_push_tag(data, ASN1_CONTEXT(5));
-		asn1_write_OctetString(data, tree->u.comparison.attr,
-				      strlen(tree->u.comparison.attr));
-		asn1_write_OctetString(data, tree->u.comparison.value.data,
-				      tree->u.comparison.value.length);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT(5))) return false;
+		if (!asn1_write_OctetString(data, tree->u.comparison.attr,
+				      strlen(tree->u.comparison.attr))) return false;
+		if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
+				      tree->u.comparison.value.length)) return false;
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	case LDB_OP_LESS:
 		/* lessOrEqual test */
-		asn1_push_tag(data, ASN1_CONTEXT(6));
-		asn1_write_OctetString(data, tree->u.comparison.attr,
-				      strlen(tree->u.comparison.attr));
-		asn1_write_OctetString(data, tree->u.comparison.value.data,
-				      tree->u.comparison.value.length);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT(6))) return false;
+		if (!asn1_write_OctetString(data, tree->u.comparison.attr,
+				      strlen(tree->u.comparison.attr))) return false;
+		if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
+				      tree->u.comparison.value.length)) return false;
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	case LDB_OP_PRESENT:
 		/* present test */
-		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7));
-		asn1_write_LDAPString(data, tree->u.present.attr);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7))) return false;
+		if (!asn1_write_LDAPString(data, tree->u.present.attr)) return false;
+		if (!asn1_pop_tag(data)) return false;
 		return !data->has_error;
 
 	case LDB_OP_APPROX:
 		/* approx test */
-		asn1_push_tag(data, ASN1_CONTEXT(8));
-		asn1_write_OctetString(data, tree->u.comparison.attr,
-				      strlen(tree->u.comparison.attr));
-		asn1_write_OctetString(data, tree->u.comparison.value.data,
-				      tree->u.comparison.value.length);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT(8))) return false;
+		if (!asn1_write_OctetString(data, tree->u.comparison.attr,
+				      strlen(tree->u.comparison.attr))) return false;
+		if (!asn1_write_OctetString(data, tree->u.comparison.value.data,
+				      tree->u.comparison.value.length)) return false;
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	case LDB_OP_EXTENDED:
@@ -343,24 +343,24 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
 		  dnAttributes    [4] BOOLEAN DEFAULT FALSE
 		  }
 		*/
-		asn1_push_tag(data, ASN1_CONTEXT(9));
+		if (!asn1_push_tag(data, ASN1_CONTEXT(9))) return false;
 		if (tree->u.extended.rule_id) {
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
-			asn1_write_LDAPString(data, tree->u.extended.rule_id);
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) return false;
+			if (!asn1_write_LDAPString(data, tree->u.extended.rule_id)) return false;
+			if (!asn1_pop_tag(data)) return false;
 		}
 		if (tree->u.extended.attr) {
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2));
-			asn1_write_LDAPString(data, tree->u.extended.attr);
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2))) return false;
+			if (!asn1_write_LDAPString(data, tree->u.extended.attr)) return false;
+			if (!asn1_pop_tag(data)) return false;
 		}
-		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3));
-		asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value);
-		asn1_pop_tag(data);
-		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4));
-		asn1_write_uint8(data, tree->u.extended.dnAttributes);
-		asn1_pop_tag(data);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3))) return false;
+		if (!asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value)) return false;
+		if (!asn1_pop_tag(data)) return false;
+		if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4))) return false;
+		if (!asn1_write_uint8(data, tree->u.extended.dnAttributes)) return false;
+		if (!asn1_pop_tag(data)) return false;
+		if (!asn1_pop_tag(data)) return false;
 		break;
 
 	default:
@@ -369,20 +369,21 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree
 	return !data->has_error;
 }
 
-static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
+static bool ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
 {
-	asn1_write_enumerated(data, result->resultcode);
-	asn1_write_OctetString(data, result->dn,
-			       (result->dn) ? strlen(result->dn) : 0);
-	asn1_write_OctetString(data, result->errormessage,
+	if (!asn1_write_enumerated(data, result->resultcode)) return false;
+	if (!asn1_write_OctetString(data, result->dn,
+			       (result->dn) ? strlen(result->dn) : 0)) return false;
+	if (!asn1_write_OctetString(data, result->errormessage,
 			       (result->errormessage) ?
-			       strlen(result->errormessage) : 0);
+			       strlen(result->errormessage) : 0)) return false;
 	if (result->referral) {
-		asn1_push_tag(data, ASN1_CONTEXT(3));
-		asn1_write_OctetString(data, result->referral,
-				       strlen(result->referral));
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false;
+		if (!asn1_write_OctetString(data, result->referral,
+				       strlen(result->referral))) return false;
+		if (!asn1_pop_tag(data)) return false;
 	}
+	return true;
 }
 
 _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
@@ -394,286 +395,286 @@ _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
 
 	if (!data) return false;
 
-	asn1_push_tag(data, ASN1_SEQUENCE(0));
-	asn1_write_Integer(data, msg->messageid);
+	if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
+	if (!asn1_write_Integer(data, msg->messageid)) goto err;
 
 	switch (msg->type) {
 	case LDAP_TAG_BindRequest: {
 		struct ldap_BindRequest *r = &msg->r.BindRequest;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_write_Integer(data, r->version);
-		asn1_write_OctetString(data, r->dn,
-				       (r->dn != NULL) ? strlen(r->dn) : 0);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_write_Integer(data, r->version)) goto err;
+		if (!asn1_write_OctetString(data, r->dn,
+				       (r->dn != NULL) ? strlen(r->dn) : 0)) goto err;
 
 		switch (r->mechanism) {
 		case LDAP_AUTH_MECH_SIMPLE:
 			/* context, primitive */
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
-			asn1_write(data, r->creds.password,
-				   strlen(r->creds.password));
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
+			if (!asn1_write(data, r->creds.password,
+				   strlen(r->creds.password))) goto err;
+			if (!asn1_pop_tag(data)) goto err;
 			break;
 		case LDAP_AUTH_MECH_SASL:
 			/* context, constructed */
-			asn1_push_tag(data, ASN1_CONTEXT(3));
-			asn1_write_OctetString(data, r->creds.SASL.mechanism,
-					       strlen(r->creds.SASL.mechanism));
+			if (!asn1_push_tag(data, ASN1_CONTEXT(3))) goto err;
+			if (!asn1_write_OctetString(data, r->creds.SASL.mechanism,
+					       strlen(r->creds.SASL.mechanism))) goto err;
 			if (r->creds.SASL.secblob) {
-				asn1_write_OctetString(data, r->creds.SASL.secblob->data,
-						       r->creds.SASL.secblob->length);
+				if (!asn1_write_OctetString(data, r->creds.SASL.secblob->data,
+						       r->creds.SASL.secblob->length)) goto err;
 			}
-			asn1_pop_tag(data);
+			if (!asn1_pop_tag(data)) goto err;
 			break;
 		default:
-			return false;
+			goto err;
 		}
 
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_BindResponse: {
 		struct ldap_BindResponse *r = &msg->r.BindResponse;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		ldap_encode_response(data, &r->response);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!ldap_encode_response(data, &r->response)) goto err;
 		if (r->SASL.secblob) {
-			asn1_write_ContextSimple(data, 7, r->SASL.secblob);
+			if (!asn1_write_ContextSimple(data, 7, r->SASL.secblob)) goto err;
 		}
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_UnbindRequest: {
 /*		struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
-		asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_SearchRequest: {
 		struct ldap_SearchRequest *r = &msg->r.SearchRequest;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_write_OctetString(data, r->basedn, strlen(r->basedn));
-		asn1_write_enumerated(data, r->scope);
-		asn1_write_enumerated(data, r->deref);
-		asn1_write_Integer(data, r->sizelimit);
-		asn1_write_Integer(data, r->timelimit);
-		asn1_write_BOOLEAN(data, r->attributesonly);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_write_OctetString(data, r->basedn, strlen(r->basedn))) goto err;
+		if (!asn1_write_enumerated(data, r->scope)) goto err;
+		if (!asn1_write_enumerated(data, r->deref)) goto err;
+		if (!asn1_write_Integer(data, r->sizelimit)) goto err;
+		if (!asn1_write_Integer(data, r->timelimit)) goto err;
+		if (!asn1_write_BOOLEAN(data, r->attributesonly)) goto err;
 
 		if (!ldap_push_filter(data, r->tree)) {
-			return false;
+			goto err;
 		}
 
-		asn1_push_tag(data, ASN1_SEQUENCE(0));
+		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
 		for (i=0; i<r->num_attributes; i++) {
-			asn1_write_OctetString(data, r->attributes[i],
-					       strlen(r->attributes[i]));
+			if (!asn1_write_OctetString(data, r->attributes[i],
+					       strlen(r->attributes[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;
 		break;
 	}
 	case LDAP_TAG_SearchResultEntry: {
 		struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_write_OctetString(data, r->dn, strlen(r->dn));
-		asn1_push_tag(data, ASN1_SEQUENCE(0));
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
+		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
 		for (i=0; i<r->num_attributes; i++) {
 			struct ldb_message_element *attr = &r->attributes[i];
-			asn1_push_tag(data, ASN1_SEQUENCE(0));
-			asn1_write_OctetString(data, attr->name,
-					       strlen(attr->name));
-			asn1_push_tag(data, ASN1_SEQUENCE(1));
+			if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
+			if (!asn1_write_OctetString(data, attr->name,
+					       strlen(attr->name))) goto err;
+			if (!asn1_push_tag(data, ASN1_SEQUENCE(1))) goto err;
 			for (j=0; j<attr->num_values; j++) {
-				asn1_write_OctetString(data,
+				if (!asn1_write_OctetString(data,
 						       attr->values[j].data,
-						       attr->values[j].length);
+						       attr->values[j].length)) 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);
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_SearchResultDone: {
 		struct ldap_Result *r = &msg->r.SearchResultDone;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		ldap_encode_response(data, r);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!ldap_encode_response(data, r)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_ModifyRequest: {
 		struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_write_OctetString(data, r->dn, strlen(r->dn));
-		asn1_push_tag(data, ASN1_SEQUENCE(0));
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
+		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
 
 		for (i=0; i<r->num_mods; i++) {
 			struct ldb_message_element *attrib = &r->mods[i].attrib;
-			asn1_push_tag(data, ASN1_SEQUENCE(0));
-			asn1_write_enumerated(data, r->mods[i].type);
-			asn1_push_tag(data, ASN1_SEQUENCE(0));
-			asn1_write_OctetString(data, attrib->name,
-					       strlen(attrib->name));
-			asn1_push_tag(data, ASN1_SET);
+			if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
+			if (!asn1_write_enumerated(data, r->mods[i].type)) goto err;
+			if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
+			if (!asn1_write_OctetString(data, attrib->name,
+					       strlen(attrib->name))) goto err;
+			if (!asn1_push_tag(data, ASN1_SET)) goto err;
 			for (j=0; j<attrib->num_values; j++) {
-				asn1_write_OctetString(data,
+				if (!asn1_write_OctetString(data,
 						       attrib->values[j].data,
-						       attrib->values[j].length);
+						       attrib->values[j].length)) goto err;
 	
 			}
-			asn1_pop_tag(data);
-			asn1_pop_tag(data);
-			asn1_pop_tag(data);
+			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;
 		break;
 	}
 	case LDAP_TAG_ModifyResponse: {
 		struct ldap_Result *r = &msg->r.ModifyResponse;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		ldap_encode_response(data, r);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!ldap_encode_response(data, r)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_AddRequest: {
 		struct ldap_AddRequest *r = &msg->r.AddRequest;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_write_OctetString(data, r->dn, strlen(r->dn));
-		asn1_push_tag(data, ASN1_SEQUENCE(0));
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
+		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
 
 		for (i=0; i<r->num_attributes; i++) {
 			struct ldb_message_element *attrib = &r->attributes[i];
-			asn1_push_tag(data, ASN1_SEQUENCE(0));
-			asn1_write_OctetString(data, attrib->name,
-					       strlen(attrib->name));
-			asn1_push_tag(data, ASN1_SET);
+			if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
+			if (!asn1_write_OctetString(data, attrib->name,
+					       strlen(attrib->name))) goto err;
+			if (!asn1_push_tag(data, ASN1_SET)) goto err;
 			for (j=0; j<r->attributes[i].num_values; j++) {
-				asn1_write_OctetString(data,
+				if (!asn1_write_OctetString(data,
 						       attrib->values[j].data,
-						       attrib->values[j].length);
+						       attrib->values[j].length)) 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);
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_AddResponse: {
 		struct ldap_Result *r = &msg->r.AddResponse;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		ldap_encode_response(data, r);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!ldap_encode_response(data, r)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_DelRequest: {
 		struct ldap_DelRequest *r = &msg->r.DelRequest;
-		asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
-		asn1_write(data, r->dn, strlen(r->dn));
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
+		if (!asn1_write(data, r->dn, strlen(r->dn))) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_DelResponse: {
 		struct ldap_Result *r = &msg->r.DelResponse;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		ldap_encode_response(data, r);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!ldap_encode_response(data, r)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_ModifyDNRequest: {
 		struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_write_OctetString(data, r->dn, strlen(r->dn));
-		asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn));
-		asn1_write_BOOLEAN(data, r->deleteolddn);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
+		if (!asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn))) goto err;
+		if (!asn1_write_BOOLEAN(data, r->deleteolddn)) goto err;
 		if (r->newsuperior) {
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
-			asn1_write(data, r->newsuperior,
-				   strlen(r->newsuperior));
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
+			if (!asn1_write(data, r->newsuperior,
+				   strlen(r->newsuperior))) goto err;
+			if (!asn1_pop_tag(data)) goto err;
 		}
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_ModifyDNResponse: {
 		struct ldap_Result *r = &msg->r.ModifyDNResponse;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		ldap_encode_response(data, r);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!ldap_encode_response(data, r)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_CompareRequest: {
 		struct ldap_CompareRequest *r = &msg->r.CompareRequest;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_write_OctetString(data, r->dn, strlen(r->dn));
-		asn1_push_tag(data, ASN1_SEQUENCE(0));
-		asn1_write_OctetString(data, r->attribute,
-				       strlen(r->attribute));
-		asn1_write_OctetString(data, r->value.data,
-				       r->value.length);
-		asn1_pop_tag(data);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err;
+		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
+		if (!asn1_write_OctetString(data, r->attribute,
+				       strlen(r->attribute))) goto err;
+		if (!asn1_write_OctetString(data, r->value.data,
+				       r->value.length)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_CompareResponse: {
 		struct ldap_Result *r = &msg->r.ModifyDNResponse;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		ldap_encode_response(data, r);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!ldap_encode_response(data, r)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_AbandonRequest: {
 		struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
-		asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type));
-		asn1_write_implicit_Integer(data, r->messageid);
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err;
+		if (!asn1_write_implicit_Integer(data, r->messageid)) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_SearchResultReference: {
 		struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_write_OctetString(data, r->referral, strlen(r->referral));
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_write_OctetString(data, r->referral, strlen(r->referral))) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_ExtendedRequest: {
 		struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0));
-		asn1_write(data, r->oid, strlen(r->oid));
-		asn1_pop_tag(data);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err;
+		if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
+		if (!asn1_pop_tag(data)) goto err;
 		if (r->value) {
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1));
-			asn1_write(data, r->value->data, r->value->length);
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto err;
+			if (!asn1_write(data, r->value->data, r->value->length)) goto err;
+			if (!asn1_pop_tag(data)) goto err;
 		}
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	case LDAP_TAG_ExtendedResponse: {
 		struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
-		asn1_push_tag(data, ASN1_APPLICATION(msg->type));
-		ldap_encode_response(data, &r->response);
+		if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err;
+		if (!ldap_encode_response(data, &r->response)) goto err;
 		if (r->oid) {
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10));
-			asn1_write(data, r->oid, strlen(r->oid));
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10))) goto err;
+			if (!asn1_write(data, r->oid, strlen(r->oid))) goto err;
+			if (!asn1_pop_tag(data)) goto err;
 		}
 		if (r->value) {
-			asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11));
-			asn1_write(data, r->value->data, r->value->length);
-			asn1_pop_tag(data);
+			if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11))) goto err;
+			if (!asn1_write(data, r->value->data, r->value->length)) goto err;
+			if (!asn1_pop_tag(data)) goto err;
 		}
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) goto err;
 		break;
 	}
 	default:
-		return false;
+		goto err;
 	}
 
 	if (msg->controls != NULL) {
-		asn1_push_tag(data, ASN1_CONTEXT(0));
+		if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err;
 		
 		for (i = 0; msg->controls[i] != NULL; i++) {
 			if (!ldap_encode_control(mem_ctx, data,
@@ -681,23 +682,24 @@ _PUBLIC_ bool ldap_encode(struct ldap_message *msg,
 						 msg->controls[i])) {
 				DEBUG(0,("Unable to encode control %s\n",
 					 msg->controls[i]->oid));
-				return false;
+				goto err;
 			}
 		}
 
-		asn1_pop_tag(data);
+		if (!asn1_pop_tag(data)) goto err;
 	}
 
-	asn1_pop_tag(data);
-
-	if (data->has_error) {
-		asn1_free(data);
-		return false;
-	}
+	if (!asn1_pop_tag(data)) goto err;
 
 	*result = data_blob_talloc(mem_ctx, data->data, data->length);
 	asn1_free(data);
+
 	return true;
+
+  err:
+
+	asn1_free(data);
+	return false;
 }
 
 static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
@@ -721,20 +723,21 @@ bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
 	return true;
 }
 
-static void ldap_decode_response(TALLOC_CTX *mem_ctx,
+static bool ldap_decode_response(TALLOC_CTX *mem_ctx,
 				 struct asn1_data *data,
 				 struct ldap_Result *result)
 {
-	asn1_read_enumerated(data, &result->resultcode);
-	asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
-	asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
+	if (!asn1_read_enumerated(data, &result->resultcode)) return false;
+	if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->dn)) return false;
+	if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage)) return false;
 	if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
-		asn1_start_tag(data, ASN1_CONTEXT(3));
-		asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(3))) return false;
+		if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->referral)) return false;
+		if (!asn1_end_tag(data)) return false;
 	} else {
 		result->referral = NULL;
 	}
+	return true;
 }
 
 static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value)
@@ -835,10 +838,10 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		const char *attrib;
 		DATA_BLOB value;
 
-		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
-		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
-		asn1_read_OctetString(data, mem_ctx, &value);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
+		if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
+		if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
+		if (!asn1_end_tag(data)) goto failed;
 		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
 			goto failed;
 		}
@@ -874,13 +877,13 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		}
 
 		while (asn1_tag_remaining(data)) {
-			asn1_peek_uint8(data, &subs_tag);
+			if (!asn1_peek_uint8(data, &subs_tag)) goto failed;
 			subs_tag &= 0x1f;	/* strip off the asn1 stuff */
 			if (subs_tag > 2) goto failed;
 
-			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));
-			asn1_read_LDAPString(data, mem_ctx, &value);
-			asn1_end_tag(data);
+			if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag))) goto failed;
+			if (!asn1_read_LDAPString(data, mem_ctx, &value)) goto failed;
+			if (!asn1_end_tag(data)) goto failed;
 
 			switch (subs_tag) {
 			case 0:
@@ -947,10 +950,10 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		const char *attrib;
 		DATA_BLOB value;
 
-		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
-		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
-		asn1_read_OctetString(data, mem_ctx, &value);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
+		if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
+		if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
+		if (!asn1_end_tag(data)) goto failed;
 		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
 			goto failed;
 		}
@@ -966,10 +969,10 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		const char *attrib;
 		DATA_BLOB value;
 
-		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
-		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
-		asn1_read_OctetString(data, mem_ctx, &value);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
+		if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
+		if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
+		if (!asn1_end_tag(data)) goto failed;
 		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
 			goto failed;
 		}
@@ -1004,10 +1007,10 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		const char *attrib;
 		DATA_BLOB value;
 
-		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));
-		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);
-		asn1_read_OctetString(data, mem_ctx, &value);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed;
+		if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed;
+		if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed;
+		if (!asn1_end_tag(data)) goto failed;
 		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {
 			goto failed;
 		}
@@ -1030,18 +1033,18 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		   we need to check we properly implement --SSS */ 
 		/* either oid or type must be defined */
 		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */
-			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));
-			asn1_read_LDAPString(data, ret, &oid);
-			asn1_end_tag(data);
+			if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto failed;
+			if (!asn1_read_LDAPString(data, ret, &oid)) goto failed;
+			if (!asn1_end_tag(data)) goto failed;
 		}
 		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) {	/* optional  */
-			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));
-			asn1_read_LDAPString(data, ret, &attr);
-			asn1_end_tag(data);
+			if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2))) goto failed;
+			if (!asn1_read_LDAPString(data, ret, &attr)) goto failed;
+			if (!asn1_end_tag(data)) goto failed;
 		}
-		asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));
-		asn1_read_LDAPString(data, ret, &value);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3))) goto failed;
+		if (!asn1_read_LDAPString(data, ret, &value)) goto failed;
+		if (!asn1_end_tag(data)) goto failed;
 		/* dnAttributes is marked as BOOLEAN DEFAULT FALSE
 		   it is not marked as OPTIONAL but openldap tools
 		   do not set this unless it is to be set as TRUE
@@ -1049,9 +1052,9 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
 		   seems that AD always requires the dnAttributes
 		   boolean value to be set */
 		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {
-			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));
-			asn1_read_uint8(data, &dnAttributes);
-			asn1_end_tag(data);
+			if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4))) goto failed;
+			if (!asn1_read_uint8(data, &dnAttributes)) goto failed;
+			if (!asn1_end_tag(data)) goto failed;
 		} else {
 			dnAttributes = 0;
 		}
@@ -1099,45 +1102,45 @@ failed:
 }
 
 /* Decode a single LDAP attribute, possibly containing multiple values */
-static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
+static bool ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
 			       struct ldb_message_element *attrib)
 {
-	asn1_start_tag(data, ASN1_SEQUENCE(0));
-	asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);
-	asn1_start_tag(data, ASN1_SET);
+	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
+	if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name)) return false;
+	if (!asn1_start_tag(data, ASN1_SET)) return false;
 	while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
 		DATA_BLOB blob;
-		asn1_read_OctetString(data, mem_ctx, &blob);
+		if (!asn1_read_OctetString(data, mem_ctx, &blob)) return false;
 		add_value_to_attrib(mem_ctx, &blob, attrib);
 	}
-	asn1_end_tag(data);
-	asn1_end_tag(data);
-	
+	if (!asn1_end_tag(data)) return false;
+	return asn1_end_tag(data);
 }
 
 /* Decode a set of LDAP attributes, as found in the dereference control */
-void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
+bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
 			      struct ldb_message_element **attributes,
 			      int *num_attributes)
 {
 	while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
 		struct ldb_message_element attrib;
 		ZERO_STRUCT(attrib);
-		ldap_decode_attrib(mem_ctx, data, &attrib);
+		if (!ldap_decode_attrib(mem_ctx, data, &attrib)) return false;
 		add_attrib_to_array_talloc(mem_ctx, &attrib,
 					   attributes, num_attributes);
 	}
+	return true;
 }
 
 /* Decode a set of LDAP attributes, as found in a search entry */
-static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
+static bool ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
 				struct ldb_message_element **attributes,
 				int *num_attributes)
 {
-	asn1_start_tag(data, ASN1_SEQUENCE(0));
-	ldap_decode_attribs_bare(mem_ctx, data, 
-				 attributes, num_attributes);
-	asn1_end_tag(data);
+	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false;
+	if (!ldap_decode_attribs_bare(mem_ctx, data,
+				 attributes, num_attributes)) return false;
+	return asn1_end_tag(data);
 }
 
 /* This routine returns LDAP status codes */
@@ -1148,46 +1151,45 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 {
 	uint8_t tag;
 
-	asn1_start_tag(data, ASN1_SEQUENCE(0));
-	asn1_read_Integer(data, &msg->messageid);
+	if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
+	if (!asn1_read_Integer(data, &msg->messageid)) goto prot_err;
 
-	if (!asn1_peek_uint8(data, &tag))
-		return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+	if (!asn1_peek_uint8(data, &tag)) goto prot_err;
 
 	switch(tag) {
 
 	case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
 		struct ldap_BindRequest *r = &msg->r.BindRequest;
 		msg->type = LDAP_TAG_BindRequest;
-		asn1_start_tag(data, tag);
-		asn1_read_Integer(data, &r->version);
-		asn1_read_OctetString_talloc(msg, data, &r->dn);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!asn1_read_Integer(data, &r->version)) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
 		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
 			int pwlen;
 			r->creds.password = "";
 			r->mechanism = LDAP_AUTH_MECH_SIMPLE;
-			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
+			if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
 			pwlen = asn1_tag_remaining(data);
 			if (pwlen == -1) {
-				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+				goto prot_err;
 			}
 			if (pwlen != 0) {
 				char *pw = talloc_array(msg, char, pwlen+1);
 				if (!pw) {
 					return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
 				}
-				asn1_read(data, pw, pwlen);
+				if (!asn1_read(data, pw, pwlen)) goto prot_err;
 				pw[pwlen] = '\0';
 				r->creds.password = pw;
 			}
-			asn1_end_tag(data);
+			if (!asn1_end_tag(data)) goto prot_err;
 		} else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
-			asn1_start_tag(data, ASN1_CONTEXT(3));
+			if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto prot_err;
 			r->mechanism = LDAP_AUTH_MECH_SASL;
-			asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism);
+			if (!asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism)) goto prot_err;
 			if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */
 				DATA_BLOB tmp_blob = data_blob(NULL, 0);
-				asn1_read_OctetString(data, msg, &tmp_blob);
+				if (!asn1_read_OctetString(data, msg, &tmp_blob)) goto prot_err;
 				r->creds.SASL.secblob = talloc(msg, DATA_BLOB);
 				if (!r->creds.SASL.secblob) {
 					return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
@@ -1198,23 +1200,23 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 			} else {
 				r->creds.SASL.secblob = NULL;
 			}
-			asn1_end_tag(data);
+			if (!asn1_end_tag(data)) goto prot_err;
 		} else {
 			/* Neither Simple nor SASL bind */
-			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+			goto prot_err;
 		}
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
 		struct ldap_BindResponse *r = &msg->r.BindResponse;
 		msg->type = LDAP_TAG_BindResponse;
-		asn1_start_tag(data, tag);
-		ldap_decode_response(msg, data, &r->response);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
 		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
 			DATA_BLOB tmp_blob = data_blob(NULL, 0);
-			asn1_read_ContextSimple(data, 7, &tmp_blob);
+			if (!asn1_read_ContextSimple(data, 7, &tmp_blob)) goto prot_err;
 			r->SASL.secblob = talloc(msg, DATA_BLOB);
 			if (!r->SASL.secblob) {
 				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
@@ -1225,14 +1227,14 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		} else {
 			r->SASL.secblob = NULL;
 		}
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
 		msg->type = LDAP_TAG_UnbindRequest;
-		asn1_start_tag(data, tag);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
@@ -1241,41 +1243,41 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		int sizelimit, timelimit;
 		const char **attrs = NULL;
 		msg->type = LDAP_TAG_SearchRequest;
-		asn1_start_tag(data, tag);
-		asn1_read_OctetString_talloc(msg, data, &r->basedn);
-		asn1_read_enumerated(data, (int *)(void *)&(r->scope));
-		asn1_read_enumerated(data, (int *)(void *)&(r->deref));
-		asn1_read_Integer(data, &sizelimit);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->basedn)) goto prot_err;
+		if (!asn1_read_enumerated(data, (int *)(void *)&(r->scope))) goto prot_err;
+		if (!asn1_read_enumerated(data, (int *)(void *)&(r->deref))) goto prot_err;
+		if (!asn1_read_Integer(data, &sizelimit)) goto prot_err;
 		r->sizelimit = sizelimit;
-		asn1_read_Integer(data, &timelimit);
+		if (!asn1_read_Integer(data, &timelimit)) goto prot_err;
 		r->timelimit = timelimit;
-		asn1_read_BOOLEAN(data, &r->attributesonly);
+		if (!asn1_read_BOOLEAN(data, &r->attributesonly)) goto prot_err;
 
 		r->tree = ldap_decode_filter_tree(msg, data);
 		if (r->tree == NULL) {
-			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+			goto prot_err;
 		}
 
-		asn1_start_tag(data, ASN1_SEQUENCE(0));
+		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
 
 		r->num_attributes = 0;
 		r->attributes = NULL;
 
-		while (asn1_tag_remaining(data) > 0) {					
+		while (asn1_tag_remaining(data) > 0) {
 
 			const char *attr;
 			if (!asn1_read_OctetString_talloc(msg, data,
 							  &attr))
-				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+				goto prot_err;
 			if (!add_string_to_array(msg, attr,
 						 &attrs,
 						 &r->num_attributes))
-				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+				goto prot_err;
 		}
 		r->attributes = attrs;
 
-		asn1_end_tag(data);
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
@@ -1284,38 +1286,38 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		msg->type = LDAP_TAG_SearchResultEntry;
 		r->attributes = NULL;
 		r->num_attributes = 0;
-		asn1_start_tag(data, tag);
-		asn1_read_OctetString_talloc(msg, data, &r->dn);
-		ldap_decode_attribs(msg, data, &r->attributes,
-				    &r->num_attributes);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
+		if (!ldap_decode_attribs(msg, data, &r->attributes,
+				    &r->num_attributes)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
 		struct ldap_Result *r = &msg->r.SearchResultDone;
 		msg->type = LDAP_TAG_SearchResultDone;
-		asn1_start_tag(data, tag);
-		ldap_decode_response(msg, data, r);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!ldap_decode_response(msg, data, r)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
 		struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
 		msg->type = LDAP_TAG_SearchResultReference;
-		asn1_start_tag(data, tag);
-		asn1_read_OctetString_talloc(msg, data, &r->referral);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->referral)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): {
 		struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
 		msg->type = LDAP_TAG_ModifyRequest;
-		asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
-		asn1_read_OctetString_talloc(msg, data, &r->dn);
-		asn1_start_tag(data, ASN1_SEQUENCE(0));
+		if (!asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest))) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
+		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
 
 		r->num_mods = 0;
 		r->mods = NULL;
@@ -1324,52 +1326,52 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 			struct ldap_mod mod;
 			int v;
 			ZERO_STRUCT(mod);
-			asn1_start_tag(data, ASN1_SEQUENCE(0));
-			asn1_read_enumerated(data, &v);
+			if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
+			if (!asn1_read_enumerated(data, &v)) goto prot_err;
 			mod.type = v;
-			ldap_decode_attrib(msg, data, &mod.attrib);
-			asn1_end_tag(data);
+			if (!ldap_decode_attrib(msg, data, &mod.attrib)) goto prot_err;
+			if (!asn1_end_tag(data)) goto prot_err;
 			if (!add_mod_to_array_talloc(msg, &mod,
 						     &r->mods, &r->num_mods)) {
 				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
 			}
 		}
 
-		asn1_end_tag(data);
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
 		struct ldap_Result *r = &msg->r.ModifyResponse;
 		msg->type = LDAP_TAG_ModifyResponse;
-		asn1_start_tag(data, tag);
-		ldap_decode_response(msg, data, r);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!ldap_decode_response(msg, data, r)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
 		struct ldap_AddRequest *r = &msg->r.AddRequest;
 		msg->type = LDAP_TAG_AddRequest;
-		asn1_start_tag(data, tag);
-		asn1_read_OctetString_talloc(msg, data, &r->dn);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
 
 		r->attributes = NULL;
 		r->num_attributes = 0;
-		ldap_decode_attribs(msg, data, &r->attributes,
-				    &r->num_attributes);
+		if (!ldap_decode_attribs(msg, data, &r->attributes,
+				    &r->num_attributes)) goto prot_err;
 
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
 		struct ldap_Result *r = &msg->r.AddResponse;
 		msg->type = LDAP_TAG_AddResponse;
-		asn1_start_tag(data, tag);
-		ldap_decode_response(msg, data, r);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!ldap_decode_response(msg, data, r)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
@@ -1378,102 +1380,102 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		int len;
 		char *dn;
 		msg->type = LDAP_TAG_DelRequest;
-		asn1_start_tag(data,
-			       ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
+		if (!asn1_start_tag(data,
+			       ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest))) goto prot_err;
 		len = asn1_tag_remaining(data);
 		if (len == -1) {
-			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+			goto prot_err;
 		}
 		dn = talloc_array(msg, char, len+1);
 		if (dn == NULL)
 			break;
-		asn1_read(data, dn, len);
+		if (!asn1_read(data, dn, len)) goto prot_err;
 		dn[len] = '\0';
 		r->dn = dn;
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
 		struct ldap_Result *r = &msg->r.DelResponse;
 		msg->type = LDAP_TAG_DelResponse;
-		asn1_start_tag(data, tag);
-		ldap_decode_response(msg, data, r);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!ldap_decode_response(msg, data, r)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): {
 		struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
 		msg->type = LDAP_TAG_ModifyDNRequest;
-		asn1_start_tag(data,
-			       ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
-		asn1_read_OctetString_talloc(msg, data, &r->dn);
-		asn1_read_OctetString_talloc(msg, data, &r->newrdn);
-		asn1_read_BOOLEAN(data, &r->deleteolddn);
+		if (!asn1_start_tag(data,
+			       ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest))) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->newrdn)) goto prot_err;
+		if (!asn1_read_BOOLEAN(data, &r->deleteolddn)) goto prot_err;
 		r->newsuperior = NULL;
 		if (asn1_tag_remaining(data) > 0) {
 			int len;
 			char *newsup;
-			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
+			if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err;
 			len = asn1_tag_remaining(data);
 			if (len == -1) {
-				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+				goto prot_err;
 			}
 			newsup = talloc_array(msg, char, len+1);
 			if (newsup == NULL) {
 				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
 			}
-			asn1_read(data, newsup, len);
+			if (!asn1_read(data, newsup, len)) goto prot_err;
 			newsup[len] = '\0';
 			r->newsuperior = newsup;
-			asn1_end_tag(data);
+			if (!asn1_end_tag(data)) goto prot_err;
 		}
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
 		struct ldap_Result *r = &msg->r.ModifyDNResponse;
 		msg->type = LDAP_TAG_ModifyDNResponse;
-		asn1_start_tag(data, tag);
-		ldap_decode_response(msg, data, r);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!ldap_decode_response(msg, data, r)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
 		struct ldap_CompareRequest *r = &msg->r.CompareRequest;
 		msg->type = LDAP_TAG_CompareRequest;
-		asn1_start_tag(data,
-			       ASN1_APPLICATION(LDAP_TAG_CompareRequest));
-		asn1_read_OctetString_talloc(msg, data, &r->dn);
-		asn1_start_tag(data, ASN1_SEQUENCE(0));
-		asn1_read_OctetString_talloc(msg, data, &r->attribute);
-		asn1_read_OctetString(data, msg, &r->value);
+		if (!asn1_start_tag(data,
+			       ASN1_APPLICATION(LDAP_TAG_CompareRequest))) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err;
+		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err;
+		if (!asn1_read_OctetString_talloc(msg, data, &r->attribute)) goto prot_err;
+		if (!asn1_read_OctetString(data, msg, &r->value)) goto prot_err;
 		if (r->value.data) {
 			talloc_steal(msg, r->value.data);
 		}
-		asn1_end_tag(data);
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
 		struct ldap_Result *r = &msg->r.CompareResponse;
 		msg->type = LDAP_TAG_CompareResponse;
-		asn1_start_tag(data, tag);
-		ldap_decode_response(msg, data, r);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!ldap_decode_response(msg, data, r)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
 	case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
 		struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
 		msg->type = LDAP_TAG_AbandonRequest;
-		asn1_start_tag(data, tag);
-		asn1_read_implicit_Integer(data, &r->messageid);
-		asn1_end_tag(data);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!asn1_read_implicit_Integer(data, &r->messageid)) goto prot_err;
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
@@ -1482,9 +1484,9 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		DATA_BLOB tmp_blob = data_blob(NULL, 0);
 
 		msg->type = LDAP_TAG_ExtendedRequest;
-		asn1_start_tag(data,tag);
+		if (!asn1_start_tag(data,tag)) goto prot_err;
 		if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
-			return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+			goto prot_err;
 		}
 		r->oid = blob2string_talloc(msg, tmp_blob);
 		data_blob_free(&tmp_blob);
@@ -1493,7 +1495,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		}
 
 		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) {
-			asn1_read_ContextSimple(data, 1, &tmp_blob);
+			if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
 			r->value = talloc(msg, DATA_BLOB);
 			if (!r->value) {
 				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
@@ -1504,7 +1506,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 			r->value = NULL;
 		}
 
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
 
@@ -1513,11 +1515,11 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		DATA_BLOB tmp_blob = data_blob(NULL, 0);
 
 		msg->type = LDAP_TAG_ExtendedResponse;
-		asn1_start_tag(data, tag);		
-		ldap_decode_response(msg, data, &r->response);
+		if (!asn1_start_tag(data, tag)) goto prot_err;
+		if (!ldap_decode_response(msg, data, &r->response)) goto prot_err;
 
 		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) {
-			asn1_read_ContextSimple(data, 1, &tmp_blob);
+			if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
 			r->oid = blob2string_talloc(msg, tmp_blob);
 			data_blob_free(&tmp_blob);
 			if (!r->oid) {
@@ -1528,7 +1530,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		}
 
 		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) {
-			asn1_read_ContextSimple(data, 1, &tmp_blob);
+			if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err;
 			r->value = talloc(msg, DATA_BLOB);
 			if (!r->value) {
 				return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR);
@@ -1539,11 +1541,11 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 			r->value = NULL;
 		}
 
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
 		break;
 	}
-	default: 
-		return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+	default:
+		goto prot_err;
 	}
 
 	msg->controls = NULL;
@@ -1554,7 +1556,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		struct ldb_control **ctrl = NULL;
 		bool *decoded = NULL;
 
-		asn1_start_tag(data, ASN1_CONTEXT(0));
+		if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto prot_err;
 
 		while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {
 			DATA_BLOB value;
@@ -1576,9 +1578,9 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 			}
 
 			if (!ldap_decode_control_wrapper(ctrl[i], data, ctrl[i], &value)) {
-				return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+				goto prot_err;
 			}
-			
+
 			if (!ldap_decode_control_value(ctrl[i], value,
 						       control_handlers,
 						       ctrl[i])) {
@@ -1603,14 +1605,18 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
 		msg->controls = ctrl;
 		msg->controls_decoded = decoded;
 
-		asn1_end_tag(data);
+		if (!asn1_end_tag(data)) goto prot_err;
 	}
 
-	asn1_end_tag(data);
+	if (!asn1_end_tag(data)) goto prot_err;
 	if ((data->has_error) || (data->nesting != NULL)) {
 		return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
 	}
 	return NT_STATUS_OK;
+
+  prot_err:
+
+	return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
 }
 
 
diff --git a/libcli/ldap/ldap_message.h b/libcli/ldap/ldap_message.h
index eb7e620..4385fe6 100644
--- a/libcli/ldap/ldap_message.h
+++ b/libcli/ldap/ldap_message.h
@@ -228,7 +228,7 @@ bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
 				  struct asn1_data *data,
 				  const char **result);
 
-void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
+bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
 			      struct ldb_message_element **attributes,
 			      int *num_attributes);
 
diff --git a/source4/libcli/ldap/ldap_controls.c b/source4/libcli/ldap/ldap_controls.c
index 1e67a01..f910acb 100644
--- a/source4/libcli/ldap/ldap_controls.c
+++ b/source4/libcli/ldap/ldap_controls.c
@@ -1197,10 +1197,10 @@ static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
 			if (!asn1_start_tag(data, ASN1_CONTEXT(0))) {
 				return false;
 			}
-			
-			ldap_decode_attribs_bare(r, data, &r[i]->attributes,
-						 &r[i]->num_attributes);
-			
+			if (!ldap_decode_attribs_bare(r, data, &r[i]->attributes,
+						 &r[i]->num_attributes)) {
+				return false;
+			}
 			if (!asn1_end_tag(data)) {
 				return false;
 			}
-- 
2.1.0.rc2.206.gedb03e5



More information about the samba-technical mailing list