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

(-)httpd-trunk/modules/ssl/ssl_private.h (+6 lines)
Lines 384-389 Link Here
384
    apr_hash_t     *tPrivateKey;
384
    apr_hash_t     *tPrivateKey;
385
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
385
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
386
    const char     *szCryptoDevice;
386
    const char     *szCryptoDevice;
387
    ENGINE         *engine;
387
#endif
388
#endif
388
    struct {
389
    struct {
389
        void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10;
390
        void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10;
Lines 550-555 Link Here
550
            *ssl_init_FindCAList(server_rec *, apr_pool_t *, const char *, const char *);
551
            *ssl_init_FindCAList(server_rec *, apr_pool_t *, const char *, const char *);
551
void         ssl_init_Child(apr_pool_t *, server_rec *);
552
void         ssl_init_Child(apr_pool_t *, server_rec *);
552
apr_status_t ssl_init_ModuleKill(void *data);
553
apr_status_t ssl_init_ModuleKill(void *data);
554
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
555
void         ssl_ossle_release_engine(server_rec *s);
556
ENGINE      *ssl_ossle_get_engine(server_rec *s, const char* enginename, const char* opensslcnf, int disablecnf);
557
X509* ssl_ossle_load_cert_engine_pkcs11(server_rec *s, const char *identifier);
558
#endif
553
559
554
/**  Apache API hooks  */
560
/**  Apache API hooks  */
555
int          ssl_hook_Auth(request_rec *);
561
int          ssl_hook_Auth(request_rec *);
(-)httpd-trunk/modules/ssl/ssl_engine_init.c (-75 / +299 lines)
Lines 35-40 Link Here
35
*/
35
*/
36
36
37
37
38
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
39
static void ssl_ossle_child_init(apr_pool_t *p, server_rec *base_server);
40
#endif
41
38
static void ssl_add_version_components(apr_pool_t *p,
42
static void ssl_add_version_components(apr_pool_t *p,
39
                                       server_rec *s)
43
                                       server_rec *s)
40
{
44
{
Lines 51-57 Link Here
51
                 modver, AP_SERVER_BASEVERSION, incver);
55
                 modver, AP_SERVER_BASEVERSION, incver);
52
}
56
}
53
57
58
/*
59
 * centralized engine loading & configuration
60
 */
61
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
62
void ssl_ossle_release_engine(server_rec *s)
63
{
64
    SSLModConfigRec *mc = myModConfig(s);
65
    if (!mc->engine)
66
        return;
54
67
68
    /* unload any dynamic engines pulled in by CONF_modules_load_file,
69
     * but don't unload the built in engines */
70
    CONF_modules_unload(0);
71
72
    /* Releases all the references retained via ssl_ossl_get_engine */
73
    ENGINE_finish(mc->engine);
74
75
    mc->engine = 0;
76
}
77
78
ENGINE * ssl_ossle_get_engine(
79
    server_rec *s,
80
    const char* enginename,
81
    const char* opensslcnf,
82
    int disablecnf)
83
{
84
    SSLModConfigRec *mc = myModConfig(s);
85
    ENGINE *e = 0;
86
    int conf_modules = 0;
87
    int funct_ref = 0;
88
89
    if (mc->engine) {
90
        return mc->engine;
91
    }
92
93
    /* CONF_modules_load_file allows for the declaration of engine names, and
94
     * associated parameters, in an openssl formated configuration file.
95
     * opensslcnf may be NULL, in which case openssl's default cofniguration
96
     * file is used automaticaly. (Eg, "/etc/ssl/openssl.cnf").
97
     *
98
     * To completely disable openssl config processing pass NULL for
99
     * `opensslcnf' and set `disablecnf' to any non zero value. */
100
101
    if (!disablecnf && CONF_modules_load_file(opensslcnf, 0, 0) <= 0)
102
    {
103
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
104
            "Init: Failed to load openssl config file `%s'",
105
            opensslcnf
106
            );
107
        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
108
        goto x_fail;
109
    }
110
    if (!disablecnf)
111
        conf_modules = 1;
112
113
    /* side effect: aquires an additional `structure ref' */
114
    e = ENGINE_by_id(enginename);
115
    if (!e)
116
        goto x_fail;
117
    ENGINE_free(e); /* drop the struct_ref taken out by ENGINE_by_id */
