View | Details | Raw Unified | Return to bug 52473
Collapse All | Expand All

(-)httpd.2.4.2/ssl_engine_config.c (-7 / +3 lines)
Lines 69-74 Link Here
69
    mc->tPublicCert            = apr_hash_make(pool);
69
    mc->tPublicCert            = apr_hash_make(pool);
70
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
70
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
71
    mc->szCryptoDevice         = NULL;
71
    mc->szCryptoDevice         = NULL;
72
    mc->engine                 = NULL;
72
#endif
73
#endif
73
#ifdef HAVE_OCSP_STAPLING
74
#ifdef HAVE_OCSP_STAPLING
74
    mc->stapling_cache         = NULL;
75
    mc->stapling_cache         = NULL;
Lines 468-476 Link Here
468
    if (strcEQ(arg, "builtin")) {
469
    if (strcEQ(arg, "builtin")) {
469
        mc->szCryptoDevice = NULL;
470
        mc->szCryptoDevice = NULL;
470
    }
471
    }
471
    else if ((e = ENGINE_by_id(arg))) {
472
    else if ((e = ssl_ossle_get_engine(cmd->server, arg, NULL, 0))) {
472
        mc->szCryptoDevice = arg;
473
        mc->szCryptoDevice = arg;
473
        ENGINE_free(e);
474
        ssl_ossle_release_engine(cmd->server);
474
    }
475
    }
475
    else {
476
    else {
476
        err = "SSLCryptoDevice: Invalid argument; must be one of: "
477
        err = "SSLCryptoDevice: Invalid argument; must be one of: "
Lines 718-728 Link Here
718
    SSLSrvConfigRec *sc = mySrvConfig(parms->server);
719
    SSLSrvConfigRec *sc = mySrvConfig(parms->server);
719
    const char *err, *desc=NULL, **files=NULL;
720
    const char *err, *desc=NULL, **files=NULL;
720
    int i;
721
    int i;
721
722
    if ((err = ssl_cmd_check_file(parms, &arg))) {
723
        return err;
724
    }
725
726
    switch (idx) {
722
    switch (idx) {
727
      case SSL_AIDX_CERTS:
723
      case SSL_AIDX_CERTS:
728
        desc = "certificates";
724
        desc = "certificates";
(-)httpd.2.4.2/ssl_engine_init.c (-9 / +151 lines)
Lines 56-61 Link Here
56
                 modver, AP_SERVER_BASEVERSION, incver);
56
                 modver, AP_SERVER_BASEVERSION, incver);
57
}
57
}
58
58
59
/* _________________________________________________________________
60
**
61
**  Centralized engine loading & configuration
62
**  _________________________________________________________________
63
*/
64
65
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
66
void ssl_ossle_release_engine(server_rec *s)
67
{
68
    SSLModConfigRec *mc = myModConfig(s);
69
    if (!mc->engine) {
70
        return;
71
	}
72
73
    /* unload any dynamic engines pulled in by CONF_modules_load_file,
74
     * but don't unload the built in engines */
75
    CONF_modules_unload(0);
76
77
    /* Releases all the references retained via ssl_ossl_get_engine */
78
    ENGINE_finish(mc->engine);
79
80
    mc->engine = 0;
81
}
82
83
ENGINE * ssl_ossle_get_engine(server_rec *s, const char *enginename,
84
                              const char *opensslcnf, int disablecnf)
85
{
86
    SSLModConfigRec *mc = myModConfig(s);
87
    ENGINE *e = 0;
88
    int conf_modules = 0;
89
    int funct_ref = 0;
90
91
    if (mc->engine) {
92
        return mc->engine;
93
    }
94
95
    /* CONF_modules_load_file allows for the declaration of engine names, and
96
     * associated parameters, in an openssl formated configuration file.
97
     * opensslcnf may be NULL, in which case openssl's default cofniguration
98
     * file is used automaticaly. (Eg, "/etc/ssl/openssl.cnf").
99
     *
100
     * To completely disable openssl config processing pass NULL for
101
     * `opensslcnf' and set `disablecnf' to any non zero value. */
102
103
    if (!disablecnf && CONF_modules_load_file(opensslcnf, 0, 0) <= 0) {
104
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
105
                     "Init: Failed to load openssl config file `%s'",
106
					 opensslcnf);
107
        ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
108
        goto x_fail;
109
    }
110
    if (!disablecnf) {
111
        conf_modules = 1;
112
    }
113
114
    /* side effect: aquires an additional `structure ref' */
115
    e = ENGINE_by_id(enginename);
