From 1923c0ebeeea926c17957139834c2d0be2262e2f Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Bj=C3=B6rn=20Jacke?= Date: Mon, 21 Apr 2008 15:14:26 +0200 Subject: [PATCH] add ssl support for Netscape LDAP library based systems and split up "ldap timeout" into "ldap operation timeout" and "ldap connection timeout" Add Netscape LDAP SSL support and along with that introduce the two more fine grained ldap parameters: * ldap connection timeout (defaults to 2 seconds) * ldap operation timeout (defaults to 15 seconds, like ldap timeout in previous versions) "ldap timeout" is being removed accordingly. --- source/configure.in | 4 + source/include/smbldap.h | 3 +- source/lib/smbldap.c | 148 ++++++++++++++++++++++++++-------------- source/libads/cldap.c | 2 +- source/libads/ldap.c | 6 +- source/param/loadparm.c | 34 ++++++++-- source/winbindd/winbindd_rpc.c | 2 +- 7 files changed, 138 insertions(+), 61 deletions(-) diff --git a/source/configure.in b/source/configure.in index 07e5bbe..dc92951 100644 --- a/source/configure.in +++ b/source/configure.in @@ -3105,6 +3105,10 @@ if test x"$with_ldap_support" != x"no"; then AC_CHECK_LIB_EXT(ldap, LDAP_LIBS, ldap_init) ########################################################s+ # check for Netscape SSL API + AC_CHECK_FUNC_EXT(ldapssl_init,$LDAP_LIBS) + + ######################################################## # If we have LDAP, does it's rebind procedure take 2 or 3 arguments? # Check found in pam_ldap 145. AC_CHECK_FUNC_EXT(ldap_set_rebind_proc,$LDAP_LIBS) diff --git a/source/include/smbldap.h b/source/include/smbldap.h index d9d7aca..d89c886 100644 --- a/source/include/smbldap.h +++ b/source/include/smbldap.h @@ -220,7 +220,8 @@ const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld, #endif /* HAVE_LDAP */ -#define LDAP_CONNECT_DEFAULT_TIMEOUT 15 +#define LDAP_CONNECTION_DEFAULT_TIMEOUT 2 +#define LDAP_OPERATION_DEFAULT_TIMEOUT 15 #define LDAP_PAGE_SIZE 1024 #endif /* _SMBLDAP_H */ diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c index 65a039b..a9ba5e8 100644 --- a/source/lib/smbldap.c +++ b/source/lib/smbldap.c @@ -612,67 +612,115 @@ int smb_ldap_start_tls(LDAP *ldap_struct, int version) int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri) { int rc; - - DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri)); - + int ot = lp_ldap_operation_timeout() * 1000; + int ct = lp_ldap_connection_timeout(); +#ifdef LDAP_X_OPT_CONNECT_TIMEOUT + ct *= 1000; +#endif +#ifndef HAVE_LDAP_INITIALIZE + int port = 0; + fstring protocol; + fstring host; +#endif + DEBUG(10, ("smb_ldap_setup_conn: %s\n", uri)); #ifdef HAVE_LDAP_INITIALIZE - - rc = ldap_initialize(ldap_struct, uri); - if (rc) { - DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); + if ((rc = ldap_initialize(ldap_struct, uri)) != LDAP_SUCCESS) { + DEBUG(0, ("ldap_initialize with %s failed: %s\n", + uri, ldap_err2string(rc))); + return rc; } - return rc; + DEBUG(3,("Successfully setup ldap_initialize with %s\n", uri)); #else - /* Parse the string manually */ + SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); - { - int port = 0; - fstring protocol; - fstring host; - SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); + sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port); + if (port == 0) { + if (strequal(protocol, "ldap")) { + port = LDAP_PORT; + } else if (strequal(protocol, "ldaps")) { + port = LDAPS_PORT; + } else { + DEBUG(0, ("Unrecognised protocol: %s\n", protocol)); + } + } + + if (strequal(protocol, "ldaps")) { +#ifdef LDAP_OPT_X_TLS /* OpenLDAP */ + int tls = LDAP_OPT_X_TLS_HARD; - /* skip leading "URL:" (if any) */ - if ( strnequal( uri, "URL:", 4 ) ) { - uri += 4; + if ((*ldap_struct = ldap_init(host, port)) == NULL) { + DEBUG(0, ("ldap_init with %s:%d failed\n", host, port)); + return LDAP_OPERATIONS_ERROR; } - - sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port); - - if (port == 0) { - if (strequal(protocol, "ldap")) { - port = LDAP_PORT; - } else if (strequal(protocol, "ldaps")) { - port = LDAPS_PORT; - } else { - DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); - } + + DEBUG(3,("Successfully setup ldap session with %s:%d\n", + host, port)); + + rc = ldap_set_option(*ldap_struct, LDAP_OPT_X_TLS, &tls); + if (rc != LDAP_SUCCESS) { + DEBUG(0, ("Failed to setup a TLS option: %s\n", + ldap_err2string(rc))); + return rc; } - - if ((*ldap_struct = ldap_init(host, port)) == NULL) { - DEBUG(0, ("ldap_init failed !\n")); + + DEBUG(3,("Successfully setup TLS option\n")); +#elif defined(HAVE_LDAPSSL_INIT) /* Netscape */ + rc = ldapssl_client_init(lp_ldap_certfile(), NULL); + if (rc != LDAP_SUCCESS) { + DEBUG(0,("ldapssl_client_init with '%s' cert db " + "failed: %s\n", lp_ldap_certfile(), + ldap_err2string(rc))); + return rc; + } + + if ((*ldap_struct = ldapssl_init(host, port, True)) == NULL) { + DEBUG(0, ("ldapssl_init to %s:%d failed!\n", host, + port)); return LDAP_OPERATIONS_ERROR; } - - if (strequal(protocol, "ldaps")) { -#ifdef LDAP_OPT_X_TLS - int tls = LDAP_OPT_X_TLS_HARD; - if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) - { - DEBUG(0, ("Failed to setup a TLS session\n")); - } - - DEBUG(3,("LDAPS option set...!\n")); + + DEBUG(3,("Successfully setup ldapssl session with %s:%d\n", + host, port )); #else - DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; + DEBUG(0,("Secure connection not supported by LDAP client " + "libraries\n")); + return LDAP_OPERATIONS_ERROR; #endif /* LDAP_OPT_X_TLS */ + } else { + if ((*ldap_struct = ldap_init(host, port)) == NULL) { + DEBUG(0, ("ldap_init with %s:%d failed\n", host, port)); + return LDAP_OPERATIONS_ERROR; } + DEBUG(3,("Successfully setup ldap session with %s:%d\n", + host, port)); } #endif /* HAVE_LDAP_INITIALIZE */ +#ifdef LDAP_OPT_TIMELIMIT + rc = ldap_set_option(*ldap_struct, LDAP_OPT_TIMELIMIT, &ot); + if (rc != LDAP_SUCCESS) { + DEBUG(0,("Failed to setup a ldap operation timeout %d: %s\n", + ot, ldap_err2string(rc))); + } +#endif /* LDAP_OPT_TIMELIMIT */ + +#ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */ + rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct); + if (rc != LDAP_SUCCESS) { + DEBUG(0,("Failed to setup a ldap connection timeout %d: %s\n", + ct, ldap_err2string(rc))); + } +#elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */ + rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct); + if (rc != LDAP_SUCCESS) { + DEBUG(0,("Failed to setup a ldap connection timeout %d: %s\n", + ct, ldap_err2string(rc))); + } +#endif + return LDAP_SUCCESS; } @@ -1174,7 +1222,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state, int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_filter; - time_t endtime = time(NULL)+lp_ldap_timeout(); + time_t endtime = time(NULL)+lp_ldap_operation_timeout(); struct timeval timeout; SMB_ASSERT(ldap_state); @@ -1211,7 +1259,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state, } /* Setup timeout for the ldap_search_ext_s call - local and remote. */ - timeout.tv_sec = lp_ldap_timeout(); + timeout.tv_sec = lp_ldap_operation_timeout(); timeout.tv_usec = 0; /* Setup alarm timeout.... Do we need both of these ? JRA. @@ -1223,7 +1271,7 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state, got_alarm = 0; CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); - alarm(lp_ldap_timeout()); + alarm(lp_ldap_operation_timeout()); /* End setup timeout. */ while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) { @@ -1371,7 +1419,7 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; - time_t endtime = time(NULL)+lp_ldap_timeout(); + time_t endtime = time(NULL)+lp_ldap_operation_timeout(); SMB_ASSERT(ldap_state); @@ -1414,7 +1462,7 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; - time_t endtime = time(NULL)+lp_ldap_timeout(); + time_t endtime = time(NULL)+lp_ldap_operation_timeout(); SMB_ASSERT(ldap_state); @@ -1457,7 +1505,7 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) int rc = LDAP_SERVER_DOWN; int attempts = 0; char *utf8_dn; - time_t endtime = time(NULL)+lp_ldap_timeout(); + time_t endtime = time(NULL)+lp_ldap_operation_timeout(); SMB_ASSERT(ldap_state); @@ -1502,7 +1550,7 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state, { int rc = LDAP_SERVER_DOWN; int attempts = 0; - time_t endtime = time(NULL)+lp_ldap_timeout(); + time_t endtime = time(NULL)+lp_ldap_operation_timeout(); if (!ldap_state) return (-1); diff --git a/source/libads/cldap.c b/source/libads/cldap.c index 39e736f..f954ffe 100644 --- a/source/libads/cldap.c +++ b/source/libads/cldap.c @@ -192,7 +192,7 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) DATA_BLOB os3 = data_blob_null; int i1; /* half the time of a regular ldap timeout, not less than 3 seconds. */ - unsigned int al_secs = MAX(3,lp_ldap_timeout()/2); + unsigned int al_secs = MAX(3,lp_ldap_operation_timeout()/2); char *p; blob = data_blob(NULL, 8192); diff --git a/source/libads/ldap.c b/source/libads/ldap.c index a9eff48..ed341fd 100644 --- a/source/libads/ldap.c +++ b/source/libads/ldap.c @@ -98,13 +98,13 @@ static int ldap_search_with_timeout(LDAP *ld, int result; /* Setup timeout for the ldap_search_ext_s call - local and remote. */ - timeout.tv_sec = lp_ldap_timeout(); + timeout.tv_sec = lp_ldap_operation_timeout(); timeout.tv_usec = 0; /* Setup alarm timeout.... Do we need both of these ? JRA. */ gotalarm = 0; CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); - alarm(lp_ldap_timeout()); + alarm(lp_ldap_operation_timeout()); /* End setup timeout. */ result = ldap_search_ext_s(ld, base, scope, filter, attrs, @@ -460,7 +460,7 @@ got_connection: /* Otherwise setup the TCP LDAP session */ ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name, - LDAP_PORT, lp_ldap_timeout()); + LDAP_PORT, lp_ldap_operation_timeout()); if (ads->ldap.ld == NULL) { status = ADS_ERROR(LDAP_OPERATIONS_ERROR); goto out; diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 962c0a4..d32de76 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -253,6 +253,7 @@ struct global { int ldap_ssl; char *szLdapSuffix; char *szLdapAdminDn; + char *ldap_certfile; int ldap_debug_level; int ldap_debug_threshold; int iAclCompat; @@ -263,7 +264,8 @@ struct global { bool clustering; int ldap_passwd_sync; int ldap_replication_sleep; - int ldap_timeout; /* This is initialised in init_globals */ + int ldap_connection_timeout; + int ldap_operation_timeout; int ldap_page_size; bool ldap_delete_dn; bool bMsAddPrinterWizard; @@ -3509,6 +3511,15 @@ static struct parm_struct parm_table[] = { .flags = FLAG_ADVANCED, }, { + .label = "ldap cert db", + .type = P_STRING, + .p_class = P_GLOBAL, + .ptr = &Globals.ldap_certfile, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, + { .label = "ldap passwd sync", .type = P_ENUM, .p_class = P_GLOBAL, @@ -3554,10 +3565,19 @@ static struct parm_struct parm_table[] = { .flags = FLAG_ADVANCED, }, { - .label = "ldap timeout", + .label = "ldap connection timeout", + .type = P_INTEGER, + .p_class = P_GLOBAL, + .ptr = &Globals.ldap_connection_timeout, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, + { + .label = "ldap operation timeout", .type = P_INTEGER, .p_class = P_GLOBAL, - .ptr = &Globals.ldap_timeout, + .ptr = &Globals.ldap_operation_timeout, .special = NULL, .enum_list = NULL, .flags = FLAG_ADVANCED, @@ -4752,11 +4772,13 @@ static void init_globals(bool first_time_only) string_set(&Globals.szLdapIdmapSuffix, ""); string_set(&Globals.szLdapAdminDn, ""); + string_set(&Globals.ldap_certfile, ""); Globals.ldap_ssl = LDAP_SSL_ON; Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF; Globals.ldap_delete_dn = False; Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */ - Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT; + Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT; + Globals.ldap_operation_timeout = LDAP_OPERATION_DEFAULT_TIMEOUT; Globals.ldap_page_size = LDAP_PAGE_SIZE; Globals.ldap_debug_level = 0; @@ -5070,11 +5092,13 @@ FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit) FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix) FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn) +FN_GLOBAL_STRING(lp_ldap_certfile, &Globals.ldap_certfile) FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl) FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync) FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn) FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep) -FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout) +FN_GLOBAL_INTEGER(lp_ldap_connection_timeout, &Globals.ldap_connection_timeout) +FN_GLOBAL_INTEGER(lp_ldap_operation_timeout, &Globals.ldap_operation_timeout) FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size) FN_GLOBAL_INTEGER(lp_ldap_debug_level, &Globals.ldap_debug_level) FN_GLOBAL_INTEGER(lp_ldap_debug_threshold, &Globals.ldap_debug_threshold) diff --git a/source/winbindd/winbindd_rpc.c b/source/winbindd/winbindd_rpc.c index bb79d7e..0f905d9 100644 --- a/source/winbindd/winbindd_rpc.c +++ b/source/winbindd/winbindd_rpc.c @@ -852,7 +852,7 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq) * search timeout doesn't seem to apply to doing an open as well. JRA. */ - ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout()); + ldp = ldap_open_with_timeout(server, port, lp_ldap_operation_timeout()); if (ldp == NULL) return -1; -- 1.5.4.4