From 4c35ffcf54d6f829c9bfe317308e301e99061acf Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Dec 09 2010 17:59:35 +0000 Subject: Bug 640027 - Naming attribute with a special char sequence parsing bug https://bugzilla.redhat.com/show_bug.cgi?id=640027 Description: When DN is made from RDNs containing escaped plus "\+", the dn normalizer considers the value could be nested multi- valued RDNs. (e.g., cn=C\=Z\+A\=X\+B\=Y\,o\=O,o=OO) In that case, multi-valued RDNs are sorted by the normalizer. (==> cn=A\=X\+B\=Y\+C\=Z\,o\=O,o=OO) The sample DN provided by Andrey Ivanov contains "\+", but that is not a separator for the multi-valued RDNs: cn=mytest\+\=-123'\;456,dc=example,dc=com The dn normalizer should have checked the possibility, as well. The check is added in this patch. Also, sorting was not triggered if multi-valued RDNs are located at the end of the value. (e.g., cn=C\=X\,B\=Y\+A\=Z,o=OO) The bug was fixed, as well. --- diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c index f02674d..0b74c4f 100644 --- a/ldap/servers/slapd/dn.c +++ b/ldap/servers/slapd/dn.c @@ -116,6 +116,11 @@ hexchar2int( char c ) #define ISCLOSEBRACKET(c) (((c) == ')') || ((c) == ']')) +#define MAYBEDN(eq) ( \ + (eq) && ((eq) != subtypestart) && \ + ((eq) != subtypestart + strlen(subtypestart) - 3) \ +) + #define B4TYPE 0 #define INTYPE 1 #define B4EQUAL 2 @@ -700,8 +705,19 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) */ if (subtypestart && (ISPLUS(*(s+1)) || subrdn_av_count > 0)) { - add_rdn_av(subtypestart, d, &subrdn_av_count, - &subrdn_avs, subinitial_rdn_av_stack); + /* if subtypestart is not valid DN, + * we do not do sorting.*/ + char *p = PL_strcasestr(subtypestart, "\\3d"); + if (MAYBEDN(p)) { + add_rdn_av(subtypestart, d, + &subrdn_av_count, + &subrdn_avs, + subinitial_rdn_av_stack); + } else { + reset_rdn_avs(&subrdn_avs, + &subrdn_av_count); + subtypestart = NULL; + } } if (!ISPLUS(*(s+1))) { /* at end of this RDN */ if (subrdn_av_count > 1) { @@ -723,8 +739,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) /* next type start of multi values */ /* should not be a escape char AND should be * followed by \\= or \\3D */ - if (!ISESCAPE(*s) && - (PL_strnstr(s, "\\=", ends - s) || + if ((PL_strnstr(s, "\\=", ends - s) || PL_strncaserstr(s, "\\3D", ends - s))) { subtypestart = d; } else { @@ -771,8 +786,16 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) */ if (subtypestart && (ISPLUSSTR(s+1) || subrdn_av_count > 0)) { - add_rdn_av(subtypestart, d, &subrdn_av_count, + /* if subtypestart is not valid DN, + * we do not do sorting.*/ + char *p = PL_strcasestr(subtypestart, "\\3d"); + if (MAYBEDN(p)) { + add_rdn_av(subtypestart, d, &subrdn_av_count, &subrdn_avs, subinitial_rdn_av_stack); + } else { + reset_rdn_avs( &subrdn_avs, &subrdn_av_count ); + subtypestart = NULL; + } } if (!ISPLUSSTR(s+1)) { /* at end of this RDN */ if (subrdn_av_count > 1) { @@ -923,8 +946,16 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) */ if (subtypestart && (ISPLUS(*s) || subrdn_av_count > 0)) { - add_rdn_av(subtypestart, d, &subrdn_av_count, + /* if subtypestart is not valid DN, + * we do not do sorting.*/ + char *p = PL_strcasestr(subtypestart, "\\3d"); + if (MAYBEDN(p)) { + add_rdn_av(subtypestart, d, &subrdn_av_count, &subrdn_avs, subinitial_rdn_av_stack); + } else { + reset_rdn_avs( &subrdn_avs, &subrdn_av_count ); + subtypestart = NULL; + } } if (!ISPLUS(*s)) { /* at end of this RDN */ if (subrdn_av_count > 1) { @@ -969,6 +1000,11 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) add_rdn_av(typestart, d, &rdn_av_count, &rdn_avs, initial_rdn_av_stack); } + /* Sub type sorting might be also ongoing */ + if (subtypestart && subrdn_av_count > 0) { + add_rdn_av(subtypestart, d, &subrdn_av_count, + &subrdn_avs, subinitial_rdn_av_stack); + } if (!ISPLUS(*s)) { /* at end of this RDN */ if (rdn_av_count > 1) { sort_rdn_avs( rdn_avs, rdn_av_count, 0 ); @@ -977,6 +1013,14 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) reset_rdn_avs( &rdn_avs, &rdn_av_count ); typestart = NULL; } + /* If in the middle of sub type sorting, finish it. */ + if (subrdn_av_count > 1) { + sort_rdn_avs( subrdn_avs, subrdn_av_count, 1 ); + } + if (subrdn_av_count > 0) { + reset_rdn_avs( &subrdn_avs, &subrdn_av_count ); + subtypestart = NULL; + } } *d++ = (ISPLUS(*s++)) ? '+' : ',';