ITS#6248 support multiple CAcert dirs

This commit is contained in:
Howard Chu 2021-07-22 21:07:21 +01:00
parent 92a8025f29
commit dfcaa3f01e
7 changed files with 73 additions and 37 deletions

View file

@ -642,7 +642,8 @@ The TLS options are OpenLDAP specific.
.\"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 *" ;

View file

@ -333,8 +333,9 @@ Specifies the file that contains certificates for all of the Certificate
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.

View file

@ -926,10 +926,11 @@ the top-level CA should be present. Multiple certificates are simply
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

View file

@ -1156,10 +1156,11 @@ the top-level CA should be present. Multiple certificates are simply
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

View file

@ -22,6 +22,8 @@ struct tls_impl;
struct tls_ctx;
struct tls_session;
#define CERTPATHSEP ";"
typedef struct tls_ctx tls_ctx;
typedef struct tls_session tls_session;

View file

@ -195,21 +195,26 @@ tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server, char *
}
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) {

View file

@ -170,21 +170,24 @@ tlso_ca_list( char * bundle, char * dir, X509 *cert )
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 );
@ -445,15 +448,37 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server, char *
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 ) {