Add options to use DER format cert+keys directly

Instead of loading from files.
This commit is contained in:
Howard Chu 2017-04-09 00:13:42 +01:00
parent 2b920ecaec
commit b402a2805f
4 changed files with 93 additions and 6 deletions

View file

@ -162,6 +162,9 @@ LDAP_BEGIN_DECL
#define LDAP_OPT_X_TLS_VERSION 0x6013 /* read-only */
#define LDAP_OPT_X_TLS_CIPHER 0x6014 /* read-only */
#define LDAP_OPT_X_TLS_PEERCERT 0x6015 /* read-only */
#define LDAP_OPT_X_TLS_CACERT 0x6016
#define LDAP_OPT_X_TLS_CERT 0x6017
#define LDAP_OPT_X_TLS_KEY 0x6018
#define LDAP_OPT_X_TLS_NEVER 0
#define LDAP_OPT_X_TLS_HARD 1

View file

@ -167,6 +167,9 @@ struct ldaptls {
char *lt_randfile; /* OpenSSL only */
char *lt_ecname; /* OpenSSL only */
int lt_protocol_min;
struct berval lt_cacert;
struct berval lt_cert;
struct berval lt_key;
};
#endif
@ -258,6 +261,9 @@ struct ldapoptions {
#define ldo_tls_protocol_min ldo_tls_info.lt_protocol_min
#define ldo_tls_crlfile ldo_tls_info.lt_crlfile
#define ldo_tls_randfile ldo_tls_info.lt_randfile
#define ldo_tls_cacert ldo_tls_info.lt_cacert
#define ldo_tls_cert ldo_tls_info.lt_cert
#define ldo_tls_key ldo_tls_info.lt_key
int ldo_tls_mode;
int ldo_tls_require_cert;
int ldo_tls_impl;

View file

@ -199,7 +199,9 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
tls_init( ti );
if ( is_server && !lts.lt_certfile && !lts.lt_keyfile &&
!lts.lt_cacertfile && !lts.lt_cacertdir ) {
!lts.lt_cacertfile && !lts.lt_cacertdir &&
!lts.lt_cacert.bv_val && !lts.lt_cert.bv_val &&
!lts.lt_key.bv_val ) {
/* minimum configuration not provided */
return LDAP_NOT_SUPPORTED;
}
@ -864,6 +866,36 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx );
lo->ldo_tls_ctx = NULL;
return ldap_int_tls_init_ctx( lo, *(int *)arg );
case LDAP_OPT_X_TLS_CACERT:
if ( !arg ) return -1;
if ( lo->ldo_tls_cacert.bv_val )
LDAP_FREE( lo->ldo_tls_cacert.bv_val );
lo->ldo_tls_cacert.bv_len = ((struct berval *)arg)->bv_len;
lo->ldo_tls_cacert.bv_val = LDAP_MALLOC( lo->ldo_tls_cacert.bv_len );
if ( !lo->ldo_tls_cacert.bv_val )
return -1;
AC_MEMCPY( lo->ldo_tls_cacert.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_cacert.bv_len );
break;
case LDAP_OPT_X_TLS_CERT:
if ( !arg ) return -1;
if ( lo->ldo_tls_cert.bv_val )
LDAP_FREE( lo->ldo_tls_cert.bv_val );
lo->ldo_tls_cert.bv_len = ((struct berval *)arg)->bv_len;
lo->ldo_tls_cert.bv_val = LDAP_MALLOC( lo->ldo_tls_cert.bv_len );
if ( !lo->ldo_tls_cert.bv_val )
return -1;
AC_MEMCPY( lo->ldo_tls_cert.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_cert.bv_len );
break;
case LDAP_OPT_X_TLS_KEY:
if ( !arg ) return -1;
if ( lo->ldo_tls_key.bv_val )
LDAP_FREE( lo->ldo_tls_key.bv_val );
lo->ldo_tls_key.bv_len = ((struct berval *)arg)->bv_len;
lo->ldo_tls_key.bv_val = LDAP_MALLOC( lo->ldo_tls_key.bv_len );
if ( !lo->ldo_tls_key.bv_val )
return -1;
AC_MEMCPY( lo->ldo_tls_key.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_key.bv_len );
break;
default:
return -1;
}

View file