118
119
    /* Take out a functional reference, all user configuration is handled in
120
     * openssl.cnf and is now complete, so ENGINE_init can succede if the
121
     * chosen engine has been configured appropriately. */
122
    if (!(funct_ref = ENGINE_init(e)))
123
        goto x_fail;
124
125
    /* Remove our engine from openssl's internal list and drop the associated
126
     * reference.  This means ENGINE_by_id will no longer succede and hence
127
     * can't cause further reference counting hell. */
128
    if (!ENGINE_remove(e)) {
129
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
130
            "Init: Failed to apply engine configuration `%s' `%s'",
131
            enginename, opensslcnf
132
            );
133
        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
134
        goto x_fail;
135
    }
136
137
    mc->engine = e;
138
139
    return mc->engine;
140
141
x_fail:
142
    if (e) {
143
        if (funct_ref)
144
            ENGINE_finish(e);
145
    }
146
    if (conf_modules) {
147
        /* unload any dynamic engines pulled in by CONF_modules_load_file,
148
         * but don't unload the built in engines. */
149
        CONF_modules_unload(0);
150
    }
151
152
    return NULL;
153
}
154
155
/* ssl_ossle_load_cert_engine_pkcs11
156
 *
157
 * This is specific to the engine_pkcs11 wrapper provided by the opensc
158
 * project. more general support *is* possible but lets get some feed back
159
 * before writing a tone of code.
160
 */
161
X509* ssl_ossle_load_cert_engine_pkcs11(server_rec *s, const char *identifier)
162
{
163
    int cmdno;
164
    struct {
165
        const char *identifier;
166
        void *cert;
167
    } param = {identifier, 0};
168
169
    SSLModConfigRec *mc = myModConfig(s);
170
    if (!mc->engine)
171
        return NULL;
172
173
    cmdno = ENGINE_ctrl(mc->engine,
174
            ENGINE_CTRL_GET_CMD_FROM_NAME, -1, "LOAD_CERT_CTRL", 0);
175
    /* XXX: check the value of cmdno */
176
    ENGINE_ctrl(mc->engine, cmdno, -1, &param, 0);
177
178
    return (X509*)param.cert;
179
}
180
#endif
181
55
/*
182
/*
56
 * Handle the Temporary RSA Keys and DH Params
183
 * Handle the Temporary RSA Keys and DH Params
57
 */
184
 */
Lines 210-249 Link Here
210
337
211
    }
338
    }
212
339
340
    /* XXX: This part of the engine_managed_keys patch is *very* much
341
     * in need of an additional config directive. Not all engine
342
     * implementations are sensitive to the process context issues
343
     * described in "Applications and processes" at p17 v2.20 6.6.1
344
     * of the PKCS #11 standard.
345
     *
346
     * In the interests of distilling the patch to its essentials whilst
347
     * clearly highlighting the issues I have simply deleted the
348
     * initialisation steps that have been moved to ssl_init_Child. The
349
     * negative diffs in this function are those things that should be gated
350
     * on SSLPKCS11ProcessModel or some equivalent. BUT NOTE that
351
     * ssl_mutex_init has *not* been removed. It now comes just after
352
     * ssl_util_thread_setup.
353
     *
354
     * The calls that have been moved are (in order):
355
     *  ssl_init_Engine
356
     *  ssl_rand_seed
357
     *  ssl_pphrase_Handle
358
     *  ssl_tmp_keys_init
359
     *  ssl_init_ConfigureServer (The whole "initialize servers" loop)
360
     */
361
213
#if APR_HAS_THREADS
362
#if APR_HAS_THREADS
214
    ssl_util_thread_setup(p);
363
    ssl_util_thread_setup(p);
215
#endif
364
#endif
216
365
217
    /*
366
    /*
218
     * SSL external crypto device ("engine") support
219
     */
220
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
221
    ssl_init_Engine(base_server, p);
222
#endif
223
224
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
225
                 "Init: Initialized %s library", SSL_LIBRARY_NAME);
226
227
    /*
228
     * Seed the Pseudo Random Number Generator (PRNG)
229
     * only need ptemp here; nothing inside allocated from the pool
230
     * needs to live once we return from ssl_rand_seed().
231
     */
232
    ssl_rand_seed(base_server, ptemp, SSL_RSCTX_STARTUP, "Init: ");
