Adam Tkac 7f4ce0
From f345805c73c294db42452ae966c48fbc36c48006 Mon Sep 17 00:00:00 2001
Adam Tkac 7f4ce0
From: Petr Spacek <pspacek@redhat.com>
Adam Tkac 7f4ce0
Date: Fri, 20 Jul 2012 14:55:43 +0200
Adam Tkac 7f4ce0
Subject: [PATCH] Fix and harden DNS-to-LDAP name conversion. Fixes
Adam Tkac 7f4ce0
 CVE-2012-3429.
Adam Tkac 7f4ce0
Adam Tkac 7f4ce0
Signed-off-by: Petr Spacek <pspacek@redhat.com>
Adam Tkac 7f4ce0
---
Adam Tkac 7f4ce0
 src/ldap_convert.c | 44 +++++++++++++++++++++++++++++++++-----------
Adam Tkac 7f4ce0
 1 file changed, 33 insertions(+), 11 deletions(-)
Adam Tkac 7f4ce0
Adam Tkac 7f4ce0
diff --git a/src/ldap_convert.c b/src/ldap_convert.c
Adam Tkac 7f4ce0
index 6b4e321..3352c57 100644
Adam Tkac 7f4ce0
--- a/src/ldap_convert.c
Adam Tkac 7f4ce0
+++ b/src/ldap_convert.c
Adam Tkac 7f4ce0
@@ -192,16 +192,23 @@ cleanup:
Adam Tkac 7f4ce0
 }
Adam Tkac 7f4ce0
 
Adam Tkac 7f4ce0
 /**
Adam Tkac 7f4ce0
+ * WARNING! This function is used to mangle input from network
Adam Tkac 7f4ce0
+ *          and it is security sensitive.
Adam Tkac 7f4ce0
+ *
Adam Tkac 7f4ce0
  * Convert a string from DNS escaping to LDAP escaping.
Adam Tkac 7f4ce0
  * The Input string dns_str is expected to be the result of dns_name_tostring().
Adam Tkac 7f4ce0
  * The DNS label can contain any binary data as described in
Adam Tkac 7f4ce0
  * http://tools.ietf.org/html/rfc2181#section-11 .
Adam Tkac 7f4ce0
  *
Adam Tkac 7f4ce0
- * DNS escaping uses form   "\123" = ASCII value 123 (decimal)
Adam Tkac 7f4ce0
+ * DNS escaping uses 2 forms: (see dns_name_totext2() in bind/lib/dns/name.c)
Adam Tkac 7f4ce0
+ *     form "\123" = ASCII value 123 (decimal)
Adam Tkac 7f4ce0
+ *     form "\$" = character '$' is escaped with '\'
Adam Tkac 7f4ce0
+ *     WARNING! Some characters are not escaped at all (e.g. ',').
Adam Tkac 7f4ce0
+ *
Adam Tkac 7f4ce0
  * LDAP escaping users form "\7b"  = ASCII value 7b (hexadecimal)
Adam Tkac 7f4ce0
  *
Adam Tkac 7f4ce0
- * Input (DNS escaped) example  : _aaa,bbb\255\000ccc.555.ddd-eee
Adam Tkac 7f4ce0
- * Output (LDAP escaped) example: _aaa\2cbbb\ff\00ccc.555.ddd-eee
Adam Tkac 7f4ce0
+ * Input  (DNS escaped)  example: \$.\255_aaa,bbb\127\000ccc.555.ddd-eee
Adam Tkac 7f4ce0
+ * Output (LDAP escaped) example: \24.\ff_aaa\2cbbb\7f\00ccc.555.ddd-eee
Adam Tkac 7f4ce0
  *
Adam Tkac 7f4ce0
  * The DNS to text functions from ISC libraries do not convert certain
Adam Tkac 7f4ce0
  * characters (e.g. ","). This function converts \123 form to \7b form in all
Adam Tkac 7f4ce0
@@ -248,13 +255,23 @@ dns_to_ldap_dn_escape(isc_mem_t *mctx, const char const * dns_str, char ** ldap_
Adam Tkac 7f4ce0
 			}
Adam Tkac 7f4ce0
 			if (dns_str[dns_idx] != '\\') { /* not nice raw value, e.g. ',' */