116
    if (!e) {
117
        goto x_fail;
118
	}
119
120
    ENGINE_free(e); /* drop the struct_ref taken out by ENGINE_by_id */
121
122
    /* Take out a functional reference, all user configuration is handled in
123
     * openssl.cnf and is now complete, so ENGINE_init can succede if the
124
     * chosen engine has been configured appropriately. */
125
    if (!(funct_ref = ENGINE_init(e))) {
126
        goto x_fail;
127
    }
128
129
    /* Remove our engine from openssl's internal list and drop the associated
130
     * reference.  This means ENGINE_by_id will no longer succede and hence
131
     * can't cause further reference counting hell. */
132
    if (!ENGINE_remove(e)) {
133
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
134
                     "Init: Failed to apply engine configuration `%s' `%s'",
135
                     enginename, opensslcnf
136
            );
137
        ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
138
        goto x_fail;
139
    }
140
141
    mc->engine = e;
142
    return mc->engine;
143
144
x_fail:
145
    if (e) {
146
       if (funct_ref) {
147
            ENGINE_finish(e);
148
	   }
149
    }
150
    if (conf_modules) {
151
        /* unload any dynamic engines pulled in by CONF_modules_load_file,
152
         * but don't unload the built in engines. */
153
        CONF_modules_unload(0);
154
    }
155
156
    return NULL;
157
158
}
159
160
/* ssl_ossle_load_cert_engine_pkcs11
161
 *
162
 * This is specific to the engine_pkcs11 wrapper provided by the opensc
163
 * project. more general support *is* possible but lets get some feed back
164
 * before writing a tone of code.
165
 */
166
X509* ssl_ossle_load_cert_engine_pkcs11(server_rec *s, const char *identifier)
167
{
168
    int cmdno;
169
    struct {
170
        const char *identifier;
171
        void *cert;
172
    } param = {identifier, 0};
173
174
    SSLModConfigRec *mc = myModConfig(s);
175
    if (!mc->engine) {
176
        return NULL;
177
    }
178
179
    cmdno = ENGINE_ctrl(mc->engine,
180
                        ENGINE_CTRL_GET_CMD_FROM_NAME, -1, "LOAD_CERT_CTRL", 0);
181
    /* XXX: check the value of cmdno */
182
    ENGINE_ctrl(mc->engine, cmdno, -1, &param, 0);
183
184
    return (X509 *)param.cert;
185
}
186
#endif
59
187
60
/*
188
/*
61
 * Handle the Temporary RSA Keys and DH Params
189
 * Handle the Temporary RSA Keys and DH Params
Lines 433-439 Link Here
433
    ENGINE *e;
561
    ENGINE *e;
434
562
435
    if (mc->szCryptoDevice) {
563
    if (mc->szCryptoDevice) {
436
        if (!(e = ENGINE_by_id(mc->szCryptoDevice))) {
564
        if (!(e = ssl_ossle_get_engine(s, mc->szCryptoDevice, NULL, 0))) {
437
            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01888)
565
            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01888)
438
                         "Init: Failed to load Crypto Device API `%s'",
566
                         "Init: Failed to load Crypto Device API `%s'",
439
                         mc->szCryptoDevice);
567
                         mc->szCryptoDevice);
Lines 455-462 Link Here
455
        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01890)
583
        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01890)
456
                     "Init: loaded Crypto Device API `%s'",
584
                     "Init: loaded Crypto Device API `%s'",
457
                     mc->szCryptoDevice);
585
                     mc->szCryptoDevice);
458
459
        ENGINE_free(e);
460
    }
586
    }
461
}
587
}
462
#endif
588
#endif
Lines 1024-1035 Link Here
1024
                 "Configuring %s server private key", type);
1150
                 "Configuring %s server private key", type);
1025
1151
1026
    ptr = asn1->cpData;
1152
    ptr = asn1->cpData;
1027
    if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData)))
1153
1028
    {
1154
    if (!mc->engine) {
1029
        ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02237)
1155
        if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData))) {
1030
                "Unable to import %s server private key", type);
1156
            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02237)
1031
        ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
1157
                         "Unable to import %s server private key", type);
1032
        ssl_die();
1158
            ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
1159
            ssl_die();
1160
        }
1161
    }
1162
    else {
1163
        /* cpData is a null terminated character string */
1164
        if (!(pkey = ENGINE_load_private_key(mc->engine, (char*)asn1->cpData,
1165
		                                     0 /*ui_method*/, 0 /*cbdata*/))) {
1166
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
1167
                         "Unable to import (ENGINE) %s server private key",
1168
						 type);