233
234
    /*
235
     * read server private keys/public certs into memory.
236
     * decrypting any encrypted keys via configured SSLPassPhraseDialogs
237
     * anything that needs to live longer than ptemp needs to also survive
238
     * restarts, in which case they'll live inside s->process->pool.
239
     */
240
    ssl_pphrase_Handle(base_server, ptemp);
241
242
    if (ssl_tmp_keys_init(base_server)) {
243
        return !OK;
244
    }
245
246
    /*
247
     * initialize the mutex handling
367
     * initialize the mutex handling
248
     */
368
     */
249
    if (!ssl_mutex_init(base_server, p)) {
369
    if (!ssl_mutex_init(base_server, p)) {
Lines 256-281 Link Here
256
    ssl_scache_init(base_server, p);
376
    ssl_scache_init(base_server, p);
257
377
258
    /*
378
    /*
259
     *  initialize servers
260
     */
261
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server,
262
                 "Init: Initializing (virtual) servers for SSL");
263
264
    for (s = base_server; s; s = s->next) {
265
        sc = mySrvConfig(s);
266
        /*
267
         * Either now skip this server when SSL is disabled for
268
         * it or give out some information about what we're
269
         * configuring.
270
         */
271
272
        /*
273
         * Read the server certificate and key
274
         */
275
        ssl_init_ConfigureServer(s, p, ptemp, sc);
276
    }
277
278
    /*
279
     * Configuration consistency checks
379
     * Configuration consistency checks
280
     */
380
     */
281
    ssl_init_CheckServers(base_server, ptemp);
381
    ssl_init_CheckServers(base_server, ptemp);
Lines 286-291 Link Here
286
     */
386
     */
287
    ssl_add_version_components(p, base_server);
387
    ssl_add_version_components(p, base_server);
288
388
389
390
    /* WRT engine_managed_keys: I'm not certain what to do about this
391
     * particular piece of openssl nastiness. Ignoring it seems to works in
392
     * my case. Thoughts anyone ?
393
     */
289
    SSL_init_app_data2_idx(); /* for SSL_get_app_data2() at request time */
394
    SSL_init_app_data2_idx(); /* for SSL_get_app_data2() at request time */
290
395
291
    return OK;
396
    return OK;
Lines 302-308 Link Here
302
    ENGINE *e;
407
    ENGINE *e;
303
408
304
    if (mc->szCryptoDevice) {
409
    if (mc->szCryptoDevice) {
305
        if (!(e = ENGINE_by_id(mc->szCryptoDevice))) {
410
        if (!(e = ssl_ossle_get_engine(s, mc->szCryptoDevice, NULL, 0))) {
306
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
411
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
307
                         "Init: Failed to load Crypto Device API `%s'",
412
                         "Init: Failed to load Crypto Device API `%s'",
308
                         mc->szCryptoDevice);
413
                         mc->szCryptoDevice);
Lines 321-328 Link Here
321
            ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
426
            ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
322
            ssl_die();
427
            ssl_die();
323
        }
428
        }
324
325
        ENGINE_free(e);
326
    }
429
    }
327
}
430
}
328
#endif
431
#endif
Lines 772-784 Link Here
772
                 "Configuring %s server private key", type);
875
                 "Configuring %s server private key", type);
773
876
774
    ptr = asn1->cpData;
877
    ptr = asn1->cpData;
775
    if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData)))
878
    if (!mc->engine) {
776
    {
879
        if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData)))
777
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
880
        {
778
                "Unable to import %s server private key", type);
881
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
779
        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
882
                    "Unable to import %s server private key", type);
780
        ssl_die();
883
            ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
884
            ssl_die();
885
        }
781
    }
886
    }
887
    else {
888
        /* cpData is a null terminated character string */
889
        if(!(pkey = ENGINE_load_private_key(
890
            mc->engine, (char*)asn1->cpData, 0 /*ui_method*/, 0 /*cbdata*/))) {
891
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
892
                    "Unable to import (ENGINE) %s server private key", type);
893
            ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
894
            ssl_die();
895
        }
896
    }