Adam Tkac 7f4ce0
 				ascii_val = dns_str[dns_idx];
Adam Tkac 7f4ce0
-			} else { /* not nice value in DNS \123 decimal format */
Adam Tkac 7f4ce0
-				/* check if input length <= expected size */
Adam Tkac 7f4ce0
-				REQUIRE (dns_str_len > dns_idx + 3); /* this problem should never happen */
Adam Tkac 7f4ce0
-				ascii_val = 100 * (dns_str[dns_idx + 1] - '0')
Adam Tkac 7f4ce0
-						+ 10 * (dns_str[dns_idx + 2] - '0')
Adam Tkac 7f4ce0
-						+ (dns_str[dns_idx + 3] - '0');
Adam Tkac 7f4ce0
-				dns_idx += 3;
Adam Tkac 7f4ce0
+			} else { /* DNS escaped value, it starts with '\' */
Adam Tkac 7f4ce0
+				if (!(dns_idx + 1 < dns_str_len)) {
Adam Tkac 7f4ce0
+					CHECK(DNS_R_BADESCAPE); /* this problem should never happen */
Adam Tkac 7f4ce0
+				}
Adam Tkac 7f4ce0
+				if (isdigit(dns_str[dns_idx + 1])) { /* \123 decimal format */
Adam Tkac 7f4ce0
+					/* check if input length <= expected size */
Adam Tkac 7f4ce0
+					if (!(dns_idx + 3 < dns_str_len)) {
Adam Tkac 7f4ce0
+						CHECK(DNS_R_BADESCAPE); /* this problem should never happen */
Adam Tkac 7f4ce0
+					}
Adam Tkac 7f4ce0
+					ascii_val = 100 * (dns_str[dns_idx + 1] - '0')
Adam Tkac 7f4ce0
+							+ 10 * (dns_str[dns_idx + 2] - '0')
Adam Tkac 7f4ce0
+							+ (dns_str[dns_idx + 3] - '0');
Adam Tkac 7f4ce0
+					dns_idx += 3;
Adam Tkac 7f4ce0
+				} else { /* \$ single char format */
Adam Tkac 7f4ce0
+					ascii_val = dns_str[dns_idx + 1];
Adam Tkac 7f4ce0
+					dns_idx += 1;
Adam Tkac 7f4ce0
+				}
Adam Tkac 7f4ce0
 			}
Adam Tkac 7f4ce0
 			/* LDAP uses \xy escaping. "xy" represent two hexadecimal digits.*/
Adam Tkac 7f4ce0
 			/* TODO: optimize to bit mask & rotate & dec->hex table? */
Adam Tkac 7f4ce0
@@ -272,8 +289,13 @@ dns_to_ldap_dn_escape(isc_mem_t *mctx, const char const * dns_str, char ** ldap_
Adam Tkac 7f4ce0
 	return ISC_R_SUCCESS;
Adam Tkac 7f4ce0
 
Adam Tkac 7f4ce0
 cleanup:
Adam Tkac 7f4ce0
-	if (*ldap_name)
Adam Tkac 7f4ce0
+	if (result == DNS_R_BADESCAPE)
Adam Tkac 7f4ce0
+		log_bug("improperly escaped DNS string: '%s'", dns_str);
Adam Tkac 7f4ce0
+
Adam Tkac 7f4ce0
+	if (*ldap_name) {
Adam Tkac 7f4ce0
 		isc_mem_free(mctx, *ldap_name);
Adam Tkac 7f4ce0
+		*ldap_name = NULL;
Adam Tkac 7f4ce0
+	}
Adam Tkac 7f4ce0
 	return result;
Adam Tkac 7f4ce0
 }
Adam Tkac 7f4ce0
 
Adam Tkac 7f4ce0
-- 
Adam Tkac 7f4ce0
1.7.11.2
Adam Tkac 7f4ce0