summaryrefslogtreecommitdiffstats
path: root/ldap/servers/plugins/passthru/ptconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/plugins/passthru/ptconfig.c')
-rw-r--r--ldap/servers/plugins/passthru/ptconfig.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/ldap/servers/plugins/passthru/ptconfig.c b/ldap/servers/plugins/passthru/ptconfig.c
new file mode 100644
index 00000000..c3653f66
--- /dev/null
+++ b/ldap/servers/plugins/passthru/ptconfig.c
@@ -0,0 +1,301 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * ptconfig.c - configuration-related code for Pass Through Authentication
+ *
+ */
+
+#include "passthru.h"
+
+/*
+ * Configuration is a bit complicated to fit into a single slapd config file
+ * line, but for now that's how it works. The format is:
+ *
+ * plugin preoperation on PTA NSHOME/passthru-plugin.so passthruauth_init ARGS
+ *
+ * where each ARGS provides configuration for one host. Each ARG should
+ * be of the form:
+ *
+ * "ldap://hosts/suffixes maxconns,maxconcurrency,timeout,ldver,connlifetime"
+ * OR
+ * "ldaps://hosts/suffixes maxconns,maxconcurrency,timeout,ldver,connlifetime"
+ *
+ * where:
+ * hosts is a space-separated list of remote servers (with optional port
+ * numbers) to be used. Each one is tried in order when opening an
+ * LDAP connection.
+ * suffixes is a semicolon separated list of DNs (if a DN contains a
+ * semicolon it must be represented \3B),
+ * maxconns is a limit on how many connections will be made,
+ * maxconcurrency is a limit on how many operations can share a connection,
+ * timeout is a time limit in seconds for bind operations to complete (use
+ * 0 to specify an infinite limit).
+ * ldver is the LDAP protocol version to use to talk to the server (2 or 3)
+ * connlifetime is a time limit time in seconds for a connection to be
+ * used before it is closed and reopened (use 0 to specify an infinite
+ * limit). connlifetime can be omitted in which case a default value
+ * is used; this is for compatibility with DS 4.0 which did not support
+ * connlifetime.
+ */
+
+
+/*
+ * function prototypes
+ */
+static char **get_backend_suffixes( void );
+static int is_underneath_backend_suffix( char *normdn, char **besuffixes );
+
+/*
+ * static variables
+ */
+/* for now, there is only one configuration and it is global to the plugin */
+static PassThruConfig theConfig;
+static int inited = 0;
+
+
+/*
+ * Read configuration and create a configuration data structure.
+ * This is called after the server has configured itself so we can check
+ * for things like collisions between our suffixes and backend's suffixes.
+ * Returns an LDAP error code (LDAP_SUCCESS if all goes well).
+ * XXXmcs: this function leaks memory if any errors occur.
+ */
+int
+passthru_config( int argc, char **argv )
+{
+ int i, j, rc, tosecs, using_def_connlifetime;
+ char *p, **suffixarray;
+ PassThruServer *prevsrvr, *srvr;
+ PassThruSuffix *suffix, *prevsuffix;
+ LDAPURLDesc *ludp;
+
+ if ( inited ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "only one pass through plugin instance can be used\n" );
+ return( LDAP_PARAM_ERROR );
+ }
+
+ inited = 1;
+
+ /*
+ * It doesn't make sense to configure a pass through plugin without
+ * providing at least one remote server. Return an error if attempted.
+ */
+ if ( argc < 1 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "no pass through servers found in configuration"
+ " (at least one must be listed)\n" );
+ return( LDAP_PARAM_ERROR );
+ }
+
+ /*
+ * Parse argv[] values.
+ */
+ prevsrvr = NULL;
+ for ( i = 0; i < argc; ++i ) {
+ srvr = (PassThruServer *)slapi_ch_calloc( 1, sizeof( PassThruServer ));
+ srvr->ptsrvr_url = slapi_ch_strdup( argv[i] );
+
+ if (( p = strchr( srvr->ptsrvr_url, ' ' )) == NULL ) {
+ /*
+ * use defaults for maxconnections, maxconcurrency, timeout,
+ * LDAP version, and connlifetime.
+ */
+ srvr->ptsrvr_maxconnections = PASSTHRU_DEF_SRVR_MAXCONNECTIONS;
+ srvr->ptsrvr_maxconcurrency = PASSTHRU_DEF_SRVR_MAXCONCURRENCY;
+ srvr->ptsrvr_timeout = (struct timeval *)slapi_ch_calloc( 1,
+ sizeof( struct timeval ));
+ srvr->ptsrvr_timeout->tv_sec = PASSTHRU_DEF_SRVR_TIMEOUT;
+ srvr->ptsrvr_ldapversion = PASSTHRU_DEF_SRVR_PROTOCOL_VERSION;
+ using_def_connlifetime = 1;
+ } else {
+ /*
+ * parse parameters. format is:
+ * maxconnections,maxconcurrency,timeout,ldapversion
+ * OR maxconnections,maxconcurrency,timeout,ldapversion,lifetime
+ */
+ *p++ = '\0';
+ rc = sscanf( p, "%d,%d,%d,%d,%d", &srvr->ptsrvr_maxconnections,
+ &srvr->ptsrvr_maxconcurrency, &tosecs,
+ &srvr->ptsrvr_ldapversion, &srvr->ptsrvr_connlifetime );
+ if ( rc < 4 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "server parameters should be in the form "
+ "\"maxconnections,maxconcurrency,timeout,ldapversion,"
+ "connlifetime\" (got \"%s\")\n", p );
+ return( LDAP_PARAM_ERROR );
+ } else if ( rc < 5 ) {
+ using_def_connlifetime = 1;
+ srvr->ptsrvr_connlifetime = PASSTHRU_DEF_SRVR_CONNLIFETIME;
+ } else {
+ using_def_connlifetime = 0;
+ }
+
+ if ( srvr->ptsrvr_ldapversion != LDAP_VERSION2
+ && srvr->ptsrvr_ldapversion != LDAP_VERSION3 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "LDAP protocol version should be %d or %d (got %d)\n",
+ LDAP_VERSION2, LDAP_VERSION3,
+ srvr->ptsrvr_ldapversion );
+ return( LDAP_PARAM_ERROR );
+ }
+
+ if ( srvr->ptsrvr_maxconnections <= 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "maximum connections must be greater than "
+ "zero (got %d)\n", srvr->ptsrvr_maxconnections );
+ return( LDAP_PARAM_ERROR );
+ }
+
+ if ( srvr->ptsrvr_maxconcurrency <= 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "maximum concurrency must be greater than "
+ "zero (got %d)\n", srvr->ptsrvr_maxconcurrency );
+ return( LDAP_PARAM_ERROR );
+ }
+
+ if ( tosecs <= 0 ) {
+ srvr->ptsrvr_timeout = NULL;
+ } else {
+ srvr->ptsrvr_timeout = (struct timeval *)slapi_ch_calloc( 1,
+ sizeof( struct timeval ));
+ srvr->ptsrvr_timeout->tv_sec = tosecs;
+ }
+ }
+
+ /*
+ * parse the LDAP URL
+ */
+ if (( rc = ldap_url_parse( srvr->ptsrvr_url, &ludp )) != 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "unable to parse LDAP URL \"%s\" (%s)\n",
+ srvr->ptsrvr_url, passthru_urlparse_err2string( rc ));
+ return( LDAP_PARAM_ERROR );
+ }
+
+ if ( ludp->lud_dn == NULL || *ludp->lud_dn == '\0' ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "missing suffix in LDAP URL \"%s\"\n",
+ srvr->ptsrvr_url );
+ return( LDAP_PARAM_ERROR );
+ }
+
+ srvr->ptsrvr_hostname = slapi_ch_strdup( ludp->lud_host );
+ srvr->ptsrvr_port = ludp->lud_port;
+ srvr->ptsrvr_secure =
+ (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 );
+
+ /*
+ * If a space-separated list of hosts is configured for failover,
+ * use a different (non infinite) default for connection lifetime.
+ */
+ if ( using_def_connlifetime &&
+ strchr( srvr->ptsrvr_hostname, ' ' ) != NULL ) {
+ srvr->ptsrvr_connlifetime =
+ PASSTHRU_DEF_SRVR_FAILOVERCONNLIFETIME;
+ }
+
+ /*
+ * split the DN into multiple suffixes (separated by ';')
+ */
+ if (( suffixarray = ldap_str2charray( ludp->lud_dn, ";" )) == NULL ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "unable to parse suffix string \"%s\" within \"%s\"\n",
+ ludp->lud_dn, srvr->ptsrvr_url );
+ return( LDAP_PARAM_ERROR );
+ }
+
+ /*
+ * free our LDAP URL descriptor
+ */
+ ldap_free_urldesc( ludp );
+ ludp = NULL;
+
+ /*
+ * reorganize the suffixes into a linked list and normalize them
+ */
+ prevsuffix = NULL;
+ for ( j = 0; suffixarray[ j ] != NULL; ++j ) {
+
+ /*
+ * allocate a new PassThruSuffix structure and fill it in.
+ */
+ suffix = (PassThruSuffix *)slapi_ch_malloc(
+ sizeof( PassThruSuffix ));
+ suffix->ptsuffix_normsuffix =
+ slapi_dn_normalize( suffixarray[ j ] );
+ suffixarray[ j ] = NULL;
+ suffix->ptsuffix_len = strlen( suffix->ptsuffix_normsuffix );
+ suffix->ptsuffix_next = NULL;
+
+ /*
+ * add to end of list
+ */
+ if ( prevsuffix == NULL ) {
+ srvr->ptsrvr_suffixes = suffix;
+ } else {
+ prevsuffix->ptsuffix_next = suffix;
+ }
+ prevsuffix = suffix;
+ }
+ ldap_memfree( suffixarray );
+
+ /*
+ * create mutexes and condition variables for this server
+ */
+ if (( srvr->ptsrvr_connlist_mutex = slapi_new_mutex()) == NULL ||
+ ( srvr->ptsrvr_connlist_cv = slapi_new_condvar(
+ srvr->ptsrvr_connlist_mutex )) == NULL ) {
+ return( LDAP_LOCAL_ERROR );
+ }
+
+ /*
+ * add this server to the end of our list
+ */
+ if ( prevsrvr == NULL ) {
+ theConfig.ptconfig_serverlist = srvr;
+ } else {
+ prevsrvr->ptsrvr_next = srvr;
+ }
+ prevsrvr = srvr;
+
+#ifdef PASSTHRU_VERBOSE_LOGGING
+ /*
+ * log configuration for debugging purposes
+ */
+ slapi_log_error( SLAPI_LOG_PLUGIN, PASSTHRU_PLUGIN_SUBSYSTEM,
+ "PTA server host: \"%s\", port: %d, secure: %d,"
+ " maxconnections: %d, maxconcurrency: %d, timeout: %d,"
+ " ldversion: %d, connlifetime: %d\n",
+ srvr->ptsrvr_hostname, srvr->ptsrvr_port,
+ srvr->ptsrvr_secure, srvr->ptsrvr_maxconnections,
+ srvr->ptsrvr_maxconcurrency,
+ srvr->ptsrvr_timeout == NULL ? -1
+ : srvr->ptsrvr_timeout->tv_sec, srvr->ptsrvr_ldapversion,
+ srvr->ptsrvr_connlifetime );
+ for ( prevsuffix = srvr->ptsrvr_suffixes; prevsuffix != NULL;
+ prevsuffix = prevsuffix->ptsuffix_next ) {
+ slapi_log_error( SLAPI_LOG_FATAL, PASSTHRU_PLUGIN_SUBSYSTEM,
+ " normalized suffix: \"%s\"\n",
+ prevsuffix->ptsuffix_normsuffix );
+ }
+#endif
+
+ }
+
+ return( LDAP_SUCCESS );
+}
+
+
+/*
+ * Get the pass though configuration data. For now, there is only one
+ * configuration and it is global to the plugin.
+ */
+PassThruConfig *
+passthru_get_config( void )
+{
+ return( &theConfig );
+}