.\"Sets/gets the TLS mode.
.TP
.B LDAP_OPT_X_TLS_CACERTDIR
-Sets/gets the path of the directory containing CA certificates.
+Sets/gets the path of the directories containing CA certificates.
+Multiple directories may be specified, separated by a semi-colon.
.BR invalue
must be
.BR "const char *" ;
Authorities the client will recognize.
.TP
.B TLS_CACERTDIR <path>
-Specifies the path of a directory that contains Certificate Authority
-certificates in separate individual files. The
+Specifies the path of directories that contain Certificate Authority
+certificates in separate individual files. Multiple directories may
+be specified, separated by a semi-colon. The
.B TLS_CACERT
is always used before
.B TLS_CACERTDIR.
appended to the file; the order is not significant.
.TP
.B olcTLSCACertificatePath: <path>
-Specifies the path of a directory that contains Certificate Authority
+Specifies the path of directories that contain Certificate Authority
certificates in separate individual files. Usually only one of this
or the olcTLSCACertificateFile is defined. If both are specified, both
-locations will be used.
+locations will be used. Multiple directories may be specified,
+separated by a semi-colon.
.TP
.B olcTLSCertificateFile: <filename>
Specifies the file that contains the
appended to the file; the order is not significant.
.TP
.B TLSCACertificatePath <path>
-Specifies the path of a directory that contains Certificate Authority
+Specifies the path of directories that contain Certificate Authority
certificates in separate individual files. Usually only one of this
or the TLSCACertificateFile is used. If both are specified, both
-locations will be used.
+locations will be used. Multiple directories may be specified,
+separated by a semi-colon.
.TP
.B TLSCertificateFile <filename>
Specifies the file that contains the
struct tls_ctx;
struct tls_session;
+#define CERTPATHSEP ";"
+
typedef struct tls_ctx tls_ctx;
typedef struct tls_session tls_session;
}
if (lo->ldo_tls_cacertdir != NULL) {
- rc = gnutls_certificate_set_x509_trust_dir(
- ctx->cred,
- lt->lt_cacertdir,
- GNUTLS_X509_FMT_PEM );
- if ( rc > 0 ) {
- Debug2( LDAP_DEBUG_TRACE,
- "TLS: loaded %d CA certificates from directory `%s'.\n",
- rc, lt->lt_cacertdir );
- } else {
- Debug1( LDAP_DEBUG_ANY,
- "TLS: warning: no certificate found in CA certificate directory `%s'.\n",
- lt->lt_cacertdir );
- /* only warn, no return */
- strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
+ char **dirs = ldap_str2charray( lt->lt_cacertdir, CERTPATHSEP );
+ int i;
+ for ( i=0; dirs[i]; i++ ) {
+ rc = gnutls_certificate_set_x509_trust_dir(
+ ctx->cred,
+ dirs[i],
+ GNUTLS_X509_FMT_PEM );
+ if ( rc > 0 ) {
+ Debug2( LDAP_DEBUG_TRACE,
+ "TLS: loaded %d CA certificates from directory `%s'.\n",
+ rc, dirs[i] );
+ } else {
+ Debug1( LDAP_DEBUG_ANY,
+ "TLS: warning: no certificate found in CA certificate directory `%s'.\n",
+ dirs[i] );
+ /* only warn, no return */
+ strncpy( errmsg, gnutls_strerror( rc ), ERRBUFSIZE );
+ }
}
+ ldap_charray_free( dirs );
}
if (lo->ldo_tls_cacertfile != NULL) {
if ( bundle ) {
ca_list = SSL_load_client_CA_file( bundle );
}
-#if defined(HAVE_DIRENT_H) || defined(dirent)
if ( dir ) {
- int freeit = 0;
+ char **dirs = ldap_str2charray( dir, CERTPATHSEP );
+ int freeit = 0, i;
if ( !ca_list ) {
ca_list = sk_X509_NAME_new_null();
freeit = 1;
}
- if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) &&
- freeit ) {
- sk_X509_NAME_free( ca_list );
- ca_list = NULL;
+ for ( i=0; dirs[i]; i++ ) {
+ if ( !SSL_add_dir_cert_subjects_to_stack( ca_list, dir ) &&
+ freeit ) {
+ sk_X509_NAME_free( ca_list );
+ ca_list = NULL;
+ break;
+ }
}
+ ldap_charray_free( dirs );
}
-#endif
if ( cert ) {
X509_NAME *xn = X509_get_subject_name( cert );
xn = X509_NAME_dup( xn );
return -1;
}
}
- if (( lt->lt_cacertfile || lt->lt_cacertdir ) && !SSL_CTX_load_verify_locations( ctx,
- lt->lt_cacertfile, lt->lt_cacertdir ) )
- {
- Debug2( LDAP_DEBUG_ANY, "TLS: "
- "could not load verify locations (file:`%s',dir:`%s').\n",
- lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
- lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "" );
- tlso_report_error( errmsg );
- return -1;
+ if ( lt->lt_cacertfile || lt->lt_cacertdir ) {
+ char **dirs, *dummy = NULL;
+ if ( lt->lt_cacertdir ) {
+ dirs = ldap_str2charray( lt->lt_cacertdir, CERTPATHSEP );
+ } else {
+ dirs = &dummy;
+ }
+ /* Start with the first dir in path */
+ if ( !SSL_CTX_load_verify_locations( ctx,
+ lt->lt_cacertfile, dirs[0] ) )
+ {
+ Debug2( LDAP_DEBUG_ANY, "TLS: "
+ "could not load verify locations (file:`%s',dir:`%s').\n",
+ lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
+ dirs[0] ? dirs[0] : "" );
+ tlso_report_error( errmsg );
+ if ( dirs != &dummy )
+ ldap_charray_free( dirs );
+ return -1;
+ }
+ /* Then additional dirs, if any */
+ if ( dirs != &dummy ) {
+ if ( dirs[1] ) {
+ int i;
+ X509_STORE *store = SSL_CTX_get_cert_store( ctx );
+ X509_LOOKUP *lookup = X509_STORE_add_lookup( store, X509_LOOKUP_hash_dir() );
+ for ( i=1; dirs[i]; i++ )
+ X509_LOOKUP_add_dir( lookup, dirs[i], X509_FILETYPE_PEM );
+ }
+ ldap_charray_free( dirs );
+ }
}
if ( is_server ) {