Return-Path: Mailing-List: contact commits-help@apr.apache.org; run by ezmlm Delivered-To: mailing list commits@apr.apache.org Received: (qmail 73984 invoked by uid 99); 8 Jan 2005 17:18:50 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from minotaur.apache.org (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Sat, 08 Jan 2005 09:18:49 -0800 Received: (qmail 15534 invoked by uid 65534); 8 Jan 2005 17:18:47 -0000 Date: 8 Jan 2005 17:18:47 -0000 Message-ID: <20050108171847.15528.qmail@minotaur.apache.org> From: minfrin@apache.org To: commits@apr.apache.org Subject: svn commit: r124662 - /apr/apr-util/trunk/CHANGES /apr/apr-util/trunk/include/apr_ldap_init.h /apr/apr-util/trunk/include/apr_ldap_option.h /apr/apr-util/trunk/ldap/apr_ldap_init.c /apr/apr-util/trunk/ldap/apr_ldap_option.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Virus-Checked: Checked Author: minfrin Date: Sat Jan 8 09:18:45 2005 New Revision: 124662 URL: http://svn.apache.org/viewcvs?view=rev&rev=124662 Log: LDAP: Move all certificate initialisation, and the creation of SSL and TLS connections into the apr_ldap_set_option() API. Add support for client certificates. Modified: apr/apr-util/trunk/CHANGES apr/apr-util/trunk/include/apr_ldap_init.h apr/apr-util/trunk/include/apr_ldap_option.h apr/apr-util/trunk/ldap/apr_ldap_init.c apr/apr-util/trunk/ldap/apr_ldap_option.c Modified: apr/apr-util/trunk/CHANGES Url: http://svn.apache.org/viewcvs/apr/apr-util/trunk/CHANGES?view=diff&rev=124662&p1=apr/apr-util/trunk/CHANGES&r1=124661&p2=apr/apr-util/trunk/CHANGES&r2=124662 ============================================================================== --- apr/apr-util/trunk/CHANGES (original) +++ apr/apr-util/trunk/CHANGES Sat Jan 8 09:18:45 2005 @@ -1,5 +1,9 @@ Changes with APR-util 1.1.0 + *) LDAP: Move all certificate initialisation, and the creation of SSL + and TLS connections into the apr_ldap_set_option() API. Add support + for client certificates. [Graham Leggett] + *) Emit the run-time link path option in apu-config after installation if the user is linking with libtool. [Justin Erenkrantz] Modified: apr/apr-util/trunk/include/apr_ldap_init.h Url: http://svn.apache.org/viewcvs/apr/apr-util/trunk/include/apr_ldap_init.h?view=diff&rev=124662&p1=apr/apr-util/trunk/include/apr_ldap_init.h&r1=124661&p2=apr/apr-util/trunk/include/apr_ldap_init.h&r2=124662 ============================================================================== --- apr/apr-util/trunk/include/apr_ldap_init.h (original) +++ apr/apr-util/trunk/include/apr_ldap_init.h Sat Jan 8 09:18:45 2005 @@ -28,6 +28,14 @@ #define APR_LDAP_CA_TYPE_DER 1 #define APR_LDAP_CA_TYPE_BASE64 2 #define APR_LDAP_CA_TYPE_CERT7_DB 3 +#define APR_LDAP_CA_TYPE_SECMOD 4 +#define APR_LDAP_CERT_TYPE_UNKNOWN 5 +#define APR_LDAP_CERT_TYPE_DER 6 +#define APR_LDAP_CERT_TYPE_BASE64 7 +#define APR_LDAP_CERT_TYPE_KEY3_DB 8 +#define APR_LDAP_KEY_TYPE_UNKNOWN 9 +#define APR_LDAP_KEY_TYPE_DER 10 +#define APR_LDAP_KEY_TYPE_BASE64 11 APU_DECLARE(int) apr_ldap_ssl_init(apr_pool_t *pool, const char *cert_auth_file, Modified: apr/apr-util/trunk/include/apr_ldap_option.h Url: http://svn.apache.org/viewcvs/apr/apr-util/trunk/include/apr_ldap_option.h?view=diff&rev=124662&p1=apr/apr-util/trunk/include/apr_ldap_option.h&r1=124661&p2=apr/apr-util/trunk/include/apr_ldap_option.h&r2=124662 ============================================================================== --- apr/apr-util/trunk/include/apr_ldap_option.h (original) +++ apr/apr-util/trunk/include/apr_ldap_option.h Sat Jan 8 09:18:45 2005 @@ -33,39 +33,112 @@ /* * The following defines handle the different TLS certificate * options available. If these options are missing, APR will try and - * emulate support for this using the derecated ldap_start_tls_s() + * emulate support for this using the deprecated ldap_start_tls_s() * function. */ -#ifdef LDAP_OPT_X_TLS_NEVER -#define APR_LDAP_OPT_TLS_NEVER LDAP_OPT_X_TLS_NEVER -#else -#define APR_LDAP_OPT_TLS_NEVER 0 -#endif +#define APR_LDAP_OPT_TLS 0x6fff +#define APR_LDAP_OPT_TLS_CERT 0x6ffe -#ifdef LDAP_OPT_X_TLS_HARD -#define APR_LDAP_OPT_TLS_HARD LDAP_OPT_X_TLS_HARD -#else -#define APR_LDAP_OPT_TLS_HARD 1 -#endif - -#ifdef LDAP_OPT_X_TLS_DEMAND -#define APR_LDAP_OPT_TLS_DEMAND LDAP_OPT_X_TLS_DEMAND -#else -#define APR_LDAP_OPT_TLS_DEMAND 2 -#endif +/** + * Structures for the apr_set_option() cases + */ -#ifdef LDAP_OPT_X_TLS_ALLOW -#define APR_LDAP_OPT_TLS_ALLOW LDAP_OPT_X_TLS_ALLOW -#else -#define APR_LDAP_OPT_TLS_ALLOW 3 -#endif +/** + * APR_LDAP_OPT_TLS_CERT + * + * This structure includes possible options to set certificates on + * system initialisation. Different SDKs have different certificate + * requirements, and to achieve this multiple certificates must be + * specified at once. + * + * Netscape: + * Needs the CA cert database (cert7.db), the client cert database (key3.db) + * and the security module file (secmod.db) set at the system initialisation + * time. Three types are supported: APR_LDAP_CERT7_DB, APR_LDAP_KEY3_DB and + * APR_LDAP_SECMOD. + * + * To specify a client cert connection, a certificate nickname needs to be + * provided with a type of APR_LDAP_CERT. + * int ldapssl_enable_clientauth( LDAP *ld, char *keynickname, + * char *keypasswd, char *certnickname ); + * keynickname is currently not used, and should be set to "" + * + * Novell: + * Needs CA certificates and client certificates set at system initialisation + * time. Three types are supported: APR_LDAP_CA*, APR_LDAP_CERT* and + * APR_LDAP_KEY*. + * + * Certificates cannot be specified per connection. + * + * The functions used are: + * ldapssl_add_trusted_cert(serverTrustedRoot, serverTrustedRootEncoding); + * Clients certs and keys are set at system initialisation time with + * int ldapssl_set_client_cert ( + * void *cert, + * int type + * void *password); + * type can be LDAPSSL_CERT_FILETYPE_B64 or LDAPSSL_CERT_FILETYPE_DER + * ldapssl_set_client_private_key(clientPrivateKey, + * clientPrivateKeyEncoding, + * clientPrivateKeyPassword); + * + * OpenSSL: + * Needs one or more CA certificates to be set at system initialisation time + * with a type of APR_LDAP_CA*. + * + * May have one or more client certificates set per connection with a type of + * APR_LDAP_CERT*, and keys with APR_LDAP_KEY*. + */ +#define APR_LDAP_CA_TYPE_UNKNOWN 0 +#define APR_LDAP_CA_TYPE_DER 1 +#define APR_LDAP_CA_TYPE_BASE64 2 +#define APR_LDAP_CA_TYPE_CERT7_DB 3 +#define APR_LDAP_CA_TYPE_SECMOD 4 +#define APR_LDAP_CERT_TYPE_UNKNOWN 5 +#define APR_LDAP_CERT_TYPE_DER 6 +#define APR_LDAP_CERT_TYPE_BASE64 7 +#define APR_LDAP_CERT_TYPE_KEY3_DB 8 +#define APR_LDAP_KEY_TYPE_UNKNOWN 9 +#define APR_LDAP_KEY_TYPE_DER 10 +#define APR_LDAP_KEY_TYPE_BASE64 11 -#ifdef LDAP_OPT_X_TLS_TRY -#define APR_LDAP_OPT_TLS_TRY LDAP_OPT_X_TLS_TRY -#else -#define APR_LDAP_OPT_TLS_TRY 4 -#endif +typedef struct apr_ldap_opt_tls_cert_t apr_ldap_opt_tls_cert_t; +struct apr_ldap_opt_tls_cert_t { + int type; + const char *path; + const char *password; + apr_ldap_opt_tls_cert_t *next; +}; +/** + * APR_LDAP_OPT_TLS + * + * This sets the SSL level on the LDAP handle. + * + * Netscape/Mozilla: + * Supports SSL, but not STARTTLS + * SSL is enabled by calling ldapssl_install_routines(). + * + * Novell: + * Supports SSL and STARTTLS. + * SSL is enabled by calling ldapssl_install_routines(). Note that calling + * other ldap functions before ldapssl_install_routines() may cause this + * function to fail. + * STARTTLS is enabled by calling ldapssl_start_tls_s() after calling + * ldapssl_install_routines() (check this). + * + * OpenLDAP: + * Supports SSL and apparently supports STARTTLS + * Currently it is not clear whether OpenLDAP can support SSL, apparently it + * can. + * Support for STARTTLS is also unconfirmed - ldap_start_tls_s() has been + * deprecated, but no replacement method or function has been defined. Even the + * OpenLDAP source code is uncommented and yields no clues... + */ +#define APR_LDAP_NONE 0 +#define APR_LDAP_SSL 1 +#define APR_LDAP_STARTTLS 2 +#define APR_LDAP_STOPTLS 3 /** * APR LDAP get option function Modified: apr/apr-util/trunk/ldap/apr_ldap_init.c Url: http://svn.apache.org/viewcvs/apr/apr-util/trunk/ldap/apr_ldap_init.c?view=diff&rev=124662&p1=apr/apr-util/trunk/ldap/apr_ldap_init.c&r1=124661&p2=apr/apr-util/trunk/ldap/apr_ldap_init.c&r2=124662 ============================================================================== --- apr/apr-util/trunk/ldap/apr_ldap_init.c (original) +++ apr/apr-util/trunk/ldap/apr_ldap_init.c Sat Jan 8 09:18:45 2005 @@ -33,9 +33,15 @@ /** * APR LDAP SSL Initialise function * - * This function sets up any SSL certificate parameters as - * required by the application. It should be called once on - * system initialisation. + * This function initialises SSL on the underlying LDAP toolkit + * if this is necessary. + * + * If a CA certificate is provided, this is set, however the setting + * of certificates via this method has been deprecated and will be removed in + * APR v2.0. + * + * The apr_ldap_set_option() function with the APR_LDAP_OPT_TLS_CERT option + * should be used instead to set certificates. * * If SSL support is not available on this platform, or a problem * was encountered while trying to set the certificate, the function @@ -47,209 +53,40 @@ int cert_file_type, apr_ldap_err_t **result_err) { - apr_ldap_err_t *result; - - if (cert_auth_file) { - return apr_ldap_ssl_add_cert(pool, - cert_auth_file, - cert_file_type, - result_err); - } - else { - result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t)); - *result_err = result; -#if APR_HAS_LDAP_SSL /* compiled with ssl support */ - - /* Novell needs special initialisation */ -#if APR_HAS_NOVELL_LDAPSDK -#if APR_HAS_LDAPSSL_CLIENT_INIT - result->rc = ldapssl_client_init(NULL, NULL); - - if (LDAP_SUCCESS == result->rc) { - return APR_SUCCESS; - } - else { - result->msg = ldap_err2string(result-> rc); - result->reason = apr_pstrdup (pool, "LDAP: Could not " - "initialize SSL"); - return APR_EGENERAL; - } -#else - result->reason = "LDAP: ldapssl_client_init() function not " - "supported by this Novell SDK. SSL not " - "initialised"; - result->rc = -1; -#endif -#endif - -#endif - } - - /* if no cert_auth_file was passed, we assume SSL support - * is possible, as we have not been specifically told otherwise. - */ - return APR_SUCCESS; - -} - - -/** - * APR LDAP SSL add client certificate function. - * - * This function sets up an optional client certificate to be used - * when connecting to the remote LDAP server. - * If SSL support is not available on this platform, or a problem - * was encountered while trying to set the certificate, the function - * will return APR_EGENERAL. Further LDAP specific error information - * can be found in result_err. - */ -APU_DECLARE(int) apr_ldap_ssl_add_cert(apr_pool_t *pool, - const char *cert_auth_file, - int cert_file_type, - apr_ldap_err_t **result_err) { - apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t)); *result_err = result; - if (cert_auth_file) { #if APR_HAS_LDAP_SSL /* compiled with ssl support */ - /* Netscape SDK */ -#if APR_HAS_NETSCAPE_LDAPSDK -#if APR_HAS_LDAP_SSL_CLIENT_INIT - /* Netscape sdk only supports a cert7.db file - */ - if (cert_file_type == APR_LDAP_CA_TYPE_CERT7_DB) { - result->rc = ldapssl_client_init(cert_auth_file, NULL); - } - else { - result->reason = "LDAP: Invalid certificate type: " - "CERT7_DB type required"; - result->rc = -1; - } -#else - result->reason = "LDAP: ldapssl_client_init() function not " - "supported by this Netscape SDK. Certificate " - "authority file not set"; - result->rc = -1; -#endif -#endif - - /* Novell SDK */ + /* Novell */ #if APR_HAS_NOVELL_LDAPSDK -#if APR_HAS_LDAPSSL_CLIENT_INIT && APR_HAS_LDAPSSL_ADD_TRUSTED_CERT && APR_HAS_LDAPSSL_CLIENT_DEINIT - /* Novell SDK supports DER or BASE64 files - */ - if (cert_file_type == APR_LDAP_CA_TYPE_DER || - cert_file_type == APR_LDAP_CA_TYPE_BASE64 ) { - - result->rc = ldapssl_client_init(NULL, NULL); - if (LDAP_SUCCESS == result->rc) { - if (cert_file_type == APR_LDAP_CA_TYPE_BASE64) { - result->rc = ldapssl_add_trusted_cert((void*)cert_auth_file, - LDAPSSL_CERT_FILETYPE_B64); - } - else { - result->rc = ldapssl_add_trusted_cert((void*)cert_auth_file, - LDAPSSL_CERT_FILETYPE_DER); - } - - if (LDAP_SUCCESS != result->rc) { - ldapssl_client_deinit(); - result->reason = apr_psprintf(pool, - "LDAP: Invalid certificate " - "or path: Could not add " - "trusted cert %s", - cert_auth_file); - } - } - } - else { - result->reason = "LDAP: Invalid certificate type: " - "DER or BASE64 type required"; - result->rc = -1; - } -#else - result->reason = "LDAP: ldapssl_client_init(), " - "ldapssl_add_trusted_cert() or " - "ldapssl_client_deinit() functions not supported " - "by this Novell SDK. Certificate authority file " - "not set"; - result->rc = -1; -#endif + ldapssl_client_init(NULL, NULL); #endif - /* openldap SDK */ -#if APR_HAS_OPENLDAP_LDAPSDK -#ifdef LDAP_OPT_X_TLS_CACERTFILE - /* OpenLDAP SDK supports BASE64 files - */ - if (cert_file_type == APR_LDAP_CA_TYPE_BASE64) { - result->rc = ldap_set_option(NULL, - LDAP_OPT_X_TLS_CACERTFILE, - cert_auth_file); - } - else { - result->reason = "LDAP: Invalid certificate type: " - "BASE64 type required"; - result->rc = -1; - } -#else - result->reason = "LDAP: LDAP_OPT_X_TLS_CACERTFILE not " - "defined by this OpenLDAP SDK. Certificate " - "authority file not set"; - result->rc = -1; -#endif -#endif - - /* microsoft SDK */ -#if APR_HAS_MICROSOFT_LDAPSDK - /* Microsoft SDK use the registry certificate store - always - * assume support is always available - */ - result->rc = LDAP_SUCCESS; -#endif - - /* Sun SDK */ -#if APR_HAS_SOLARIS_LDAPSDK - result->reason = "LDAP: Attempt to set certificate store failed. " - "APR does not yet know how to set a certificate " - "store on the Sun toolkit"; - result->rc = -1; -#endif - - /* SDK not recognised */ -#if APR_HAS_OTHER_LDAPSDK - /* unknown toolkit type, assume no support available */ - result->reason = "LDAP: Attempt to set certificate store failed. " - "Toolkit type not recognised by APR as supporting " - "SSL"; - result->rc = -1; -#endif + /* if a certificate was specified, set it */ + if (cert_auth_file) { + apr_ldap_opt_tls_cert_t *cert = (apr_ldap_opt_tls_cert_t *)apr_palloc(pool, sizeof(apr_ldap_opt_tls_cert_t)); + cert->type = cert_file_type; + cert->path = cert_auth_file; + return apr_ldap_set_option(pool, NULL, APR_LDAP_OPT_TLS, (void *)cert, result_err); + } #else /* not compiled with SSL Support */ - + if (cert_auth_file) { result->reason = "LDAP: Attempt to set certificate store failed. " "Not built with SSL support"; result->rc = -1; - + } #endif /* APR_HAS_LDAP_SSL */ - if (result->rc != -1) { - result->msg = ldap_err2string(result-> rc); - } - - if (LDAP_SUCCESS == result->rc) { - return APR_SUCCESS; - } - else { - return APR_EGENERAL; - } + if (result->rc != -1) { + result->msg = ldap_err2string(result-> rc); + } + + if (LDAP_SUCCESS != result->rc) { + return APR_EGENERAL; } - /* if no cert_auth_file was passed, we assume SSL support - * is possible, as we have not been specifically told otherwise. - */ return APR_SUCCESS; } @@ -293,11 +130,9 @@ * toolkit supports it, the following values are accepted for * secure: * - * APR_LDAP_OPT_TLS_NEVER: No encryption - * APR_LDAP_OPT_TLS_HARD: SSL encryption (ldaps://) - * APR_LDAP_OPT_TLS_DEMAND: Force STARTTLS on ldap:// - * APR_LDAP_OPT_TLS_ALLOW: Allow STARTTLS on ldap:// - * APR_LDAP_OPT_TLS_TRY: Optionally try STARTLS on ldap:// + * APR_LDAP_NONE: No encryption + * APR_LDAP_SSL: SSL encryption (ldaps://) + * APR_LDAP_STARTTLS: Force STARTTLS on ldap:// */ APU_DECLARE(int) apr_ldap_init(apr_pool_t *pool, LDAP **ldap, @@ -309,124 +144,13 @@ apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t)); *result_err = result; - /* clear connection requested */ - if (!secure) { - *ldap = ldap_init((char *)hostname, portno); + *ldap = ldap_init((char *)hostname, portno); + if (*ldap != NULL) { + return apr_ldap_set_option(pool, *ldap, APR_LDAP_OPT_TLS, &secure, result_err); } - else { /* ssl connnection requested */ -#if APR_HAS_LDAP_SSL - - /* netscape toolkit */ -#if APR_HAS_NETSCAPE_LDAPSDK -#if APR_HAS_LDAPSSL_INIT - *ldap = ldapssl_init(hostname, portno, 1); -#else - result->reason = "LDAP: SSL not yet supported by APR on " - "this version of the Netscape toolkit"; - return APR_ENOTIMPL; -#endif -#endif - - /* novell toolkit */ -#if APR_HAS_NOVELL_LDAPSDK - if (secure == APR_LDAP_OPT_TLS_HARD) { - *ldap = ldapssl_init(hostname, portno, 1); - } - else { - *ldap = ldapssl_init(hostname, portno, 0); - result->rc = ldapssl_start_tls(*ldap); - if (LDAP_SUCCESS != result->rc) { - ldap_unbind_s(*ldap); - result->reason = "LDAP: ldapssl_start_tls failed, " - "could not set security mode for " - "apr_ldap_init()"; - result->msg = ldap_err2string(result->rc); - *ldap = NULL; - return APR_EGENERAL; - } - } -#endif - - /* openldap toolkit */ -#if APR_HAS_OPENLDAP_LDAPSDK -#ifdef LDAP_OPT_X_TLS - *ldap = ldap_init(hostname, portno); - if (NULL != *ldap) { - int SSLmode = secure; - result->rc = ldap_set_option(*ldap, LDAP_OPT_X_TLS, &SSLmode); - if (LDAP_SUCCESS != result->rc) { - ldap_unbind_s(*ldap); - result->reason = "LDAP: ldap_set_option failed, " - "could not set security mode for " - "apr_ldap_init()"; - result->msg = ldap_err2string(result->rc); - *ldap = NULL; - return APR_EGENERAL; - } - } -#else - result->reason = "LDAP: SSL/TLS not yet supported by APR on this " - "version of the OpenLDAP toolkit"; - return APR_ENOTIMPL; -#endif -#endif - - /* microsoft toolkit */ -#if APR_HAS_MICROSOFT_LDAPSDK - if (APR_LDAP_OPT_TLS_HARD == secure) { - *ldap = ldap_sslinit((char *)hostname, portno, 1); - } - else { - if (APR_LDAP_OPT_TLS_DEMAND == secure) { - *ldap = ldap_init(hostname, portno); - if (NULL != *ldap) { - result->rc = ldap_start_tls_s(*ldap, NULL, NULL, NULL, NULL); - if (LDAP_SUCCESS != result->rc) { - ldap_unbind_s(*ldap); - result->reason = "LDAP: ldap_start_tls_s() failed, " - "could not set STARTTLS mode for " - "apr_ldap_init()"; - result->msg = ldap_err2string(result->rc); - *ldap = NULL; - return APR_EGENERAL; - } - } - } - else { - result->reason = "LDAP: APR_LDAP_OPT_TLS_ALLOW and " - "APR_LDAP_OPT_TLS_TRY are not supported " - "by APR on this version of the Microsoft " - "toolkit. Use APR_LDAP_OPT_TLS_DEMAND " - "instead to enable STARTTLS"; - return APR_ENOTIMPL; - } - } -#endif - - /* sun toolkit */ -#if APR_HAS_SOLARIS_LDAPSDK - result->reason = "LDAP: SSL not yet supported by APR on " - "this version of the Sun toolkit"; - return APR_ENOTIMPL; -#endif - - /* unknown toolkit - return not implemented */ -#if APR_HAS_OTHER_LDAPSDK - return APR_ENOTIMPL; -#endif - -#endif /* APR_HAS_LDAP_SSL */ - } - - /* if the attempt returned a NULL object, return an error - * from the os as per the LDAP C SDK. - */ - if (NULL == *ldap) { + else { return apr_get_os_error(); } - - /* otherwise we were successful */ - return APR_SUCCESS; } Modified: apr/apr-util/trunk/ldap/apr_ldap_option.c Url: http://svn.apache.org/viewcvs/apr/apr-util/trunk/ldap/apr_ldap_option.c?view=diff&rev=124662&p1=apr/apr-util/trunk/ldap/apr_ldap_option.c&r1=124661&p2=apr/apr-util/trunk/ldap/apr_ldap_option.c&r2=124662 ============================================================================== --- apr/apr-util/trunk/ldap/apr_ldap_option.c (original) +++ apr/apr-util/trunk/ldap/apr_ldap_option.c Sat Jan 8 09:18:45 2005 @@ -87,18 +87,460 @@ return APR_ENOMEM; } - /* set the option specified using the native LDAP function */ - result->rc = ldap_set_option(ldap, option, (void *)invalue); + switch (option) { + case APR_LDAP_OPT_TLS_CERT: { + option_set_cert(pool, ldap, invalue, result); + break; + } + case APR_LDAP_OPT_TLS: { + option_set_tls(pool, ldap, invalue, result); + break; + } + default: { + + /* set the option specified using the native LDAP function */ + result->rc = ldap_set_option(ldap, option, (void *)invalue); + + /* handle the error case */ + if (LDAP_SUCCESS != result->rc) { + result->msg = ldap_err2string(result->rc); + result->reason = "LDAP: Could not set an option"; + } + + } + } /* handle the error case */ if (LDAP_SUCCESS != result->rc) { - result->msg = ldap_err2string(result-> rc); - result->reason = apr_pstrdup (pool, "LDAP: Could not get an option"); return APR_EGENERAL; } return APR_SUCCESS; } + +/** + * Handle APR_LDAP_OPT_TLS + * + * This function sets the type of TLS to be applied to this connection. + * The options are: + * APR_LDAP_NONE: no encryption + * APR_LDAP_SSL: SSL encryption (ldaps://) + * APR_LDAP_STARTTLS: STARTTLS encryption + * APR_LDAP_STOPTLS: Stop existing TLS connecttion + */ +int option_set_tls(apr_pool_t *pool, + LDAP *ldap, + const void *invalue, + apr_ldap_err_t *result) { + + int tls = * (const int *)invalue; + +#if APR_HAS_LDAP_SSL /* compiled with ssl support */ + + /* Netscape SDK */ +#if APR_HAS_NETSCAPE_LDAPSDK + if (APR_LDAP_SSL == tls) { + result->rc = ldapssl_install_routines(ldap); + if (result->rc == LDAP_SUCCESS) { + result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, LDAP_OPT_ON); + } + if (result->rc != LDAP_SUCCESS) { + result->msg = ldap_err2string(result->rc); + result->reason = "LDAP: Could not switch SSL on for this " + "connection."; + } + } + else if (APR_LDAP_STARTTLS == tls) { + result->reason = "LDAP: STARTTLS is not supported by the " + "Netscape/Mozilla SDK"; + result->rc = -1; + } + else if (APR_LDAP_STOPTLS == tls) { + result->reason = "LDAP: STOPTLS is not supported by the " + "Netscape/Mozilla SDK"; + result->rc = -1; + } +#endif + + /* Novell SDK */ +#if APR_HAS_NOVELL_SDK + /* ldapssl_install_routines(ldap) + * Behavior is unpredictable when other LDAP functions are called + * between the ldap_init function and the ldapssl_install_routines + * function. + * + * STARTTLS is supported by the ldap_start_tls_s() method + */ + if (APR_LDAP_SSL == tls) { + result->rc = ldapssl_install_routines(ldap); + if (result->rc != LDAP_SUCCESS) { + result->msg = ldap_err2string(result->rc); + result->reason = "LDAP: Could not switch SSL on for this " + "connection."; + } + } + else if (APR_LDAP_STARTTLS == tls) { + result->rc = ldapssl_start_tls(ldap); + if (result->rc != LDAP_SUCCESS) { + result->msg = ldap_err2string(result->rc); + result->reason = "LDAP: Could not start TLS on this connection"; + } + } + else if (APR_LDAP_STOPTLS == tls) { + result->rc = ldapssl_stop_tls(ldap); + if (result->rc != LDAP_SUCCESS) { + result->msg = ldap_err2string(result->rc); + result->reason = "LDAP: Could not stop TLS on this connection"; + } + } +#endif + + /* OpenLDAP SDK */ +#if APR_HAS_OPENLDAP_LDAPSDK +#ifdef LDAP_OPT_X_TLS + if (APR_LDAP_SSL == tls) { + int SSLmode = LDAP_OPT_X_TLS_HARD; + result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS, &SSLmode); + if (LDAP_SUCCESS != result->rc) { + result->reason = "LDAP: ldap_set_option failed. " + "Could not set LDAP_OPT_X_TLS to " + "LDAP_OPT_X_TLS_HARD"; + result->msg = ldap_err2string(result->rc); + } + } + else if (APR_LDAP_STARTTLS == tls) { + result->rc = ldap_start_tls_s(ldap, NULL, NULL); + if (LDAP_SUCCESS != result->rc) { + result->reason = "LDAP: ldap_start_tls_s() failed"; + result->msg = ldap_err2string(result->rc); + } + } + else if (APR_LDAP_STOPTLS == tls) { + result->reason = "LDAP: STOPTLS is not supported by the " + "OpenLDAP SDK"; + result->rc = -1; + } +#else + result->reason = "LDAP: SSL/TLS not yet supported by APR on this " + "version of the OpenLDAP toolkit"; + result->rc = -1; +#endif +#endif + + /* Solaris SDK */ +#if APR_HAS_SOLARIS_LDAPSDK + if (APR_LDAP_NONE != tls) { + result->reason = "LDAP: SSL/TLS is currently not supported by " + "APR on the Solaris SDK"; + result->rc = -1; + } +#endif + + /* Microsoft SDK */ +#if APR_HAS_MICROSOFT_LDAPSDK + if (APR_LDAP_NONE == tls) { + mode = 0; + result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, &mode); + if (LDAP_SUCCESS != result->rc) { + result->reason = "LDAP: an attempt to set LDAP_OPT_SSL off " + "failed."; + result->msg = ldap_err2string(result->rc); + } + } + else if (APR_LDAP_SSL == tls) { + mode = 1; + result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, &mode); + if (LDAP_SUCCESS != result->rc) { + result->reason = "LDAP: an attempt to set LDAP_OPT_SSL on " + "failed."; + result->msg = ldap_err2string(result->rc); + } + } + else if (APR_LDAP_STARTTLS == tls) { + result->rc = ldap_start_tls_s(ldap, NULL, NULL, NULL, NULL); + if (LDAP_SUCCESS != result->rc) { + result->reason = "LDAP: ldap_start_tls_s() failed"; + result->msg = ldap_err2string(result->rc); + } + } + else if (APR_LDAP_STOPTLS == tls) { + result->rc = ldap_stop_tls_s(ldap); + if (LDAP_SUCCESS != result->rc) { + result->reason = "LDAP: ldap_stop_tls_s() failed"; + result->msg = ldap_err2string(result->rc); + } + } +#endif + +#if APR_HAS_OTHER_LDAPSDK + if (APR_LDAP_NONE != tls) { + result->reason = "LDAP: SSL/TLS is currently not supported by " + "APR on this LDAP SDK"; + result->rc = -1; + } +#endif + +#endif /* APR_HAS_LDAP_SSL */ + +} + +/** + * Handle APR_LDAP_OPT_TLS_CACERTFILE + * + * This function sets the CA certificate for further SSL/TLS connections. + * + * The file provided are in different formats depending on the toolkit used: + * + * Netscape: cert7.db file + * Novell: PEM or DER + * OpenLDAP: PEM (others supported?) + * Microsoft: unknown + * Solaris: unknown + */ +int option_set_cert(apr_pool_t *pool, + LDAP *ldap, + const void *invalue, + apr_ldap_err_t *result) { + + apr_ldap_opt_tls_cert_t *cert = (apr_ldap_opt_tls_cert_t *)invalue; + +#if APR_HAS_LDAP_SSL + +#if APR_HAS_NETSCAPE_LDAPSDK +#if APR_HAS_LDAP_SSL_CLIENT_INIT + const char *secmod = NULL; + const char *key3db = NULL; + const char *cert7db = NULL; + + /* set up cert7.db, key3.db and secmod parameters */ + while (cert) { + switch (cert->type) { + case APR_LDAP_CA_TYPE_CERT7_DB: { + cert7db = cert->path; + break; + } + case APR_LDAP_CA_TYPE_SECMOD: { + secmod = cert->path; + break; + } + case APR_LDAP_CERT_TYPE_KEY3_DB: { + key3db = cert->path; + break; + } + default: { + result->rc = -1; + result->reason = "LDAP: The Netscape/Mozilla LDAP SDK only " + "understands the CERT7, KEY3 and SECMOD " + "file types."; + } + } + if (result->rc != LDAP_SUCCESS) { + break; + } + cert = cert->next; + } + + /* actually set the certificate parameters */ + if (result->rc == LDAP_SUCCESS) { + if (secmod) { + result->rc = ldapssl_advclientauth_init(cert7db, NULL, + key3db ? 1 : 0, key3db, NULL, + 1, secmod, LDAPSSL_AUTH_CNCHECK); + if (result->rc != LDAP_SUCCESS) { + result->reason = "LDAP: ldapssl_advclientauth_init() failed."; + result->msg = ldap_err2string(result->rc); + } + } + else if (key3db) { + result->rc = ldapssl_clientauth_init(cert7db, NULL, + 1, key3db, NULL); + if (result->rc != LDAP_SUCCESS) { + result->reason = "LDAP: ldapssl_clientauth_init() failed."; + result->msg = ldap_err2string(result->rc); + } + } + else { + result->rc = ldapssl_client_init(cert7db, NULL); + if (result->rc != LDAP_SUCCESS) { + result->reason = "LDAP: ldapssl_client_init() failed."; + result->msg = ldap_err2string(result->rc); + } + } + } +#else + result->reason = "LDAP: ldapssl_client_init() function not " + "supported by this Netscape SDK. Certificate " + "authority file not set"; + result->rc = -1; +#endif +#endif + + /* Novell SDK */ +#if APR_HAS_NOVELL_LDAPSDK +#if APR_HAS_LDAPSSL_CLIENT_INIT && APR_HAS_LDAPSSL_ADD_TRUSTED_CERT && APR_HAS_LDAPSSL_CLIENT_DEINIT + /* The Novell library cannot support per connection certificates. Error + * out if the ldap handle is provided. + */ + if (ldap) { + result->rc = -1; + result->reason = "LDAP: The Novell LDAP SDK cannot support the setting " + "of certificates or keys on a per connection basis."; + } + /* Novell's library needs to be inititalised first */ + else { + result->rc = ldapssl_client_init(NULL, NULL); + if (LDAP_SUCCESS != result->rc) { + result->msg = ldap_err2string(result-> rc); + result->reason = apr_pstrdup (pool, "LDAP: Could not " + "initialize SSL"); + } + } + /* set one or more certificates */ + while (LDAP_SUCCESS == result->rc && cert) { + /* Novell SDK supports DER or BASE64 files. */ + switch (cert->type) { + case APR_LDAP_CA_TYPE_DER: { + result->rc = ldapssl_add_trusted_cert((void *)cert->path, + LDAPSSL_CERT_FILETYPE_DER); + result->msg = ldap_err2string(result->rc); + break; + } + case APR_LDAP_CA_TYPE_BASE64: { + result->rc = ldapssl_add_trusted_cert((void *)cert->path, + LDAPSSL_CERT_FILETYPE_B64); + result->msg = ldap_err2string(result->rc); + break; + } + case APR_LDAP_CERT_TYPE_DER: { + result->rc = ldapssl_set_client_cert((void *)cert->path, + LDAPSSL_CERT_FILETYPE_DER, + cert->password); + result->msg = ldap_err2string(result->rc); + break; + } + case APR_LDAP_CERT_TYPE_BASE64: { + result->rc = ldapssl_set_client_cert((void *)cert->path, + LDAPSSL_CERT_FILETYPE_B64, + cert->password); + result->msg = ldap_err2string(result->rc); + break; + } + case APR_LDAP_KEY_TYPE_DER: { + result->rc = ldapssl_set_client_private_key((void *)cert->path, + LDAPSSL_CERT_FILETYPE_DER, + cert->password); + result->msg = ldap_err2string(result->rc); + break; + } + case APR_LDAP_KEY_TYPE_BASE64: { + result->rc = ldapssl_set_client_private_key((void *)cert->path, + LDAPSSL_CERT_FILETYPE_B64, + cert->password); + result->msg = ldap_err2string(result->rc); + break; + } + default: { + result->rc = -1; + result->reason = "LDAP: The Novell LDAP SDK only understands the " + "DER and PEM (BASE64) file types."; + } + } + if (LDAP_SUCCESS != result->rc) { + break; + } + cert = cert->next; + } +#else + result->reason = "LDAP: ldapssl_client_init(), " + "ldapssl_add_trusted_cert() or " + "ldapssl_client_deinit() functions not supported " + "by this Novell SDK. Certificate authority file " + "not set"; + result->rc = -1; +#endif +#endif + + /* openldap SDK */ +#if APR_HAS_OPENLDAP_LDAPSDK +#ifdef LDAP_OPT_X_TLS_CACERTFILE + /* set one or more certificates */ + /* FIXME: make it support setting directories as well as files */ + while (cert) { + /* OpenLDAP SDK supports BASE64 files. */ + switch (cert->type) { + case APR_LDAP_CA_TYPE_BASE64: { + result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_CACERTFILE, + (void *)cert->path); + result->msg = ldap_err2string(result->rc); + break; + } + case APR_LDAP_CERT_TYPE_BASE64: { + result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_CERTFILE, + (void *)cert->path); + result->msg = ldap_err2string(result->rc); + break; + } + case APR_LDAP_KEY_TYPE_BASE64: { + result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_KEYFILE, + (void *)cert->path); + result->msg = ldap_err2string(result->rc); + break; + } + default: { + result->rc = -1; + result->reason = "LDAP: The OpenLDAP SDK only understands the " + "PEM (BASE64) file type."; + } + } + if (LDAP_SUCCESS != result->rc) { + break; + } + cert = cert->next; + } +#else + result->reason = "LDAP: LDAP_OPT_X_TLS_CACERTFILE not " + "defined by this OpenLDAP SDK. Certificate " + "authority file not set"; + result->rc = -1; +#endif +#endif + + /* microsoft SDK */ +#if APR_HAS_MICROSOFT_LDAPSDK + /* Microsoft SDK use the registry certificate store - error out here + * with a message explaining this. + */ + result->reason = "LDAP: CA certificates cannot be set using this method, " + "as they are stored in the registry instead." + result->rc = -1; +#endif + + /* Sun SDK */ +#if APR_HAS_SOLARIS_LDAPSDK + result->reason = "LDAP: Attempt to set certificate store failed. " + "APR does not yet know how to set a certificate " + "store on the Sun toolkit"; + result->rc = -1; +#endif + + /* SDK not recognised */ +#if APR_HAS_OTHER_LDAPSDK + result->reason = "LDAP: LDAP_OPT_X_TLS_CACERTFILE not " + "defined by this LDAP SDK. Certificate " + "authority file not set"; + result->rc = -1; +#endif + +#else /* not compiled with SSL Support */ + result->reason = "LDAP: Attempt to set certificate(s) failed. " + "Not built with SSL support"; + result->rc = -1; +#endif /* APR_HAS_LDAP_SSL */ + + return result->rc; + +} + #endif /* APR_HAS_LDAP */