Add support for multiple URI lines by joining the contents and passing
the result to ldap_initialize.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2003-2009
|
Copyright (c) 2003-2010
|
||||||
Todd C. Miller <Todd.Miller@courtesan.com>
|
Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
@@ -259,14 +259,16 @@ below in upper case but are parsed in a case-independent manner.
|
|||||||
=item B<URI> ldap[s]://[hostname[:port]] ...
|
=item B<URI> ldap[s]://[hostname[:port]] ...
|
||||||
|
|
||||||
Specifies a whitespace-delimited list of one or more URIs describing
|
Specifies a whitespace-delimited list of one or more URIs describing
|
||||||
the LDAP server(s) to connect to. The I<protocol> may be either B<ldap>
|
the LDAP server(s) to connect to. The I<protocol> may be either
|
||||||
or B<ldaps>, the latter being for servers that support TLS (SSL)
|
B<ldap> or B<ldaps>, the latter being for servers that support TLS
|
||||||
encryption. If no I<port> is specified, the default is port 389 for
|
(SSL) encryption. If no I<port> is specified, the default is port
|
||||||
C<ldap://> or port 636 for C<ldaps://>. If no I<hostname> is specified,
|
389 for C<ldap://> or port 636 for C<ldaps://>. If no I<hostname>
|
||||||
B<sudo> will connect to B<localhost>. Only systems using the OpenSSL
|
is specified, B<sudo> will connect to B<localhost>. Multiple B<URI>
|
||||||
libraries support the mixing of C<ldap://> and C<ldaps://> URIs.
|
lines are treated identically to a B<URI> line containing multiple
|
||||||
The Netscape-derived libraries used on most commercial versions of
|
entries. Only systems using the OpenSSL libraries support the
|
||||||
Unix are only capable of supporting one or the other.
|
mixing of C<ldap://> and C<ldaps://> URIs. The Netscape-derived
|
||||||
|
libraries used on most commercial versions of Unix are only capable
|
||||||
|
of supporting one or the other.
|
||||||
|
|
||||||
=item B<HOST> name[:port] ...
|
=item B<HOST> name[:port] ...
|
||||||
|
|
||||||
|
@@ -142,7 +142,7 @@ static struct ldap_config {
|
|||||||
int rootuse_sasl;
|
int rootuse_sasl;
|
||||||
int ssl_mode;
|
int ssl_mode;
|
||||||
char *host;
|
char *host;
|
||||||
char *uri;
|
struct ldap_config_list_str *uri;
|
||||||
char *binddn;
|
char *binddn;
|
||||||
char *bindpw;
|
char *bindpw;
|
||||||
char *rootbinddn;
|
char *rootbinddn;
|
||||||
@@ -166,7 +166,7 @@ static struct ldap_config_table ldap_conf_table[] = {
|
|||||||
{ "port", CONF_INT, FALSE, -1, &ldap_conf.port },
|
{ "port", CONF_INT, FALSE, -1, &ldap_conf.port },
|
||||||
{ "ssl", CONF_STR, FALSE, -1, &ldap_conf.ssl },
|
{ "ssl", CONF_STR, FALSE, -1, &ldap_conf.ssl },
|
||||||
{ "sslpath", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile },
|
{ "sslpath", CONF_STR, FALSE, -1, &ldap_conf.tls_certfile },
|
||||||
{ "uri", CONF_STR, FALSE, -1, &ldap_conf.uri },
|
{ "uri", CONF_LIST_STR, FALSE, -1, &ldap_conf.uri },
|
||||||
#ifdef LDAP_OPT_DEBUG_LEVEL
|
#ifdef LDAP_OPT_DEBUG_LEVEL
|
||||||
{ "debug", CONF_INT, FALSE, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug },
|
{ "debug", CONF_INT, FALSE, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug },
|
||||||
#endif
|
#endif
|
||||||
@@ -313,70 +313,75 @@ toobig:
|
|||||||
* where the trailing slash is optional.
|
* where the trailing slash is optional.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
sudo_ldap_parse_uri(const char *uri_list)
|
sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list)
|
||||||
{
|
{
|
||||||
char *buf, *uri, *host, *cp, *port;
|
char *buf, *uri, *host, *cp, *port;
|
||||||
char hostbuf[LINE_MAX];
|
char hostbuf[LINE_MAX];
|
||||||
int nldap = 0, nldaps = 0;
|
int nldap = 0, nldaps = 0;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
buf = estrdup(uri_list);
|
do {
|
||||||
hostbuf[0] = '\0';
|
buf = estrdup(uri_list->val);
|
||||||
for ((uri = strtok(buf, " \t")); uri != NULL; (uri = strtok(NULL, " \t"))) {
|
hostbuf[0] = '\0';
|
||||||
if (strncasecmp(uri, "ldap://", 7) == 0) {
|
for ((uri = strtok(buf, " \t")); uri != NULL; (uri = strtok(NULL, " \t"))) {
|
||||||
nldap++;
|
if (strncasecmp(uri, "ldap://", 7) == 0) {
|
||||||
host = uri + 7;
|
nldap++;
|
||||||
} else if (strncasecmp(uri, "ldaps://", 8) == 0) {
|
host = uri + 7;
|
||||||
nldaps++;
|
} else if (strncasecmp(uri, "ldaps://", 8) == 0) {
|
||||||
host = uri + 8;
|
nldaps++;
|
||||||
} else {
|
host = uri + 8;
|
||||||
warningx("unsupported LDAP uri type: %s", uri);
|
} else {
|
||||||
goto done;
|
warningx("unsupported LDAP uri type: %s", uri);
|
||||||
}
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* trim optional trailing slash */
|
/* trim optional trailing slash */
|
||||||
if ((cp = strrchr(host, '/')) != NULL && cp[1] == '\0') {
|
if ((cp = strrchr(host, '/')) != NULL && cp[1] == '\0') {
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostbuf[0] != '\0') {
|
if (hostbuf[0] != '\0') {
|
||||||
if (strlcat(hostbuf, " ", sizeof(hostbuf)) >= sizeof(hostbuf))
|
if (strlcat(hostbuf, " ", sizeof(hostbuf)) >= sizeof(hostbuf))
|
||||||
goto toobig;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*host == '\0')
|
|
||||||
host = "localhost"; /* no host specified, use localhost */
|
|
||||||
|
|
||||||
if (strlcat(hostbuf, host, sizeof(hostbuf)) >= sizeof(hostbuf))
|
|
||||||
goto toobig;
|
|
||||||
|
|
||||||
/* If using SSL and no port specified, add port 636 */
|
|
||||||
if (nldaps) {
|
|
||||||
if ((port = strrchr(host, ':')) == NULL ||
|
|
||||||
!isdigit((unsigned char)port[1]))
|
|
||||||
if (strlcat(hostbuf, ":636", sizeof(hostbuf)) >= sizeof(hostbuf))
|
|
||||||
goto toobig;
|
goto toobig;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (hostbuf[0] == '\0') {
|
|
||||||
warningx("invalid uri: %s", uri_list);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nldaps != 0) {
|
if (*host == '\0')
|
||||||
if (nldap != 0) {
|
host = "localhost"; /* no host specified, use localhost */
|
||||||
warningx("cannot mix ldap and ldaps URIs");
|
|
||||||
|
if (strlcat(hostbuf, host, sizeof(hostbuf)) >= sizeof(hostbuf))
|
||||||
|
goto toobig;
|
||||||
|
|
||||||
|
/* If using SSL and no port specified, add port 636 */
|
||||||
|
if (nldaps) {
|
||||||
|
if ((port = strrchr(host, ':')) == NULL ||
|
||||||
|
!isdigit((unsigned char)port[1]))
|
||||||
|
if (strlcat(hostbuf, ":636", sizeof(hostbuf)) >= sizeof(hostbuf))
|
||||||
|
goto toobig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hostbuf[0] == '\0') {
|
||||||
|
warningx("invalid uri: %s", uri_list);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
|
|
||||||
warningx("cannot mix ldaps and starttls");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
ldap_conf.ssl_mode = SUDO_LDAP_SSL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ldap_conf.host);
|
if (nldaps != 0) {
|
||||||
ldap_conf.host = estrdup(hostbuf);
|
if (nldap != 0) {
|
||||||
|
warningx("cannot mix ldap and ldaps URIs");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
|
||||||
|
warningx("cannot mix ldaps and starttls");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
ldap_conf.ssl_mode = SUDO_LDAP_SSL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ldap_conf.host);
|
||||||
|
ldap_conf.host = estrdup(hostbuf);
|
||||||
|
efree(buf);
|
||||||
|
} while ((uri_list = uri_list->next));
|
||||||
|
|
||||||
|
buf = NULL;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@@ -386,6 +391,30 @@ done:
|
|||||||
toobig:
|
toobig:
|
||||||
errorx(1, "sudo_ldap_parse_uri: out of space building hostbuf");
|
errorx(1, "sudo_ldap_parse_uri: out of space building hostbuf");
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static char *
|
||||||
|
sudo_ldap_join_uri(struct ldap_config_list_str *uri_list)
|
||||||
|
{
|
||||||
|
struct ldap_config_list_str *uri;
|
||||||
|
size_t len = 0;
|
||||||
|
char *buf, *cp;
|
||||||
|
|
||||||
|
/* Usually just a single entry. */
|
||||||
|
if (uri_list->next == NULL)
|
||||||
|
return(estrdup(uri_list->val));
|
||||||
|
|
||||||
|
for (uri = uri_list; uri != NULL; uri = uri->next) {
|
||||||
|
len += strlen(uri->val) + 1;
|
||||||
|
}
|
||||||
|
buf = cp = emalloc(len);
|
||||||
|
buf[0] = '\0';
|
||||||
|
for (uri = uri_list; uri != NULL; uri = uri->next) {
|
||||||
|
cp += strlcpy(cp, uri->val, len - (cp - buf));
|
||||||
|
*cp++ = ' ';
|
||||||
|
}
|
||||||
|
cp[-1] = '\0';
|
||||||
|
return(buf);
|
||||||
|
}
|
||||||
#endif /* HAVE_LDAP_INITIALIZE */
|
#endif /* HAVE_LDAP_INITIALIZE */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -949,8 +978,12 @@ sudo_ldap_read_config(void)
|
|||||||
sudo_printf(SUDO_CONV_ERROR_MSG, "LDAP Config Summary\n");
|
sudo_printf(SUDO_CONV_ERROR_MSG, "LDAP Config Summary\n");
|
||||||
sudo_printf(SUDO_CONV_ERROR_MSG, "===================\n");
|
sudo_printf(SUDO_CONV_ERROR_MSG, "===================\n");
|
||||||
if (ldap_conf.uri) {
|
if (ldap_conf.uri) {
|
||||||
sudo_printf(SUDO_CONV_ERROR_MSG, "uri %s\n",
|
struct ldap_config_list_str *uri = ldap_conf.uri;
|
||||||
ldap_conf.uri);
|
|
||||||
|
do {
|
||||||
|
sudo_printf(SUDO_CONV_ERROR_MSG, "uri %s\n",
|
||||||
|
uri->val);
|
||||||
|
} while ((uri = uri->next) != NULL);
|
||||||
} else {
|
} else {
|
||||||
sudo_printf(SUDO_CONV_ERROR_MSG, "host %s\n",
|
sudo_printf(SUDO_CONV_ERROR_MSG, "host %s\n",
|
||||||
ldap_conf.host ? ldap_conf.host : "(NONE)");
|
ldap_conf.host ? ldap_conf.host : "(NONE)");
|
||||||
@@ -1053,10 +1086,13 @@ sudo_ldap_read_config(void)
|
|||||||
#ifndef HAVE_LDAP_INITIALIZE
|
#ifndef HAVE_LDAP_INITIALIZE
|
||||||
/* Convert uri list to host list if no ldap_initialize(). */
|
/* Convert uri list to host list if no ldap_initialize(). */
|
||||||
if (ldap_conf.uri) {
|
if (ldap_conf.uri) {
|
||||||
if (sudo_ldap_parse_uri(ldap_conf.uri) != 0)
|
struct ldap_config_list_str *uri = ldap_conf.uri;
|
||||||
|
if (sudo_ldap_parse_uri(uri) != 0)
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
free(ldap_conf.uri);
|
do {
|
||||||
ldap_conf.uri = NULL;
|
ldap_conf.uri = uri->next;
|
||||||
|
efree(uri);
|
||||||
|
} while ((uri = ldap_conf.uri));
|
||||||
ldap_conf.port = LDAP_PORT;
|
ldap_conf.port = LDAP_PORT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1551,7 +1587,7 @@ sudo_ldap_set_options(LDAP *ld)
|
|||||||
(long)tv.tv_sec, ldap_err2string(rc));
|
(long)tv.tv_sec, ldap_err2string(rc));
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
DPRINTF(("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %ld)\n",
|
DPRINTF(("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %ld)",
|
||||||
(long)tv.tv_sec), 1);
|
(long)tv.tv_sec), 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1565,7 +1601,7 @@ sudo_ldap_set_options(LDAP *ld)
|
|||||||
ldap_err2string(rc));
|
ldap_err2string(rc));
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
DPRINTF(("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD)\n"), 1);
|
DPRINTF(("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD)"), 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return(0);
|
return(0);
|
||||||
@@ -1672,8 +1708,10 @@ sudo_ldap_open(struct sudo_nss *nss)
|
|||||||
/* Connect to LDAP server */
|
/* Connect to LDAP server */
|
||||||
#ifdef HAVE_LDAP_INITIALIZE
|
#ifdef HAVE_LDAP_INITIALIZE
|
||||||
if (ldap_conf.uri != NULL) {
|
if (ldap_conf.uri != NULL) {
|
||||||
DPRINTF(("ldap_initialize(ld, %s)", ldap_conf.uri), 2);
|
char *buf = sudo_ldap_join_uri(ldap_conf.uri);
|
||||||
rc = ldap_initialize(&ld, ldap_conf.uri);
|
DPRINTF(("ldap_initialize(ld, %s)", buf), 2);
|
||||||
|
rc = ldap_initialize(&ld, buf);
|
||||||
|
efree(buf);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
rc = sudo_ldap_init(&ld, ldap_conf.host, ldap_conf.port);
|
rc = sudo_ldap_init(&ld, ldap_conf.host, ldap_conf.port);
|
||||||
|
Reference in New Issue
Block a user