summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRich Megginson <rmeggins@redhat.com>2010-08-20 15:36:12 -0600
committerRich Megginson <rmeggins@redhat.com>2010-08-31 10:36:02 -0600
commitd0b39138e041e0053421a0002341c1f300be3e1c (patch)
tree9c75cb94b5109f5a048168236202bfc5558fe203
parentc40f6877c1c528e77751dea94d86bd9aaaaf26cb (diff)
downloadds-d0b39138e041e0053421a0002341c1f300be3e1c.tar.gz
ds-d0b39138e041e0053421a0002341c1f300be3e1c.tar.xz
ds-d0b39138e041e0053421a0002341c1f300be3e1c.zip
slapi_ldap_url_parse must handle multiple host:port in url
mozldap supports a non-standard URL extension which allows multiple host:port combinations - openldap does not support this - fake out openldap by converting spaces to %20 and all but the last colon to %3A before calling ldap_url_parse, then unescape ludp->lud_host before returning
-rw-r--r--ldap/servers/slapd/ldaputil.c99
1 files changed, 94 insertions, 5 deletions
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 2a9c965a..ac0db055 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -141,27 +141,87 @@ slapi_ldap_url_parse(const char *url, LDAPURLDesc **ludpp, int require_dn, int *
PR_ASSERT(url);
PR_ASSERT(ludpp);
int rc;
+ const char *url_to_use = url;
+#if defined(USE_OPENLDAP)
+ char *urlescaped = NULL;
+#endif
if (secure) {
*secure = 0;
}
+#if defined(USE_OPENLDAP)
+ /* openldap does not support the non-standard multi host:port URLs supported
+ by mozldap - so we have to fake out openldap - replace all spaces with %20 -
+ replace all but the last colon with %3A
+ Go to the 3rd '/' or to the end of the string (convert only the host:port part) */
+ if (url) {
+ char *p = strstr(url, "://");
+ if (p) {
+ int foundspace = 0;
+ int coloncount = 0;
+ char *lastcolon = NULL;
+ p += 3;
+ for (; *p && (*p != '/'); p++) {
+ if (*p == ' ') {
+ foundspace = 1;
+ }
+ if (*p == ':') {
+ coloncount++;
+ lastcolon = p;
+ }
+ }
+ if (foundspace) {
+ char *src = NULL, *dest = NULL;
+ /* have to convert url */
+ /* len * 3 is way too much, but acceptable */
+ urlescaped = slapi_ch_calloc(strlen(url) * 3, sizeof(char));
+ dest = urlescaped;
+ /* copy the scheme */
+ src = strstr(url, "://");
+ src += 3;
+ memcpy(dest, url, src-url);
+ dest += (src-url);
+ /* we have to convert all spaces to %20 - we have to convert
+ all colons except the last one to %3A */
+ for (; *src; ++src) {
+ if (src < p) {
+ if (*src == ' ') {
+ memcpy(dest, "%20", 3);
+ dest += 3;
+ } else if ((coloncount > 1) && (*src == ':') && (src != lastcolon)) {
+ memcpy(dest, "%3A", 3);
+ dest += 3;
+ } else {
+ *dest++ = *src;
+ }
+ } else {
+ *dest++ = *src;
+ }
+ }
+ *dest = '\0';
+ url_to_use = urlescaped;
+ }
+ }
+ }
+#endif
+
#if defined(HAVE_LDAP_URL_PARSE_NO_DEFAULTS)
- rc = ldap_url_parse_no_defaults(url, ludpp, require_dn);
+ rc = ldap_url_parse_no_defaults(url_to_use, ludpp, require_dn);
if (!rc && *ludpp && secure) {
*secure = (*ludpp)->lud_options & LDAP_URL_OPT_SECURE;
}
#else /* openldap */
#if defined(HAVE_LDAP_URL_PARSE_EXT) && defined(LDAP_PVT_URL_PARSE_NONE) && defined(LDAP_PVT_URL_PARSE_NOEMPTY_DN)
- rc = ldap_url_parse_ext(url, ludpp, require_dn ? LDAP_PVT_URL_PARSE_NONE : LDAP_PVT_URL_PARSE_NOEMPTY_DN);
+ rc = ldap_url_parse_ext(url_to_use, ludpp, require_dn ? LDAP_PVT_URL_PARSE_NONE : LDAP_PVT_URL_PARSE_NOEMPTY_DN);
#else
- rc = ldap_url_parse(url, ludpp);
+ rc = ldap_url_parse(url_to_use, ludpp);
if ((rc || !*ludpp) && !require_dn) { /* failed - see if failure was due to missing dn */
- size_t len = strlen(url);
+ size_t len = strlen(url_to_use);
/* assume the url is just scheme://host:port[/] - add the empty string
as the DN (adding a trailing / first if needed) and try to parse
again
*/
- char *urlcopy = slapi_ch_smprintf("%s%s%s", url, (url[len-1] == '/' ? "" : "/"), "");
+ char *urlcopy = slapi_ch_smprintf("%s%s%s", url_to_use, (url_to_use[len-1] == '/' ? "" : "/"), "");
if (*ludpp) {
ldap_free_urldesc(*ludpp); /* free the old one, if any */
}
@@ -177,6 +237,35 @@ slapi_ldap_url_parse(const char *url, LDAPURLDesc **ludpp, int require_dn, int *
}
#endif /* openldap */
+#if defined(USE_OPENLDAP)
+ if (urlescaped && (*ludpp) && (*ludpp)->lud_host) {
+ /* have to unescape lud_host - can unescape in place */
+ char *p = strstr((*ludpp)->lud_host, "://");
+ if (p) {
+ char *dest = NULL;
+ p += 3;
+ dest = p;
+ /* up to the first '/', unescape the host */
+ for (; *p && (*p != '/'); p++) {
+ if (!strncmp(p, "%20", 3)) {
+ *dest++ = ' ';
+ p += 2;
+ } else if (!strncmp(p, "%3A", 3)) {
+ *dest++ = ':';
+ p += 2;
+ } else {
+ *dest++ = *p;
+ }
+ }
+ /* just copy the remainder of the host, if any */
+ while (*p) {
+ *dest++ = *p++;
+ }
+ *dest = '\0';
+ }
+ }
+ slapi_ch_free_string(&urlescaped);
+#endif
return rc;
}