782
897
783
    if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) {
898
    if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) {
784
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
899
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
Lines 1202-1207 Link Here
1202
1317
1203
    /* open the mutex lockfile */
1318
    /* open the mutex lockfile */
1204
    ssl_mutex_reinit(s, p);
1319
    ssl_mutex_reinit(s, p);
1320
1321
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
1322
    ssl_ossle_child_init(p, s);
1323
#endif /*if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)*/
1205
}
1324
}
1206
1325
1207
#define MODSSL_CFG_ITEM_FREE(func, item) \
1326
#define MODSSL_CFG_ITEM_FREE(func, item) \
Lines 1242-1275 Link Here
1242
    }
1361
    }
1243
}
1362
}
1244
1363
1245
apr_status_t ssl_init_ModuleKill(void *data)
1364
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
1365
static apr_status_t ssl_ossle_child_exit(server_rec* s)
1246
{
1366
{
1247
    SSLSrvConfigRec *sc;
1367
    SSLSrvConfigRec *sc = mySrvConfig(s);
1248
    server_rec *base_server = (server_rec *)data;
1368
    SSLModConfigRec *mc = myModConfig(s);
1369
1370
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
1371
        "Begin child process engine cleanup: pid=`%d' engine=`%s'",
1372
            mc->pid, mc->szCryptoDevice);
1373
    ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, s);
1374
1375
    ssl_tmp_keys_free(s);
1376
    ssl_init_ctx_cleanup_proxy(sc->proxy);
1377
    ssl_init_ctx_cleanup_server(sc->server);
1378
    EVP_cleanup();
1379
1380
    ssl_ossle_release_engine(s);
1381
1382
    CRYPTO_cleanup_all_ex_data();
1383
1384
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
1385
        "Completed child process engine cleanup: pid=`%d' engine=`%s'",
1386
            mc->pid, mc->szCryptoDevice);
1387
    ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, s);
1388
1389
    return APR_SUCCESS;
1390
}
1391
1392
static apr_status_t ssl_child_exit(void *data)
1393
{
1394
    return ssl_ossle_child_exit((server_rec *)data);
1395
}
1396
1397
static void ssl_ossle_child_init(apr_pool_t *p, server_rec *base_server)
1398
{
1249
    server_rec *s;
1399
    server_rec *s;
1400
    SSLSrvConfigRec *sc = mySrvConfig(base_server);
1401
    SSLModConfigRec *mc = myModConfig(base_server);
1402
    ENGINE *e;
1403
    apr_pool_t *ptemp;
1250
1404
1251
    /*
1405
    /* XXX: TODO: some means to apply the pkcs11 rules only to those
1252
     * Drop the session cache and mutex
1406
     * engine implementations that care. */
1253
     */
1407
    if (!mc->szCryptoDevice)
1254
    ssl_scache_kill(base_server);
1408
        return;
1255
1409
1256
    /*
1410
    if (mc->engine) {
1257
     * Destroy the temporary keys and params
1411
        /* Complain loudly, but don't die, if the parent process has
1412
         * initialized the engine. */
1413
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
1414
                     "Init(child): Crypto Device API `%s' loaded by parent "
1415
                     "process. This breaks pkcs11 rules (v 2.20 6.6.1). "
1416
                     "Expect problems if your engine is wrapping a pkcs11 "
1417
                     "implementation.",
1418
                     mc->szCryptoDevice);
1419
        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, base_server);
1420
        return;
1421
    }
1422
1423
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server,
1424
        "Begin child process engine initialization: pid=`%d' engine=`%s'",
1425
            mc->pid, mc->szCryptoDevice);
1426
    ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, base_server);
1427
1428
1429
    apr_pool_create(&ptemp, p);
1430
    apr_pool_tag(ptemp, "ptemp");
1431
1432
    if (!(e = ssl_ossle_get_engine(base_server, mc->szCryptoDevice,
1433
                    NULL, 0))) {
1434
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
1435
                     "Init(child): Failed to load Crypto Device API `%s'",
1436
                     mc->szCryptoDevice);
1437
        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, base_server);
1438
        ssl_die();
1439
    }
1440
    if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
1441
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
1442
                     "Init(child): Failed to enable Crypto Device API `%s'",
1443
                     mc->szCryptoDevice);
1444
        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, base_server);
1445
        ssl_die();
1446
    }
1447
1448
    ssl_rand_seed(base_server, ptemp, SSL_RSCTX_STARTUP, "Init(child): ");
