]> git.sur5r.net Git - openldap/commitdiff
Add options to use DER format cert+keys directly
authorHoward Chu <hyc@openldap.org>
Sat, 8 Apr 2017 23:13:42 +0000 (00:13 +0100)
committerHoward Chu <hyc@openldap.org>
Sat, 8 Apr 2017 23:13:42 +0000 (00:13 +0100)
Instead of loading from files.

include/ldap.h
libraries/libldap/ldap-int.h
libraries/libldap/tls2.c
libraries/libldap/tls_o.c

index 4caacb15b3aa1a7152bb3fa08b483483f17ca625..588e9066dcbd708fc1a70357f047a89132427a2c 100644 (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
index db100c80588373d8f3583ead0d91b8711356e9f3..bcd6118b5f2afe810e7924f7fff604cb0ad4a792 100644 (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;
index d6b36bbd3609a852635d1f8d95793565467e5658..732826b2e0688cf95e5cd3b4b50ddea17a7745f4 100644 (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;
        }
index 795278d30d694052c4eb71f0ada97f073940a7a9..ce0663b66bc83a34788451d689a5220a8c558a03 100644 (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 ) )