1169
            ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
1170
            ssl_die();
1171
        }
1033
    }
1172
    }
1034
1173
1035
    if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) {
1174
    if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) {
Lines 1057-1062 Link Here
1057
1196
1058
    mctx->pks->keys[idx] = pkey;
1197
    mctx->pks->keys[idx] = pkey;
1059
1198
1199
    /* Release the engine if there is one. */
1200
    ssl_ossle_release_engine(s);
1201
1060
    return TRUE;
1202
    return TRUE;
1061
}
1203
}
1062
1204
(-)httpd.2.4.2/ssl_engine_pphrase.c (-22 / +86 lines)
Lines 220-232 Link Here
220
            } else {
220
            } else {
221
                apr_cpystrn(szPath, sc->server->pks->cert_files[i],
221
                apr_cpystrn(szPath, sc->server->pks->cert_files[i],
222
                            sizeof(szPath));
222
                            sizeof(szPath));
223
                if ((rv = exists_and_readable(szPath, p, NULL))
223
                if (!mc->engine) {
224
                    != APR_SUCCESS) {
224
                    if ((rv = exists_and_readable(szPath, p, NULL))
225
                          != APR_SUCCESS) {
225
                    ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02201)
226
                    ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02201)
226
                                 "Init: Can't open server certificate file %s",
227
                                 "Init: Can't open server certificate file %s",
227
                                 szPath);
228
                                 szPath);
228
                    ssl_die();
229
                    ssl_die();
229
                }
230
                   }
230
                if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) {
231
                if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) {
231
                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02241)
232
                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02241)
232
                                 "Init: Unable to read server certificate from"
233
                                 "Init: Unable to read server certificate from"
Lines 237-243 Link Here
237
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02202)
238
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02202)
238
                             "Init: Read server certificate from '%s'",
239
                             "Init: Read server certificate from '%s'",
239
                             szPath);
240
                             szPath);
240
            }
241
                }
242
                else { 
243
		    /* For backwards compat, and convenience for engine
244
                    * implementors, we should probably have a configurable
245
                    * means to say: "for these named engines, use apaches
246
                    * existing pem file support to load server keys and
247
                    * certificates", this patch treats all engines the same
248
                    * TODO:
249
                    *  1. explicit support for passing UI callbacks and
250
                    * data necessary for hardware that needs password entry,
251
                    * or other interactions, in order to load keys. It's a can
252
                    * of worms so I'm leaving it out for now.
253
                    * 2. Add at least "SSLCryptoDeviceLoadCertCmd" in order to
254
                    * enable a more general purpose implementation of engine
255
                    * based certificate loading. */
256
                    pX509Cert = ssl_ossle_load_cert_engine_pkcs11(s, szPath);
257
                    if (!pX509Cert) {
258
                        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
259
                                     "Init: Unable to server certificate `%s' using "
260
								 "engine `%s'", szPath, mc->szCryptoDevice);
261
                        ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
262
                        ssl_die();
263
                    }
264
                }
265
             }
266
           
241
            /*
267
            /*
242
             * check algorithm type of certificate and make
268
             * check algorithm type of certificate and make
243
             * sure only one certificate per type is used.
269
             * sure only one certificate per type is used.
Lines 323-329 Link Here
323
                 * the callback function which serves the pass
349
                 * the callback function which serves the pass
324
                 * phrases to OpenSSL
350
                 * phrases to OpenSSL
325
                 */
351
                 */
326
                if ((rv = exists_and_readable(szPath, p,
352
                if (!mc->engine && (rv = exists_and_readable(szPath, p,
327
                                              &pkey_mtime)) != APR_SUCCESS ) {
353
                                              &pkey_mtime)) != APR_SUCCESS ) {
328
                     ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02243)
354
                     ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02243)
329
                                  "Init: Can't open server private key file "
355
                                  "Init: Can't open server private key file "
Lines 373-381 Link Here
373
                 * functions will fail spuriously if the error stack
399
                 * functions will fail spuriously if the error stack
374
                 * is not empty. */
400
                 * is not empty. */
375
                ERR_clear_error();
401
                ERR_clear_error();
376
402
	
377
                bReadable = ((pPrivateKey = SSL_read_PrivateKey(szPath, NULL,
403
		if (!mc->engine) {
378
                            ssl_pphrase_Handle_CB, s)) != NULL ? TRUE : FALSE);
404
                    bReadable = ((pPrivateKey = SSL_read_PrivateKey(szPath,
405
                                  NULL, ssl_pphrase_Handle_CB, s))
406
                                  != NULL ? TRUE : FALSE);
407
                }