1449
1450
    /* XXX: This assumes the backend supporting the engine can deal sensibly
1451
     * with key import on behalf of a multi-process application. Ie, that
1452
     * it *won't* block the server to perform interactive auth each time
1453
     * a new child process goes through the ssl_pphrase_Handle dance.
1258
     */
1454
     */
1259
    ssl_tmp_keys_free(base_server);
1455
    ssl_pphrase_Handle(base_server, ptemp);
1260
1456
1261
    /*
1457
    ssl_tmp_keys_init(base_server);
1262
     * Free the non-pool allocated structures
1458
1263
     * in the per-server configurations
1264
     */
1265
    for (s = base_server; s; s = s->next) {
1459
    for (s = base_server; s; s = s->next) {
1266
        sc = mySrvConfig(s);
1460
        sc = mySrvConfig(s);
1461
        ssl_init_ConfigureServer(s, p, ptemp, sc);
1462
    }
1463
    sc = mySrvConfig(base_server);
1464
    apr_pool_destroy(ptemp);
1267
1465
1268
        ssl_init_ctx_cleanup_proxy(sc->proxy);
1466
    /* ssl_child_exit handler to handle pkcs11 semantics for
1467
     * C_Initialize/C_Finalize */
1468
    apr_pool_cleanup_register(p, base_server, ssl_child_exit, ssl_child_exit);
1269
1469
1270
        ssl_init_ctx_cleanup_server(sc->server);
1470
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server,
1271
    }
1471
        "Completed child process engine initialization: pid=`%d' engine=`%s'",
1472
            mc->pid, mc->szCryptoDevice);
1473
    ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, base_server); 
1474
}
1475
#endif /*if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)*/
1272
1476
1477
apr_status_t ssl_init_ModuleKill(void *data)
1478
{
1479
    server_rec *base_server = (server_rec *)data;
1480
1481
    /* XXX: engine_managed_keys patch: The deletions in this function
1482
     * correspond to the similar deletions in ssl_init_Module and are subject
1483
     * to the same comments.
1484
     *
1485
     * The calls that have moved to the corresponding child cleanup are (in order):
1486
     *  ssl_tmp_keys_free
1487
     *  FOR EACH server, including the base_server:
1488
     *   ssl_init_ctx_cleaup_proxy
1489
     *   ssl_init_ctx_cleanup_server
1490
     */
1491
1492
    /*
1493
     * Drop the session cache and mutex
1494
     */
1495
    ssl_scache_kill(base_server);
1496
1273
    return APR_SUCCESS;
1497
    return APR_SUCCESS;
1274
}
1498
}
1275
1499
(-)httpd-trunk/modules/ssl/ssl_engine_config.c (-2 / +16 lines)
Lines 75-80 Link Here
75
    mc->tPublicCert            = apr_hash_make(pool);
75
    mc->tPublicCert            = apr_hash_make(pool);
76
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
76
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
77
    mc->szCryptoDevice         = NULL;
77
    mc->szCryptoDevice         = NULL;
78
    mc->engine                 = NULL;
78
#endif
79
#endif
79
80
80
    memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys));
81
    memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys));
Lines 432-440 Link Here
432
    if (strcEQ(arg, "builtin")) {
433
    if (strcEQ(arg, "builtin")) {
433
        mc->szCryptoDevice = NULL;
434
        mc->szCryptoDevice = NULL;
434
    }
435
    }
435
    else if ((e = ENGINE_by_id(arg))) {
436
    else if ((e = ssl_ossle_get_engine(cmd->server, arg,
437
                    NULL /*openssl.cnf*/, 0 /*disablecnf*/))) {
436
        mc->szCryptoDevice = arg;
438
        mc->szCryptoDevice = arg;
437
        ENGINE_free(e);
439
        /* In order to more easily accommodate pkcs11's requirement of "one
440
         * context per process", immediately unload the engine once we know the
441
         * config argument is good. NOTE: `ENGINE_free' or `ENGINE_finish' are
442
         * not thorough enough.
443
         */
444
        ssl_ossle_release_engine(cmd->server);
438
    }
445
    }
