CVE-2015-5330: ldb_dn: simplify and fix ldb_dn_escape_internal()
[samba.git] / lib / ldb / common / ldb_dn.c
index 6b6f90c13ea00914315fac90906eb888352372d7..1b8e51e499059d35d4f57de0163bde1e6d747c04 100644 (file)
@@ -189,33 +189,23 @@ struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx,
 /* see RFC2253 section 2.4 */
 static int ldb_dn_escape_internal(char *dst, const char *src, int len)
 {
 /* see RFC2253 section 2.4 */
 static int ldb_dn_escape_internal(char *dst, const char *src, int len)
 {
-       const char *p, *s;
+       char c;
        char *d;
        char *d;
-       size_t l;
-
-       p = s = src;
+       int i;
        d = dst;
 
        d = dst;
 
-       while (p - src < len) {
-               p += strcspn(p, ",=\n\r+<>#;\\\" ");
-
-               if (p - src == len) /* found no escapable chars */
-                       break;
-
-               /* copy the part of the string before the stop */
-               memcpy(d, s, p - s);
-               d += (p - s); /* move to current position */
-               
-               switch (*p) {
+       for (i = 0; i < len; i++){
+               c = src[i];
+               switch (c) {
                case ' ':
                case ' ':
-                       if (p == src || (p-src)==(len-1)) {
+                       if (i == 0 || i == len - 1) {
                                /* if at the beginning or end
                                 * of the string then escape */
                                *d++ = '\\';
                                /* if at the beginning or end
                                 * of the string then escape */
                                *d++ = '\\';
-                               *d++ = *p++;                                     
+                               *d++ = c;
                        } else {
                                /* otherwise don't escape */
                        } else {
                                /* otherwise don't escape */
-                               *d++ = *p++;
+                               *d++ = c;
                        }
                        break;
 
                        }
                        break;
 
@@ -231,30 +221,30 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len)
                case '?':
                        /* these must be escaped using \c form */
                        *d++ = '\\';
                case '?':
                        /* these must be escaped using \c form */
                        *d++ = '\\';
-                       *d++ = *p++;
+                       *d++ = c;
                        break;
 
                        break;
 
-               default: {
+               case ';':
+               case '\r':
+               case '\n':
+               case '=':
+               case '\0': {
                        /* any others get \XX form */
                        unsigned char v;
                        const char *hexbytes = "0123456789ABCDEF";
                        /* any others get \XX form */
                        unsigned char v;
                        const char *hexbytes = "0123456789ABCDEF";
-                       v = *(const unsigned char *)p;
+                       v = (const unsigned char)c;
                        *d++ = '\\';
                        *d++ = hexbytes[v>>4];
                        *d++ = hexbytes[v&0xF];
                        *d++ = '\\';
                        *d++ = hexbytes[v>>4];
                        *d++ = hexbytes[v&0xF];
-                       p++;
                        break;
                }
                        break;
                }
+               default:
+                       *d++ = c;
                }
                }
-               s = p; /* move forward */
        }
 
        }
 
-       /* copy the last part (with zero) and return */
-       l = len - (s - src);
-       memcpy(d, s, l + 1);
-
        /* return the length of the resulting string */
        /* return the length of the resulting string */
-       return (l + (d - dst));
+       return (d - dst);
 }
 
 char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value)
 }
 
 char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value)