408
                else {
409
                    pPrivateKey = ENGINE_load_private_key(mc->engine, szPath,
410
                                                          UI_OpenSSL() 
411
														  /*ui_method*/,
412
														  0 /*cbdata*/); 
413
                    bReadable = pPrivateKey != NULL ? TRUE : FALSE;
414
                }
379
415
380
                /*
416
                /*
381
                 * when the private key file now was readable,
417
                 * when the private key file now was readable,
Lines 474-485 Link Here
474
                continue;
510
                continue;
475
511
476
            if (pPrivateKey == NULL) {
512
            if (pPrivateKey == NULL) {
477
                ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02247)
513
                if (!mc->engine) { 
478
                            "Init: Unable to read server private key from "
514
                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02247)
479
                            "file %s [Hint: Perhaps it is in a separate file? "
515
                                "Init: Unable to read server private key from "
480
                            "  See SSLCertificateKeyFile]", szPath);
516
                                "file %s [Hint: Perhaps it is in a separate file? "
481
                ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
517
                                "  See SSLCertificateKeyFile]", szPath);
482
                ssl_die();
518
                    ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
519
                    ssl_die();
520
                }
521
                else {
522
                    /* log the error with clear indication that engine format
523
                     * keys are in play. */
524
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
525
                                "Init: Unable to load server private key "
526
                                "using the identifier `%s' and engine `%s'",
527
                                szPath, mc->szCryptoDevice);
528
                    ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
529
                }
483
            }
530
            }
484
531
485
            /*
532
            /*
Lines 535-548 Link Here
535
             * because the SSL library uses static variables inside a
582
             * because the SSL library uses static variables inside a
536
             * RSA structure which do not survive DSO reloads!)
583
             * RSA structure which do not survive DSO reloads!)
537
             */
584
             */
538
            length = i2d_PrivateKey(pPrivateKey, NULL);
585
            if (!mc->engine){ 
539
            ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length);
586
                length = i2d_PrivateKey(pPrivateKey, NULL);
540
            (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
587
                ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length);
541
588
                (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
542
            if (nPassPhraseDialogCur != 0) {
589
543
                /* remember mtime of encrypted keys */
590
                if (nPassPhraseDialogCur != 0) {
544
                asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id);
591
                    /* remember mtime of encrypted keys */
545
                asn1->source_mtime = pkey_mtime;
592
                    asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id);
593
                    asn1->source_mtime = pkey_mtime;
594
                }
595
            }
596
            else {
597
                /* the asn1 trick does not play well with hardware hosted
598
                keys. */
599
                length = strlen(szPath) + 1;
600
                /* cpData is the key_id */
601
                ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length);
602
                memcpy(ucp, szPath, length);
603
                /* un-necessary, given we will reload, but retained for
604
                * consistency. */
605
                if (nPassPhraseDialogCur != 0) {
606
                    /* remember mtime of encrypted keys */
607
                    asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id);
608
                    asn1->source_mtime = pkey_mtime;
609
                }
546
            }
610
            }
547
611
548
            /*
612
            /*
(-)httpd.2.4.2/ssl_private.h (+7 lines)
Lines 529-534 Link Here
529
529
530
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
530
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
531
    const char     *szCryptoDevice;
531
    const char     *szCryptoDevice;
532
    ENGINE         *engine;
532
#endif
533
#endif
533
534
534
#ifdef HAVE_OCSP_STAPLING
535
#ifdef HAVE_OCSP_STAPLING
Lines 774-779 Link Here
774
void         ssl_init_Child(apr_pool_t *, server_rec *);
775
void         ssl_init_Child(apr_pool_t *, server_rec *);
775
apr_status_t ssl_init_ModuleKill(void *data);
776
apr_status_t ssl_init_ModuleKill(void *data);
776
777
778
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
779
void         ssl_ossle_release_engine(server_rec *s);
780
ENGINE      *ssl_ossle_get_engine(server_rec *s, const char *enginename, const char *opensslcnf, int disablecnf);
781
X509        *ssl_ossle_load_cert_engine_pkcs11(server_rec *s, const char *identifier);
782
#endif
783
777
/**  Apache API hooks  */
784
/**  Apache API hooks  */
778
int          ssl_hook_Auth(request_rec *);
785
int          ssl_hook_Auth(request_rec *);
779
int          ssl_hook_UserCheck(request_rec *);
786
int          ssl_hook_UserCheck(request_rec *);

Return to bug 52473