439
    else {
446
    else {
440
        err = "SSLCryptoDevice: Invalid argument; must be one of: "
447
        err = "SSLCryptoDevice: Invalid argument; must be one of: "
Lines 652-660 Link Here
652
    const char *err, *desc=NULL, **files=NULL;
659
    const char *err, *desc=NULL, **files=NULL;
653
    int i;
660
    int i;
654
661
662
    /* checking that arg is a file, that it exists, and is non empty is totally
663
     * incompatible with hardware hosted keys. Unfortunately, because the order
664
     * we will encounter SSLCryptoDevice vs the various SSLCertificate commands
665
     * is indeterminate, I can see no obvious way to may this check work -
666
     * order dependence and apache config appears to be a general malaise. */
667
#if 0
655
    if ((err = ssl_cmd_check_file(parms, &arg))) {
668
    if ((err = ssl_cmd_check_file(parms, &arg))) {
656
        return err;
669
        return err;
657
    }
670
    }
671
#endif
658
672
659
    switch (idx) {
673
    switch (idx) {
660
      case SSL_AIDX_CERTS:
674
      case SSL_AIDX_CERTS:
(-)httpd-trunk/modules/ssl/ssl_engine_pphrase.c (-29 / +94 lines)
Lines 206-224 Link Here
206
            } else {
206
            } else {
207
                apr_cpystrn(szPath, sc->server->pks->cert_files[i],
207
                apr_cpystrn(szPath, sc->server->pks->cert_files[i],
208
                            sizeof(szPath));
208
                            sizeof(szPath));
209
                if ((rv = exists_and_readable(szPath, p, NULL))
209
210
                    != APR_SUCCESS) {
210
                if (!mc->engine) {
211
                    ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
211
                     if ((rv = exists_and_readable(szPath, p, NULL))
212
                                 "Init: Can't open server certificate file %s",
212
                         != APR_SUCCESS) {
213
                                 szPath);
213
                         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
214
                    ssl_die();
214
                                      "Init: Can't open server certificate "
215
                                      "file %s", szPath);
216
                         ssl_die();
217
                     }
218
                     if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)
219
                                    ) == NULL) {
220
                         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
221
                                      "Init: Unable to read server "
222
                                      "certificate from file %s", szPath);
223
                         ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
224
                         ssl_die();
225
                     }
215
                }
226
                }
216
                if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) {
227
                else {
217
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
228
                    /* XXX: For backwards compat, and convenience for engine
218
                                 "Init: Unable to read server certificate from"
229
                     * implementors, we should probably have a configurable
219
                                 " file %s", szPath);
230
                     * means to say: "for these named engines, use apaches
220
                    ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
231
                     * existing pem file support to load server keys and
221
                    ssl_die();
232
                     * certificates", this patch treats all engines the same
233
                     * TODO:
234
                     *  1. explicit support for passing UI callbacks and
235
                     * data necessary for hardware that needs password entry,
236
                     * or other interactions, in order to load keys. It's a can
237
                     * of worms so I'm leaving it out for now.
238
                     * 2. Add at least "SSLCryptoDeviceLoadCertCmd" in order to
239
                     * enable a more general purpose implementation of engine
240
                     * based certificate loading. */
241
                    pX509Cert = ssl_ossle_load_cert_engine_pkcs11(s, szPath);
242
                    if(!pX509Cert) {
243
                         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
244
                              "Init: Unable to server certificate `%s' using "
245
                              "engine `%s'",
246
                              szPath, mc->szCryptoDevice
247
                              );
248
                         ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
249
                         ssl_die();
250
                    }
222
                }
251
                }
223
            }
252
            }
224
            /*
253
            /*
Lines 302-308 Link Here
302
                 * the callback function which serves the pass
331
                 * the callback function which serves the pass
303
                 * phrases to OpenSSL
332
                 * phrases to OpenSSL
304
                 */
333
                 */
