summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@redhat.com>2012-02-23 20:01:03 -0500
committerNalin Dahyabhai <nalin@redhat.com>2012-02-23 20:01:03 -0500
commit7874eabc4dd75d86cbccd3f4bc0d4d77ef4606a7 (patch)
tree1d4c719200e4c56b0799a24278206db199ee411c
parentebd8dda68bb83ea82bc2f5107a2f6d5714a1d0cf (diff)
downloadslapi-nis-7874eabc4dd75d86cbccd3f4bc0d4d77ef4606a7.tar.gz
slapi-nis-7874eabc4dd75d86cbccd3f4bc0d4d77ef4606a7.tar.xz
slapi-nis-7874eabc4dd75d86cbccd3f4bc0d4d77ef4606a7.zip
properly escape RDN values when building compat entries (#796509)
-rw-r--r--NEWS1
-rw-r--r--src/back-sch.c82
-rwxr-xr-xtests/test31-schema-weird-rdn/after.sh4
-rw-r--r--tests/test31-schema-weird-rdn/after.txt13
-rwxr-xr-xtests/test31-schema-weird-rdn/before.sh4
-rw-r--r--tests/test31-schema-weird-rdn/before.txt5
-rwxr-xr-xtests/test31-schema-weird-rdn/change.sh91
-rw-r--r--tests/test31-schema-weird-rdn/description.txt1
-rw-r--r--tests/test31-schema-weird-rdn/dse.ldif13
9 files changed, 205 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index c9836bb..cc89bec 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,4 @@
+0.38 * Properly escape RDN values when building compat entries (#796509).
0.37 * Fix a compile error on systems which don't define
LDAP_SCOPE_SUBORDINATE, reported by Christian Neuhold.
0.36 * Stop yp_first/yp_next from looping indefinitely when keys get
diff --git a/src/back-sch.c b/src/back-sch.c
index ac6ff17..2e2d195 100644
--- a/src/back-sch.c
+++ b/src/back-sch.c
@@ -287,7 +287,8 @@ void
backend_set_entry(Slapi_PBlock *pb, Slapi_Entry *e,
struct backend_set_data *data)
{
- char *dn, *rdn, *ndn, *ldif, *plugin_id, *keys[2], *values[2], **ava;
+ const char *hexchars = "0123456789ABCDEF";
+ char *rdn, *ndn, *ldif, *plugin_id, *keys[2], *values[2], **ava, *p, *q;
char *attr, *val;
unsigned int rdn_len, value_len, *ava_lens;
const char *rdnstr;
@@ -317,21 +318,68 @@ backend_set_entry(Slapi_PBlock *pb, Slapi_Entry *e,
&data->common.ref_attr_list,
&data->common.inref_attr_list,
&rdn_len);
- if (rdn == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
- "no RDN for %s, unsetting domain/map/id"
+ if ((rdn == NULL) || (strlen(rdn) == 0) || (strchr(rdn, '=') == NULL)) {
+ slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
+ "no RDN for %s, unsetting domain/map/id "
"\"%s\"/\"%s\"/(\"%s\")\n",
ndn, data->common.group, data->common.set, ndn);
map_data_unset_entry(data->common.state,
data->common.group, data->common.set, ndn);
+ return;
+ }
+ /* Assume attribute=value and hex-escape the whole value to build the
+ * new entry's RDN. The server functions will un-escape whatever they
+ * can when we build the resulting DN. */
+ q = malloc(strlen(rdn) * 3 + 1);
+ p = strchr(rdn, '=') + 1;
+ i = p - rdn;
+ memcpy(q, rdn, i);
+ while (*p != '\0') {
+ j = ((unsigned int) *p++) & 0xff;
+ q[i++] = '\\';
+ q[i++] = hexchars[(j & 0xf0) >> 4];
+ q[i++] = hexchars[j & 0xf];
+ }
+ q[i] = '\0';
+ srdn = slapi_rdn_new_dn(q);
+ free(q);
+ /* Now build the SDN. Check it for validity. */
+ sdn = slapi_sdn_add_rdn(slapi_sdn_dup(data->container_sdn), srdn);
+ slapi_rdn_free(&srdn);
+ if ((sdn == NULL) ||
+ (slapi_sdn_get_dn(sdn) == NULL) ||
+ (slapi_sdn_get_ndn(sdn) == NULL)) {
+ slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
+ "would generate an invalid DN (1), "
+ "unsetting domain/map/id "
+ "\"%s\"/\"%s\"/(\"%s\")\n",
+ data->common.group, data->common.set, ndn);
+ map_data_unset_entry(data->common.state,
+ data->common.group, data->common.set, ndn);
+ if (sdn != NULL) {
+ slapi_sdn_free(&sdn);
+ }
+ format_free_data(rdn);
+ return;
}
- /* Now build the entry itself, and set the DN first. */
+ /* Now build the entry itself. Set the DN first, and make sure it took
+ * the value. */
entry = slapi_entry_alloc();
- dn = slapi_dn_plus_rdn(slapi_sdn_get_ndn(data->container_sdn), rdn);
- sdn = slapi_sdn_new_dn_byval(dn);
slapi_entry_set_sdn(entry, sdn);
slapi_sdn_free(&sdn);
- slapi_ch_free((void **) &dn);
+ if ((slapi_entry_get_dn(entry) == NULL) ||
+ (slapi_entry_get_ndn(entry) == NULL)) {
+ slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
+ "would generate an invalid DN (2), "
+ "unsetting domain/map/id "
+ "\"%s\"/\"%s\"/(\"%s\")\n",
+ data->common.group, data->common.set, ndn);
+ map_data_unset_entry(data->common.state,
+ data->common.group, data->common.set, ndn);
+ slapi_entry_free(entry);
+ format_free_data(rdn);
+ return;
+ }
/* Set operational attributes here so that they can be overridden. */
backend_set_operational_attributes(entry, data->common.state,
time(NULL), 0);
@@ -457,8 +505,24 @@ backend_set_entry(Slapi_PBlock *pb, Slapi_Entry *e,
backend_entry_make_entry_data(e_dn, entry),
backend_entry_free_entry_data);
} else {
+ if (rdnstr == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
+ "would generate an invalid RDN, "
+ "unsetting domain/map/id "
+ "\"%s\"/\"%s\"/(\"%s\")\n",
+ data->common.group, data->common.set,
+ ndn);
+ }
+ if (slapi_entry_get_ndn(entry) == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, plugin_id,
+ "would generate an invalid entry DN, "
+ "unsetting domain/map/id "
+ "\"%s\"/\"%s\"/(\"%s\")\n",
+ data->common.group, data->common.set,
+ ndn);
+ }
slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
- "no value for %s, unsetting domain/map/id"
+ "no value for %s, unsetting domain/map/id "
"\"%s\"/\"%s\"/(\"%s\")\n",
ndn, data->common.group, data->common.set, ndn);
map_data_unset_entry(data->common.state,
diff --git a/tests/test31-schema-weird-rdn/after.sh b/tests/test31-schema-weird-rdn/after.sh
new file mode 100755
index 0000000..32c64be
--- /dev/null
+++ b/tests/test31-schema-weird-rdn/after.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+{ search -b cn=compat,cn=accounts,dc=example,dc=com dn ; \
+ search -b cn=compat2,cn=accounts,dc=example,dc=com dn; } |\
+grep ^dn: | env LANG=C sort
diff --git a/tests/test31-schema-weird-rdn/after.txt b/tests/test31-schema-weird-rdn/after.txt
new file mode 100644
index 0000000..4536f9b
--- /dev/null
+++ b/tests/test31-schema-weird-rdn/after.txt
@@ -0,0 +1,13 @@
+dn: cn=-User 1 E,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=CRON\2C the destroyer,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1 A,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1 B,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1 C,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1 F\2B,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1 G-,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1\2BH,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1\5C\2BI,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=You \2B Me \3D We,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=\2BUser 1 D,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=compat,cn=accounts,dc=example,dc=com
+dn: ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
diff --git a/tests/test31-schema-weird-rdn/before.sh b/tests/test31-schema-weird-rdn/before.sh
new file mode 100755
index 0000000..32c64be
--- /dev/null
+++ b/tests/test31-schema-weird-rdn/before.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+{ search -b cn=compat,cn=accounts,dc=example,dc=com dn ; \
+ search -b cn=compat2,cn=accounts,dc=example,dc=com dn; } |\
+grep ^dn: | env LANG=C sort
diff --git a/tests/test31-schema-weird-rdn/before.txt b/tests/test31-schema-weird-rdn/before.txt
new file mode 100644
index 0000000..07e162b
--- /dev/null
+++ b/tests/test31-schema-weird-rdn/before.txt
@@ -0,0 +1,5 @@
+dn: cn=User 1 A,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1 B,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=User 1 C,ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
+dn: cn=compat,cn=accounts,dc=example,dc=com
+dn: ou=passwd,cn=compat,cn=accounts,dc=example,dc=com
diff --git a/tests/test31-schema-weird-rdn/change.sh b/tests/test31-schema-weird-rdn/change.sh
new file mode 100755
index 0000000..b5ffd76
--- /dev/null
+++ b/tests/test31-schema-weird-rdn/change.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+add << EOF
+dn: uid=user1d,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+uid: user1d
+uidNumber: 1004
+gidNumber: 1004
+cn: +User 1 D
+gecos: User 1 D
+loginShell: /bin/sh
+homeDirectory: /home/user1d
+
+dn: uid=user1e,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+uid: user1e
+uidNumber: 1005
+gidNumber: 1005
+cn: -User 1 E
+gecos: User 1 E
+loginShell: /bin/sh
+homeDirectory: /home/user1e
+
+dn: uid=user1f,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+uid: user1f
+uidNumber: 1006
+gidNumber: 1006
+cn: User 1 F+
+gecos: User 1 F
+loginShell: /bin/sh
+homeDirectory: /home/user1f
+
+dn: uid=user1g,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+uid: user1g
+uidNumber: 1007
+gidNumber: 1007
+cn: User 1 G-
+gecos: User 1 G
+loginShell: /bin/sh
+homeDirectory: /home/user1g
+
+dn: uid=user1h,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+uid: user1h
+uidNumber: 1008
+gidNumber: 1008
+cn: User 1+H
+gecos: User 1 H
+loginShell: /bin/sh
+homeDirectory: /home/user1h
+
+dn: uid=user1i,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+uid: user1i
+uidNumber: 1009
+gidNumber: 1009
+cn: User 1\+I
+gecos: User 1 I
+loginShell: /bin/sh
+homeDirectory: /home/user1i
+
+dn: uid=user1j,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+uid: user1j
+uidNumber: 1010
+gidNumber: 1010
+cn: CRON, the destroyer
+gecos: User 1 J
+loginShell: /bin/sh
+homeDirectory: /home/user1j
+
+dn: uid=user1k,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+uid: user1k
+uidNumber: 1011
+gidNumber: 1011
+cn: You + Me = We
+gecos: User 1 K
+loginShell: /bin/sh
+homeDirectory: /home/user1k
+
+EOF
diff --git a/tests/test31-schema-weird-rdn/description.txt b/tests/test31-schema-weird-rdn/description.txt
new file mode 100644
index 0000000..c3b091d
--- /dev/null
+++ b/tests/test31-schema-weird-rdn/description.txt
@@ -0,0 +1 @@
+an RDN that needs escaping
diff --git a/tests/test31-schema-weird-rdn/dse.ldif b/tests/test31-schema-weird-rdn/dse.ldif
new file mode 100644
index 0000000..0897534
--- /dev/null
+++ b/tests/test31-schema-weird-rdn/dse.ldif
@@ -0,0 +1,13 @@
+dn: cn=compat-passwd,cn=Schema Compatibility,cn=plugins,cn=config
+objectClass: top
+objectClass: extensibleObject
+cn: compat-passwd
+schema-compat-container-group: cn=compat,cn=Accounts,dc=example,dc=com
+schema-compat-container-rdn: ou=passwd
+schema-compat-check-access: yes
+schema-compat-search-base: cn=Users1,cn=Accounts,dc=example,dc=com
+schema-compat-search-filter: (objectClass=posixAccount)
+schema-compat-entry-rdn: cn=%{cn}
+schema-compat-entry-attribute: objectclass=extensibleobject
+schema-compat-entry-attribute: uidNumber=%{uidNumber}
+