From bfe31ac30e4dec8a2b850c5a60180d02674a8207 Mon Sep 17 00:00:00 2001 From: Nathan Kinder Date: Dec 07 2010 22:29:57 +0000 Subject: Bug 641944 - Don't normalize non-DN RDN values Our current DN normalization code assumes that a RDN value can contain a DN pointer. It also normalizes this RDN value as a DN, regardless of the syntax of the RDN attribute type. This causes non-DN RDN values to get messed up. This patch makes the DN normalization code only normalize a RDN value as a DN for an attribute type that is defined to use the Distinguished Name syntax. --- diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c index 97a9c92..05db7af 100644 --- a/ldap/servers/slapd/attr.c +++ b/ldap/servers/slapd/attr.c @@ -964,5 +964,9 @@ done: const char * attr_get_syntax_oid(const Slapi_Attr *attr) { - return attr->a_plugin->plg_syntax_oid; + if (attr->a_plugin) { + return attr->a_plugin->plg_syntax_oid; + } else { + return NULL; + } } diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c index 1940b8d..456f830 100644 --- a/ldap/servers/slapd/attrsyntax.c +++ b/ldap/servers/slapd/attrsyntax.c @@ -822,15 +822,13 @@ slapi_attr_get_syntax_oid_copy( const Slapi_Attr *a, char **oidp ) int slapi_attr_is_dn_syntax_attr(Slapi_Attr *attr) { - char *syntaxoid = NULL; + const char *syntaxoid = NULL; int dn_syntax = 0; /* not DN, by default */ - if (attr->a_plugin) { /* If not set, there is no way to get the info */ - slapi_attr_get_syntax_oid_copy(attr, &syntaxoid); - if (syntaxoid) { + if (attr && attr->a_plugin) { /* If not set, there is no way to get the info */ + if (syntaxoid = attr_get_syntax_oid(attr)) { dn_syntax = ((0 == strcmp(syntaxoid, NAMEANDOPTIONALUID_SYNTAX_OID)) || (0 == strcmp(syntaxoid, DN_SYNTAX_OID))); - slapi_ch_free_string(&syntaxoid); } } return dn_syntax; diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c index 48d92eb..914712a 100644 --- a/ldap/servers/slapd/dn.c +++ b/ldap/servers/slapd/dn.c @@ -515,6 +515,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) struct berval *subrdn_avs = NULL; struct berval subinitial_rdn_av_stack[ SLAPI_DNNORM_INITIAL_RDN_AVS ]; int chkblank = 0; + int is_dn_syntax = 0; if (NULL == dest) { goto bail; @@ -562,12 +563,63 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) case INTYPE: /* in type; cn=... */ /* ^ */ if (ISEQUAL(*s)) { + /* See if the type is defined to use + * the Distinguished Name syntax. */ + char savechar; + Slapi_Attr test_attr; + + /* We need typestart to be a string containing only + * the type. We terminate the type and then reset + * the string after we check the syntax. */ + savechar = *d; + *d = '\0'; + + slapi_attr_init(&test_attr, typestart); + is_dn_syntax = slapi_attr_is_dn_syntax_attr(&test_attr); + + /* Reset the character we modified. */ + *d = savechar; + state = B4VALUE; *d++ = *s++; } else if (ISCLOSEBRACKET(*s)) { /* special care for ACL macro */ + /* See if the type is defined to use + * the Distinguished Name syntax. */ + char savechar; + Slapi_Attr test_attr; + + /* We need typestart to be a string containing only + * the type. We terminate the type and then reset + * the string after we check the syntax. */ + savechar = *d; + *d = '\0'; + + slapi_attr_init(&test_attr, typestart); + is_dn_syntax = slapi_attr_is_dn_syntax_attr(&test_attr); + + /* Reset the character we modified. */ + *d = savechar; + state = INVALUE; /* skip a trailing space */ *d++ = *s++; } else if (ISSPACE(*s)) { + /* See if the type is defined to use + * the Distinguished Name syntax. */ + char savechar; + Slapi_Attr test_attr; + + /* We need typestart to be a string containing only + * the type. We terminate the type and then reset + * the string after we check the syntax. */ + savechar = *d; + *d = '\0'; + + slapi_attr_init(&test_attr, typestart); + is_dn_syntax = slapi_attr_is_dn_syntax_attr(&test_attr); + + /* Reset the character we modified. */ + *d = savechar; + state = B4EQUAL; /* skip a trailing space */ } else if (ISQUOTE(*s) || SEPARATOR(*s)) { /* type includes quote / separator; not a valid dn */ @@ -615,7 +667,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) rc = -1; goto bail; } /* otherwise, go through */ - if (ISESCAPE(*s)) { + if (!is_dn_syntax || ISESCAPE(*s)) { subtypestart = NULL; /* if escaped, can't be multivalued dn */ } else { subtypestart = d; /* prepare for '+' in the nested DN, if any */ @@ -636,12 +688,12 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) rc = -1; goto bail; } else { - if (ISEQUAL(*(s+1))) { + if (ISEQUAL(*(s+1)) && is_dn_syntax) { while (ISSPACE(*(d-1))) { /* remove trailing spaces */ d--; } - } else if (SEPARATOR(*(s+1))) { + } else if (SEPARATOR(*(s+1)) && is_dn_syntax) { /* separator is a subset of needsescape */ while (ISSPACE(*(d-1))) { /* remove trailing spaces */ @@ -691,7 +743,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) *d++ = *s++; /* '\\' */ PR_snprintf(d, 3, "%X", *s); /* hexpair */ d += 2; - if (ISPLUS(*s)) { + if (ISPLUS(*s) && is_dn_syntax) { /* next type start of multi values */ /* should not be a escape char AND should be * followed by \\= or \\3D */ @@ -702,7 +754,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) subtypestart = NULL; } } - if (SEPARATOR(*s) || ISEQUAL(*s)) { + if ((SEPARATOR(*s) || ISEQUAL(*s)) && is_dn_syntax) { while (ISSPACE(*(s+1))) s++; /* remove leading spaces */ s++; @@ -717,12 +769,12 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) (ISEOV(s+3, ends) && ISBLANKSTR(s+1))))) { /* e.g., cn=abc\20 ,... */ /* ^ */ - if (ISEQUALSTR(s+1)) { + if (ISEQUALSTR(s+1) && is_dn_syntax) { while (ISSPACE(*(d-1))) { /* remove trailing spaces */ d--; } - } else if (SEPARATORSTR(s+1)) { + } else if (SEPARATORSTR(s+1) && is_dn_syntax) { /* separator is a subset of needsescape */ while (ISSPACE(*(d-1))) { /* remove trailing spaces */ @@ -766,7 +818,7 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) *d++ = *s++; /* '\\' */ *d++ = *s++; /* HEX */ *d++ = *s++; /* HEX */ - if (ISPLUSSTR(s-2)) { + if (ISPLUSSTR(s-2) && is_dn_syntax) { /* next type start of multi values */ /* should not be a escape char AND should be followed * by \\= or \\3D */ @@ -777,9 +829,10 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) subtypestart = NULL; } } - if (SEPARATORSTR(s-2) || ISEQUALSTR(s-2)) { - while (ISSPACE(*s)) /* remove leading spaces */ + if ((SEPARATORSTR(s-2) || ISEQUALSTR(s-2)) && is_dn_syntax) { + while (ISSPACE(*s)) {/* remove leading spaces */ s++; + } } } else if (s + 2 < ends && isxdigit(*(s+1)) && isxdigit(*(s+2))) { @@ -836,26 +889,36 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) s++; continue; } - subtypestart = d; /* prepare for '+' in the quoted value, if any */ + if (is_dn_syntax) { + subtypestart = d; /* prepare for '+' in the quoted value, if any */ + } subrdn_av_count = 0; case INQUOTEDVALUE: if (ISQUOTE(*s)) { if (ISESCAPE(*(d-1))) { /* the quote is escaped */ PR_snprintf(d, 3, "%X", *(s++)); /* hexpair */ } else { /* end of INQUOTEVALUE */ - while (ISSPACE(*(d-1))) { /* eliminate trailing spaces */ + if (is_dn_syntax) { + while (ISSPACE(*(d-1))) { /* eliminate trailing spaces */ + d--; + chkblank = 1; + } + /* We have to keep the last ' ' of a value in quotes. + * The same idea as the escaped last space: + * "cn=A,ou=B " */ + /* ^ */ + if (chkblank && ISBLANK(*d)) { + PR_snprintf(d, 4, "\\%X", *d); /* hexpair */ + d += 3; + chkblank = 0; + } + } else if (ISSPACE(*(d-1))) { + /* Convert last trailing space to hex code */ d--; - chkblank = 1; - } - /* We have to keep the last ' ' of a value in quotes. - * The same idea as the escaped last space: - * "cn=A,ou=B " */ - /* ^ */ - if (chkblank && ISBLANK(*d)) { PR_snprintf(d, 4, "\\%X", *d); /* hexpair */ d += 3; - chkblank = 0; } + state = B4SEPARATOR; s++; } @@ -866,11 +929,11 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) rc = -1; goto bail; } else { - if (ISEQUAL(*s)) { + if (ISEQUAL(*s) && is_dn_syntax) { while (ISSPACE(*(d-1))) { /* remove trailing spaces */ d--; } - } else if (SEPARATOR(*s)) { + } else if (SEPARATOR(*s) && is_dn_syntax) { /* separator is a subset of needsescape */ while (ISSPACE(*(d-1))) { /* remove trailing spaces */ d--; @@ -917,10 +980,10 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) *d++ = '\\'; PR_snprintf(d, 3, "%X", *s); /* hexpair */ d += 2; - if (ISPLUS(*s++)) { + if (ISPLUS(*s++) && is_dn_syntax) { subtypestart = d; /* next type start of multi values */ } - if (SEPARATOR(*(s-1)) || ISEQUAL(*(s-1))) { + if ((SEPARATOR(*(s-1)) || ISEQUAL(*(s-1))) && is_dn_syntax) { while (ISSPACE(*s)) /* remove leading spaces */ s++; }