diff options
author | Rich Megginson <rmeggins@redhat.com> | 2010-08-20 15:36:12 -0600 |
---|---|---|
committer | Rich Megginson <rmeggins@redhat.com> | 2010-08-31 13:35:54 -0600 |
commit | 312afcd8a09384c7fe08389ddbc33b6e774f9e4d (patch) | |
tree | 0401afa48694e20d192db9b2df23457b1276f600 /ldap/servers/slapd | |
parent | d213146b92c90e4cc86843f6978c9badb4877eb6 (diff) | |
download | ds-312afcd8a09384c7fe08389ddbc33b6e774f9e4d.tar.gz ds-312afcd8a09384c7fe08389ddbc33b6e774f9e4d.tar.xz ds-312afcd8a09384c7fe08389ddbc33b6e774f9e4d.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
Diffstat (limited to 'ldap/servers/slapd')
-rw-r--r-- | ldap/servers/slapd/ldaputil.c | 99 |
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; } |