305
                if ((rv = exists_and_readable(szPath, p,
334
                if (!mc->engine && (rv = exists_and_readable(szPath, p,
306
                                              &pkey_mtime)) != APR_SUCCESS ) {
335
                                              &pkey_mtime)) != APR_SUCCESS ) {
307
                     ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
336
                     ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
308
                                  "Init: Can't open server private key file "
337
                                  "Init: Can't open server private key file "
Lines 357-366 Link Here
357
                 * functions will fail spuriously if the error stack
386
                 * functions will fail spuriously if the error stack
358
                 * is not empty. */
387
                 * is not empty. */
359
                ERR_clear_error();
388
                ERR_clear_error();
389
                if (!mc->engine) {
390
                     bReadable = ((pPrivateKey = SSL_read_PrivateKey(szPath,
391
                                         NULL, ssl_pphrase_Handle_CB, s))
392
                               != NULL ? TRUE : FALSE);
393
                }
394
                else {
395
                    pPrivateKey = ENGINE_load_private_key(
396
                            mc->engine, szPath, 0 /*ui_method*/, 0 /*cbdata*/);
397
                    bReadable = pPrivateKey != NULL ? TRUE : FALSE;
398
                }
360
399
361
                bReadable = ((pPrivateKey = SSL_read_PrivateKey(szPath, NULL,
362
                            ssl_pphrase_Handle_CB, s)) != NULL ? TRUE : FALSE);
363
364
                /*
400
                /*
365
                 * when the private key file now was readable,
401
                 * when the private key file now was readable,
366
                 * it's fine and we go out of the loop
402
                 * it's fine and we go out of the loop
Lines 451-462 Link Here
451
            }
487
            }
452
488
453
            if (pPrivateKey == NULL) {
489
            if (pPrivateKey == NULL) {
454
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
490
               if (!mc->engine) {
455
                            "Init: Unable to read server private key from "
491
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
456
                            "file %s [Hint: Perhaps it is in a separate file? "
492
                                "Init: Unable to read server private key from "
457
                            "  See SSLCertificateKeyFile]", szPath);
493
                                "file %s [Hint: Perhaps it is in a separate "
458
                ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
494
                                "file? See SSLCertificateKeyFile]", szPath);
459
                ssl_die();
495
                    ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
496
                    ssl_die();
497
               }
498
               else {
499
                    /* log the error with clear indication that engine format
500
                     * keys are in play. */
501
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
502
                                "Init: Unable to load server private key "
503
                                "using the identifier `%s' and engine `%s'",
504
                                szPath, mc->szCryptoDevice);
505
                    ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
506
               }
460
            }
507
            }
461
508
462
            /*
509
            /*
Lines 513-527 Link Here
513
             * RSA structure which do not survive DSO reloads!)
560
             * RSA structure which do not survive DSO reloads!)
514
             */
561
             */
515
            cp = asn1_table_vhost_key(mc, p, cpVHostID, an);
562
            cp = asn1_table_vhost_key(mc, p, cpVHostID, an);
516
            length = i2d_PrivateKey(pPrivateKey, NULL);
563
            if (!mc->engine) {
517
            ucp = ssl_asn1_table_set(mc->tPrivateKey, cp, length);
564
                 length = i2d_PrivateKey(pPrivateKey, NULL);
518
            (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
565
                 ucp = ssl_asn1_table_set(mc->tPrivateKey, cp, length);
566
                 /* 2nd arg increments */
567
                 (void)i2d_PrivateKey(pPrivateKey, &ucp);
519
568
520
            if (nPassPhraseDialogCur != 0) {
569
                 if (nPassPhraseDialogCur != 0) {
521
                /* remember mtime of encrypted keys */
570
                     /* remember mtime of encrypted keys */
522
                asn1 = ssl_asn1_table_get(mc->tPrivateKey, cp);
571
                     asn1 = ssl_asn1_table_get(mc->tPrivateKey, cp);
523
                asn1->source_mtime = pkey_mtime;
572
                     asn1->source_mtime = pkey_mtime;
573
                 }
524
            }
574
            }
575
            else { /* mc->engine != 0 */
576
                 /* the asn1 trick does not play well with hardware hosted
577
                  * keys. */
578
                 length = strlen(szPath) + 1;
579
                 /* cpData is the key_id */
580
                 ucp = ssl_asn1_table_set(mc->tPrivateKey, cp, length);
581
                 memcpy(ucp, szPath, length);
582
                 /* un-necessary, given we will reload, but retained for
583
                  * consistency. */
584
                 if (nPassPhraseDialogCur != 0) {
585
                     /* remember mtime of encrypted keys */
586
                     asn1 = ssl_asn1_table_get(mc->tPrivateKey, cp);
587
                     asn1->source_mtime = pkey_mtime;
588
                 }
589
            }
525
590
526
            /*
591
            /*
527
             * Free the private key structure
592
             * Free the private key structure

Return to bug 42688