ldap/servers/slapd/attr.c | 6 +-
ldap/servers/slapd/attrsyntax.c | 8 +-
ldap/servers/slapd/dn.c | 111 +++++++++++++++++++++++++++++++---------
3 files changed, 95 insertions(+), 30 deletions(-)
New commits:
commit bfe31ac30e4dec8a2b850c5a60180d02674a8207
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Dec 7 10:15:00 2010 -0800
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++;
}