mirror of
https://github.com/apache/httpd.git
synced 2025-08-03 16:33:59 +00:00

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1103337 13f79535-47bb-0310-9956-ffa450edef68
666 lines
22 KiB
C
666 lines
22 KiB
C
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "mod_session.h"
|
|
#include "apu_version.h"
|
|
#include "apr_base64.h" /* for apr_base64_decode et al */
|
|
#include "apr_lib.h"
|
|
#include "apr_strings.h"
|
|
#include "http_log.h"
|
|
#include "http_core.h"
|
|
|
|
#if APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION < 4
|
|
|
|
#error session_crypto_module requires APU v1.4.0 or later
|
|
|
|
#elif APU_HAVE_CRYPTO == 0
|
|
|
|
#error Crypto support must be enabled in APR
|
|
|
|
#else
|
|
|
|
#if APR_MAJOR_VERSION < 2
|
|
#define CRYPTO_VERSION 104
|
|
#else
|
|
#define CRYPTO_VERSION 200
|
|
#endif
|
|
|
|
#include "apr_crypto.h" /* for apr_*_crypt et al */
|
|
|
|
#define LOG_PREFIX "mod_session_crypto: "
|
|
#define DRIVER_KEY "session_crypto_driver"
|
|
|
|
module AP_MODULE_DECLARE_DATA session_crypto_module;
|
|
|
|
/**
|
|
* Structure to carry the per-dir session config.
|
|
*/
|
|
typedef struct {
|
|
const char *passphrase;
|
|
apr_array_header_t *params;
|
|
int passphrase_set;
|
|
apr_crypto_block_key_type_e cipher;
|
|
int cipher_set;
|
|
}session_crypto_dir_conf;
|
|
|
|
/**
|
|
* Structure to carry the server wide session config.
|
|
*/
|
|
typedef struct {
|
|
const char *library;
|
|
apr_array_header_t *params;
|
|
int library_set;
|
|
int noinit;
|
|
int noinit_set;
|
|
}session_crypto_conf;
|
|
|
|
AP_DECLARE(int) ap_session_crypto_encode(request_rec * r, session_rec * z);
|
|
AP_DECLARE(int) ap_session_crypto_decode(request_rec * r, session_rec * z);
|
|
AP_DECLARE(int) ap_session_crypto_init(apr_pool_t *p, apr_pool_t *plog,
|
|
apr_pool_t *ptemp, server_rec *s);
|
|
|
|
/**
|
|
* Initialise the encryption as per the current config.
|
|
*
|
|
* Returns APR_SUCCESS if successful.
|
|
*/
|
|
static apr_status_t crypt_init(request_rec * r,
|
|
const apr_crypto_driver_t *driver,
|
|
apr_crypto_t **f, apr_crypto_key_t **key,
|
|
apr_uuid_t *salt, apr_size_t *ivSize,
|
|
session_crypto_dir_conf * dconf)
|
|
{
|
|
apr_status_t res;
|
|
|
|
if (!driver) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, LOG_PREFIX
|
|
"encryption driver not configured, "
|
|
"no SessionCryptoDriver set");
|
|
return APR_EGENERAL;
|
|
}
|
|
|
|
if (!dconf->passphrase_set) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, LOG_PREFIX
|
|
"encryption not configured, "
|
|
"no passphrase set");
|
|
return APR_EGENERAL;
|
|
}
|
|
|
|
/* set up */
|
|
#if CRYPTO_VERSION < 200
|
|
res = apr_crypto_make(driver, r->pool, dconf->params, f);
|
|
#else
|
|
res = apr_crypto_make(f, driver, dconf->params, r->pool);
|
|
#endif
|
|
if (APR_ENOTIMPL == res) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"generic symmetrical encryption is not supported by this "
|
|
"version of APR. session encryption not possible");
|
|
}
|
|
|
|
if (APR_SUCCESS == res) {
|
|
#if CRYPTO_VERSION < 200
|
|
res = apr_crypto_passphrase(driver, r->pool, *f, dconf->passphrase,
|
|
strlen(dconf->passphrase),
|
|
(unsigned char *) salt, salt ? sizeof(apr_uuid_t) : 0,
|
|
dconf->cipher, APR_MODE_CBC, 1, 4096, key, ivSize);
|
|
#else
|
|
res = apr_crypto_passphrase(key, ivSize, dconf->passphrase,
|
|
strlen(dconf->passphrase),
|
|
(unsigned char *) salt, salt ? sizeof(apr_uuid_t) : 0,
|
|
dconf->cipher, APR_MODE_CBC, 1, 4096, *f, r->pool);
|
|
#endif
|
|
}
|
|
|
|
if (APR_STATUS_IS_ENOKEY(res)) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"the passphrase '%s' was empty", dconf->passphrase);
|
|
}
|
|
if (APR_STATUS_IS_EPADDING(res)) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"padding is not supported for cipher");
|
|
}
|
|
if (APR_STATUS_IS_EKEYTYPE(res)) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"the key type is not known");
|
|
}
|
|
if (APR_SUCCESS != res) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"encryption could not be configured. Please check the "
|
|
"certificates and/or passphrase as appropriate");
|
|
return APR_EGENERAL;
|
|
}
|
|
|
|
return APR_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Encrypt the string given as per the current config.
|
|
*
|
|
* Returns APR_SUCCESS if successful.
|
|
*/
|
|
static apr_status_t encrypt_string(request_rec * r,
|
|
const apr_crypto_driver_t *driver,
|
|
session_crypto_dir_conf *dconf,
|
|
const char *in, char **out)
|
|
{
|
|
apr_status_t res;
|
|
apr_crypto_t *f = NULL;
|
|
apr_crypto_key_t *key = NULL;
|
|
apr_size_t ivSize = 0;
|
|
apr_crypto_block_t *block = NULL;
|
|
unsigned char *encrypt = NULL;
|
|
unsigned char *combined = NULL;
|
|
apr_size_t encryptlen, tlen;
|
|
char *base64;
|
|
apr_size_t blockSize = 0;
|
|
const unsigned char *iv = NULL;
|
|
apr_uuid_t salt;
|
|
|
|
/* by default, return an empty string */
|
|
*out = "";
|
|
|
|
/* don't attempt to encrypt an empty string, trying to do so causes a segfault */
|
|
if (!in || !*in) {
|
|
return APR_SUCCESS;
|
|
}
|
|
|
|
/* use a uuid as a salt value, and prepend it to our result */
|
|
apr_uuid_get(&salt);
|
|
res = crypt_init(r, driver, &f, &key, &salt, &ivSize, dconf);
|
|
if (res != APR_SUCCESS) {
|
|
return res;
|
|
}
|
|
|
|
#if CRYPTO_VERSION < 200
|
|
res = apr_crypto_block_encrypt_init(driver, r->pool, f, key, &iv, &block,
|
|
&blockSize);
|
|
#else
|
|
res = apr_crypto_block_encrypt_init(&block, &iv, key,
|
|
&blockSize, f, r->pool);
|
|
#endif
|
|
if (APR_SUCCESS != res) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"apr_crypto_block_encrypt_init failed");
|
|
return res;
|
|
}
|
|
|
|
/* encrypt the given string */
|
|
#if CRYPTO_VERSION < 200
|
|
res = apr_crypto_block_encrypt(driver, block, &encrypt,
|
|
&encryptlen, (unsigned char *)in, strlen(in));
|
|
#else
|
|
res = apr_crypto_block_encrypt(&encrypt,
|
|
&encryptlen, (unsigned char *)in, strlen(in), f, block);
|
|
#endif
|
|
if (APR_SUCCESS != res) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"apr_crypto_block_encrypt failed");
|
|
return res;
|
|
}
|
|
#if CRYPTO_VERSION < 200
|
|
res = apr_crypto_block_encrypt_finish(driver, block, encrypt + encryptlen,
|
|
&tlen);
|
|
#else
|
|
res = apr_crypto_block_encrypt_finish(encrypt + encryptlen,
|
|
&tlen, f, block);
|
|
#endif
|
|
if (APR_SUCCESS != res) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"apr_crypto_block_encrypt_finish failed");
|
|
return res;
|
|
}
|
|
encryptlen += tlen;
|
|
|
|
/* prepend the salt and the iv to the result */
|
|
combined = apr_palloc(r->pool, ivSize + encryptlen + sizeof(apr_uuid_t));
|
|
memcpy(combined, &salt, sizeof(apr_uuid_t));
|
|
memcpy(combined + sizeof(apr_uuid_t), iv, ivSize);
|
|
memcpy(combined + sizeof(apr_uuid_t) + ivSize, encrypt, encryptlen);
|
|
|
|
/* base64 encode the result */
|
|
base64 = apr_palloc(r->pool, apr_base64_encode_len(ivSize + encryptlen +
|
|
sizeof(apr_uuid_t) + 1)
|
|
* sizeof(char));
|
|
apr_base64_encode(base64, (const char *) combined,
|
|
ivSize + encryptlen + sizeof(apr_uuid_t));
|
|
*out = base64;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
/**
|
|
* Decrypt the string given as per the current config.
|
|
*
|
|
* Returns APR_SUCCESS if successful.
|
|
*/
|
|
static apr_status_t decrypt_string(request_rec * r,
|
|
const apr_crypto_driver_t *driver,
|
|
session_crypto_dir_conf *dconf,
|
|
const char *in, char **out)
|
|
{
|
|
apr_status_t res;
|
|
apr_crypto_t *f = NULL;
|
|
apr_crypto_key_t *key = NULL;
|
|
apr_size_t ivSize = 0;
|
|
apr_crypto_block_t *block = NULL;
|
|
unsigned char *decrypted = NULL;
|
|
apr_size_t decryptedlen, tlen;
|
|
apr_size_t decodedlen;
|
|
char *decoded;
|
|
apr_size_t blockSize = 0;
|
|
|
|
/* strip base64 from the string */
|
|
decoded = apr_palloc(r->pool, apr_base64_decode_len(in));
|
|
decodedlen = apr_base64_decode(decoded, in);
|
|
decoded[decodedlen] = '\0';
|
|
|
|
res = crypt_init(r, driver, &f, &key, (apr_uuid_t *)decoded, &ivSize, dconf);
|
|
if (res != APR_SUCCESS) {
|
|
return res;
|
|
}
|
|
|
|
/* sanity check - decoded too short? */
|
|
if (decodedlen < (sizeof(apr_uuid_t) + ivSize)) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, LOG_PREFIX
|
|
"too short to decrypt, skipping");
|
|
return APR_ECRYPT;
|
|
}
|
|
|
|
/* bypass the salt at the start of the decoded block */
|
|
decoded += sizeof(apr_uuid_t);
|
|
decodedlen -= sizeof(apr_uuid_t);
|
|
|
|
#if CRYPTO_VERSION < 200
|
|
res = apr_crypto_block_decrypt_init(driver, r->pool, f, key, (unsigned char *)decoded, &block,
|
|
&blockSize);
|
|
#else
|
|
res = apr_crypto_block_decrypt_init(&block, &blockSize, (unsigned char *)decoded, key,
|
|
f, r->pool);
|
|
#endif
|
|
if (APR_SUCCESS != res) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"apr_crypto_block_decrypt_init failed");
|
|
return res;
|
|
}
|
|
|
|
/* bypass the iv at the start of the decoded block */
|
|
decoded += ivSize;
|
|
decodedlen -= ivSize;
|
|
|
|
/* decrypt the given string */
|
|
#if CRYPTO_VERSION < 200
|
|
res = apr_crypto_block_decrypt(driver, block, &decrypted,
|
|
&decryptedlen, (unsigned char *)decoded, decodedlen);
|
|
#else
|
|
res = apr_crypto_block_decrypt(&decrypted,
|
|
&decryptedlen, (unsigned char *)decoded, decodedlen, f, block);
|
|
#endif
|
|
if (res) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"apr_crypto_block_decrypt failed");
|
|
return res;
|
|
}
|
|
*out = (char *) decrypted;
|
|
|
|
#if CRYPTO_VERSION < 200
|
|
res = apr_crypto_block_decrypt_finish(driver, block, decrypted + decryptedlen,
|
|
&tlen);
|
|
#else
|
|
res = apr_crypto_block_decrypt_finish(decrypted + decryptedlen,
|
|
&tlen, f, block);
|
|
#endif
|
|
if (APR_SUCCESS != res) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"apr_crypto_block_decrypt_finish failed");
|
|
return res;
|
|
}
|
|
decryptedlen += tlen;
|
|
decrypted[decryptedlen] = 0;
|
|
|
|
return APR_SUCCESS;
|
|
|
|
}
|
|
|
|
/**
|
|
* Crypto encoding for the session.
|
|
*
|
|
* @param r The request pointer.
|
|
* @param z A pointer to where the session will be written.
|
|
*/
|
|
AP_DECLARE(int) ap_session_crypto_encode(request_rec * r, session_rec * z)
|
|
{
|
|
|
|
char *encoded = NULL;
|
|
apr_status_t res;
|
|
const apr_crypto_driver_t *driver = NULL;
|
|
session_crypto_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
|
|
&session_crypto_module);
|
|
|
|
if (dconf->passphrase_set && z->encoded && *z->encoded) {
|
|
apr_pool_userdata_get((void **)&driver, DRIVER_KEY, r->server->process->pconf);
|
|
res = encrypt_string(r, driver, dconf, z->encoded, &encoded);
|
|
if (res != OK) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, res, r, LOG_PREFIX
|
|
"encrypt session failed");
|
|
return res;
|
|
}
|
|
z->encoded = encoded;
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
/**
|
|
* Crypto decoding for the session.
|
|
*
|
|
* @param r The request pointer.
|
|
* @param z A pointer to where the session will be written.
|
|
*/
|
|
AP_DECLARE(int) ap_session_crypto_decode(request_rec * r, session_rec * z)
|
|
{
|
|
|
|
char *encoded = NULL;
|
|
apr_status_t res;
|
|
const apr_crypto_driver_t *driver = NULL;
|
|
session_crypto_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
|
|
&session_crypto_module);
|
|
|
|
if ((dconf->passphrase_set) && z->encoded && *z->encoded) {
|
|
apr_pool_userdata_get((void **)&driver, DRIVER_KEY,
|
|
r->server->process->pconf);
|
|
res = decrypt_string(r, driver, dconf, z->encoded, &encoded);
|
|
if (res != APR_SUCCESS) {
|
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, LOG_PREFIX
|
|
"decrypt session failed, wrong passphrase?");
|
|
return res;
|
|
}
|
|
z->encoded = encoded;
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
/**
|
|
* Initialise the SSL in the post_config hook.
|
|
*/
|
|
AP_DECLARE(int) ap_session_crypto_init(apr_pool_t *p, apr_pool_t *plog,
|
|
apr_pool_t *ptemp, server_rec *s)
|
|
{
|
|
const apr_crypto_driver_t *driver = NULL;
|
|
|
|
session_crypto_conf *conf = ap_get_module_config(s->module_config,
|
|
&session_crypto_module);
|
|
|
|
/* session_crypto_init() will be called twice. Don't bother
|
|
* going through all of the initialization on the first call
|
|
* because it will just be thrown away.*/
|
|
if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
|
|
return OK;
|
|
|
|
if (conf->library) {
|
|
|
|
const apu_err_t *err = NULL;
|
|
apr_status_t rv;
|
|
|
|
rv = apr_crypto_init(p, NULL);
|
|
if (APR_SUCCESS != rv) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, LOG_PREFIX
|
|
"APR crypto could not be initialised");
|
|
return rv;
|
|
}
|
|
|
|
#if CRYPTO_VERSION < 200
|
|
rv = apr_crypto_get_driver(p, conf->library, &driver, conf->params, &err);
|
|
#else
|
|
rv = apr_crypto_get_driver(&driver, conf->library, conf->params, &err, p);
|
|
#endif
|
|
if (APR_EREINIT == rv) {
|
|
if (!conf->noinit) {
|
|
ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, LOG_PREFIX
|
|
"warning: crypto for '%s' was already initialised, "
|
|
"using existing configuration", conf->library);
|
|
}
|
|
rv = APR_SUCCESS;
|
|
}
|
|
else {
|
|
if (conf->noinit) {
|
|
ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, LOG_PREFIX
|
|
"warning: crypto for '%s' was not previously initialised "
|
|
"when it was expected to be, initialised instead by "
|
|
"mod_session_crypto", conf->library);
|
|
}
|
|
}
|
|
if (APR_SUCCESS != rv && err) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, LOG_PREFIX
|
|
"%s", err->msg);
|
|
return rv;
|
|
}
|
|
if (APR_ENOTIMPL == rv) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, LOG_PREFIX
|
|
"The crypto library '%s' could not be found",
|
|
conf->library);
|
|
return rv;
|
|
}
|
|
if (APR_SUCCESS != rv || !driver) {
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, LOG_PREFIX
|
|
"The crypto library '%s' could not be loaded",
|
|
conf->library);
|
|
return rv;
|
|
}
|
|
|
|
ap_log_error(APLOG_MARK, APLOG_INFO, rv, s, LOG_PREFIX
|
|
"The crypto library '%s' was loaded successfully",
|
|
conf->library);
|
|
|
|
apr_pool_userdata_set((const void *)driver, DRIVER_KEY,
|
|
apr_pool_cleanup_null, s->process->pconf);
|
|
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static void *create_session_crypto_config(apr_pool_t * p, server_rec *s)
|
|
{
|
|
session_crypto_conf *new =
|
|
(session_crypto_conf *) apr_pcalloc(p, sizeof(session_crypto_conf));
|
|
|
|
/* if no library has been configured, set the recommended library
|
|
* as a sensible default.
|
|
*/
|
|
#ifdef APU_CRYPTO_RECOMMENDED_DRIVER
|
|
new->library = APU_CRYPTO_RECOMMENDED_DRIVER;
|
|
#endif
|
|
|
|
return (void *) new;
|
|
}
|
|
|
|
static void *create_session_crypto_dir_config(apr_pool_t * p, char *dummy)
|
|
{
|
|
session_crypto_dir_conf *new =
|
|
(session_crypto_dir_conf *) apr_pcalloc(p, sizeof(session_crypto_dir_conf));
|
|
|
|
/* default cipher AES256-SHA */
|
|
new->cipher = APR_KEY_AES_256;
|
|
|
|
return (void *) new;
|
|
}
|
|
|
|
static void *merge_session_crypto_dir_config(apr_pool_t * p, void *basev, void *addv)
|
|
{
|
|
session_crypto_dir_conf *new = (session_crypto_dir_conf *) apr_pcalloc(p, sizeof(session_crypto_dir_conf));
|
|
session_crypto_dir_conf *add = (session_crypto_dir_conf *) addv;
|
|
session_crypto_dir_conf *base = (session_crypto_dir_conf *) basev;
|
|
|
|
new->passphrase = (add->passphrase_set == 0) ? base->passphrase : add->passphrase;
|
|
new->params = (add->passphrase_set == 0) ? base->params : add->params;
|
|
new->passphrase_set = add->passphrase_set || base->passphrase_set;
|
|
new->cipher = (add->cipher_set == 0) ? base->cipher : add->cipher;
|
|
new->cipher_set = add->cipher_set || base->cipher_set;
|
|
|
|
return new;
|
|
}
|
|
|
|
static const char *set_crypto_driver(cmd_parms * cmd, void *config, const char *arg)
|
|
{
|
|
char *word, *val;
|
|
int library_set = 0;
|
|
session_crypto_conf *conf =
|
|
(session_crypto_conf *)ap_get_module_config(cmd->server->module_config,
|
|
&session_crypto_module);
|
|
apr_crypto_param_t *param;
|
|
|
|
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
|
|
|
if (err != NULL) {
|
|
return err;
|
|
}
|
|
|
|
conf->params = apr_array_make(cmd->pool, 10, sizeof(apr_crypto_param_t));
|
|
|
|
while (*arg) {
|
|
word = ap_getword_conf(cmd->pool, &arg);
|
|
val = strchr(word, '=');
|
|
if (!val) {
|
|
if (!strcasecmp(word, "noinit")) {
|
|
conf->noinit = 1;
|
|
conf->noinit_set = 1;
|
|
}
|
|
else if (!library_set) {
|
|
conf->library = word;
|
|
conf->library_set = 1;
|
|
library_set = 1;
|
|
}
|
|
else {
|
|
return "Invalid SessionCryptoDriver parameter. Parameter must "
|
|
"be in the form 'key=value'.";
|
|
}
|
|
}
|
|
else {
|
|
*val++ = '\0';
|
|
if (!strcasecmp(word, "dir")) {
|
|
param = apr_array_push(conf->params);
|
|
param->type = APR_CRYPTO_CA_TYPE_DIR;
|
|
param->path = val;
|
|
}
|
|
else if (!strcasecmp(word, "key3")) {
|
|
param = apr_array_push(conf->params);
|
|
param->type = APR_CRYPTO_CERT_TYPE_KEY3_DB;
|
|
param->path = val;
|
|
}
|
|
else if (!strcasecmp(word, "cert7")) {
|
|
param = apr_array_push(conf->params);
|
|
param->type = APR_CRYPTO_CA_TYPE_CERT7_DB;
|
|
param->path = val;
|
|
}
|
|
else if (!strcasecmp(word, "secmod")) {
|
|
param = apr_array_push(conf->params);
|
|
param->type = APR_CRYPTO_CA_TYPE_SECMOD;
|
|
param->path = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static const char *set_crypto_passphrase(cmd_parms * cmd, void *config, const char *arg)
|
|
{
|
|
char *word, *val;
|
|
int passphrase_set = 0;
|
|
session_crypto_dir_conf *dconf = (session_crypto_dir_conf *) config;
|
|
apr_crypto_param_t *param;
|
|
dconf->params = apr_array_make(cmd->pool, 10, sizeof(apr_crypto_param_t));
|
|
|
|
while (*arg) {
|
|
word = ap_getword_conf(cmd->pool, &arg);
|
|
val = strchr(word, '=');
|
|
if (!val) {
|
|
if (!passphrase_set) {
|
|
dconf->passphrase = word;
|
|
dconf->passphrase_set = 1;
|
|
passphrase_set = 1;
|
|
}
|
|
else {
|
|
return "Invalid SessionCryptoPassphrase parameter. Parameter must "
|
|
"be in the form 'key=value'.";
|
|
}
|
|
}
|
|
else {
|
|
*val++ = '\0';
|
|
if (!strcasecmp(word, "engine")) {
|
|
param = apr_array_push(dconf->params);
|
|
param->type = APR_CRYPTO_ENGINE;
|
|
param->path = val;
|
|
}
|
|
else if (!strcasecmp(word, "cipher")) {
|
|
if (!strcasecmp(val, "3des192")) {
|
|
dconf->cipher = APR_KEY_3DES_192;
|
|
dconf->cipher_set = 1;
|
|
}
|
|
else if (!strcasecmp(val, "aes256")) {
|
|
dconf->cipher = APR_KEY_AES_256;
|
|
dconf->cipher_set = 1;
|
|
}
|
|
else {
|
|
return "Invalid SessionCryptoPassphrase parameter. Cipher must "
|
|
"be '3des192' or 'aes256'.";
|
|
}
|
|
}
|
|
else {
|
|
return "Invalid SessionCryptoPassphrase parameter. Parameters must "
|
|
"be 'engine' or 'cipher'.";
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static const command_rec session_crypto_cmds[] =
|
|
{
|
|
AP_INIT_RAW_ARGS("SessionCryptoPassphrase", set_crypto_passphrase, NULL, RSRC_CONF|OR_AUTHCFG,
|
|
"The passphrase used to encrypt the session"),
|
|
AP_INIT_RAW_ARGS("SessionCryptoDriver", set_crypto_driver, NULL, RSRC_CONF,
|
|
"The underlying crypto library driver to use"),
|
|
{ NULL}
|
|
};
|
|
|
|
static void register_hooks(apr_pool_t * p)
|
|
{
|
|
ap_hook_session_encode(ap_session_crypto_encode, NULL, NULL, APR_HOOK_LAST);
|
|
ap_hook_session_decode(ap_session_crypto_decode, NULL, NULL, APR_HOOK_FIRST);
|
|
ap_hook_post_config(ap_session_crypto_init, NULL, NULL, APR_HOOK_FIRST);
|
|
}
|
|
|
|
AP_DECLARE_MODULE(session_crypto) =
|
|
{
|
|
STANDARD20_MODULE_STUFF,
|
|
create_session_crypto_dir_config, /* dir config creater */
|
|
merge_session_crypto_dir_config, /* dir merger --- default is to
|
|
* override */
|
|
create_session_crypto_config, /* server config */
|
|
NULL, /* merge server config */
|
|
session_crypto_cmds, /* command apr_table_t */
|
|
register_hooks /* register hooks */
|
|
};
|
|
|
|
#endif
|