@ -114,7 +114,7 @@ static void tlso_thr_init( void ) {}
#endif /* OpenSSL 1.1 */
static STACK_OF(X509_NAME) *
tlso_ca_list( char * bundle, char * dir )
tlso_ca_list( char * bundle, char * dir, X509 *cert )
{
STACK_OF(X509_NAME) *ca_list = NULL;
@ -136,6 +136,12 @@ tlso_ca_list( char * bundle, char * dir )
}
}
#endif
if ( cert ) {
X509_NAME *xn = X509_get_subject_name( cert );
xn = X509_NAME_dup( xn );
if ( xn )
sk_X509_NAME_push( ca_list, xn );
}
return ca_list;
}
@ -266,7 +272,8 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
return -1;
}
if ( lo->ldo_tls_cacertfile == NULL && lo->ldo_tls_cacertdir == NULL ) {
if ( lo->ldo_tls_cacertfile == NULL && lo->ldo_tls_cacertdir == NULL &&
lo->ldo_tls_cacert.bv_val == NULL ) {
if ( !SSL_CTX_set_default_verify_paths( ctx ) ) {
Debug( LDAP_DEBUG_ANY, "TLS: "
"could not use default certificate paths", 0, 0, 0 );
@ -274,7 +281,19 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
return -1;
}
} else {
if ( !SSL_CTX_load_verify_locations( ctx,
X509 *cert = NULL;
if ( lo->ldo_tls_cacert.bv_val ) {
const unsigned char *pp = lo->ldo_tls_cacert.bv_val;
cert = d2i_X509( NULL, &pp, lo->ldo_tls_cacert.bv_len );
X509_STORE *store = SSL_CTX_get_cert_store( ctx );
if ( !X509_STORE_add_cert( store, cert )) {
Debug( LDAP_DEBUG_ANY, "TLS: "
"could not use CA certificate", 0, 0, 0 );
tlso_report_error();
return -1;
}
}
if (( lt->lt_cacertfile || lt->lt_cacertdir ) && !SSL_CTX_load_verify_locations( ctx,
lt->lt_cacertfile, lt->lt_cacertdir ) )
{
Debug( LDAP_DEBUG_ANY, "TLS: "
@ -289,7 +308,7 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
if ( is_server ) {
STACK_OF(X509_NAME) *calist;
/* List of CA names to send to a client */
calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir );
calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir, cert );
if ( !calist ) {
Debug( LDAP_DEBUG_ANY, "TLS: "
"could not load client CA list (file:`%s',dir:`%s').\n",
@ -302,20 +321,47 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
SSL_CTX_set_client_CA_list( ctx, calist );
}
if ( cert )
X509_free( cert );
}
if ( lo->ldo_tls_cert.bv_val )
{
const unsigned char *pp = lo->ldo_tls_cert.bv_val;
X509 *cert = d2i_X509( NULL, &pp, lo->ldo_tls_cert.bv_len );
if ( !SSL_CTX_use_certificate( ctx, cert )) {
Debug( LDAP_DEBUG_ANY,
"TLS: could not use certificate.\n", 0,0,0);
tlso_report_error();
return -1;
}
X509_free( cert );
} else
if ( lo->ldo_tls_certfile &&
!SSL_CTX_use_certificate_file( ctx,
lt->lt_certfile, SSL_FILETYPE_PEM ) )
{
Debug( LDAP_DEBUG_ANY,
"TLS: could not use certificate `%s'.\n",
"TLS: could not use certificate file `%s'.\n",
lo->ldo_tls_certfile,0,0);
tlso_report_error();
return -1;
}
/* Key validity is checked automatically if cert has already been set */
if ( lo->ldo_tls_key.bv_val )
{
const unsigned char *pp = lo->ldo_tls_key.bv_val;
EVP_PKEY *pkey = d2i_AutoPrivateKey( NULL, &pp, lo->ldo_tls_key.bv_len );
if ( !SSL_CTX_use_PrivateKey( ctx, pkey ))
{
Debug( LDAP_DEBUG_ANY,
"TLS: could not use private key.\n", 0,0,0);
tlso_report_error();
return -1;
}
EVP_PKEY_free( pkey );
} else
if ( lo->ldo_tls_keyfile &&
!SSL_CTX_use_PrivateKey_file( ctx,
lt->lt_keyfile, SSL_FILETYPE_PEM ) )