mod_session_crypto.c revision d6e81217d873dc3b87fc4ffa5fbac2fad4191a15
/* 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
*
*
* 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_ssl.h" /* for apr_*_encrypt et al */
#include "apr_lib.h"
#include "apr_strings.h"
#include "http_log.h"
#define LOG_PREFIX "mod_session_crypto: "
#define DEFAULT_CIPHER "AES256"
#define DEFAULT_DIGEST "SHA"
/**
* Structure to carry the per-dir session config.
*/
typedef struct {
const char *passphrase;
int passphrase_set;
const char *certfile;
int certfile_set;
const char *keyfile;
int keyfile_set;
const char *cipher;
int cipher_set;
const char *digest;
int digest_set;
const char *engine;
int engine_set;
/**
* Initialise the encryption as per the current config.
*
* Returns APR_SUCCESS if successful.
*/
static apr_status_t crypt_init(request_rec * r, apr_evp_factory_t ** f, apr_evp_crypt_key_e * key, session_crypto_dir_conf * conf)
{
"encryption not configured, "
return APR_EGENERAL;
}
/* set up */
if (conf->certfile_set) {
APR_EVP_FACTORY_ASYM, r->pool);
if (APR_ENOTIMPL == res) {
"this version of APR. session encryption not possible");
}
}
else {
*key = APR_EVP_KEY_SYM;
APR_EVP_FACTORY_SYM, r->pool);
if (APR_ENOTIMPL == res) {
"generic symmetrical encryption is not supported by this "
"version of APR. session encryption not possible");
}
}
if (APR_STATUS_IS_ENOCIPHER(res)) {
}
if (APR_STATUS_IS_ENODIGEST(res)) {
}
if (APR_STATUS_IS_ENOCERT(res)) {
"the public and private key could not be extracted from "
"the certificates");
}
if (APR_STATUS_IS_ENOENGINE(res)) {
}
if (APR_SUCCESS != res) {
"encryption could not be configured. Please check the "
return APR_EGENERAL;
}
return APR_SUCCESS;
}
#endif
/**
* Encrypt the string given as per the current config.
*
* Returns APR_SUCCESS if successful.
*/
{
apr_evp_factory_t *f = NULL;
apr_evp_crypt_t *e = NULL;
char *base64;
/* by default, return an empty string */
*out = "";
/* don't attempt to encrypt an empty string, trying to do so causes a segfault */
return APR_SUCCESS;
}
if (res != APR_SUCCESS) {
return res;
}
if (APR_SUCCESS != res) {
"encryption could be configured but not initialised");
return res;
}
/* encrypt the given string */
if (APR_SUCCESS != res) {
"attempt to encrypt failed");
return res;
}
if (APR_SUCCESS != res) {
"attempt to finish the encryption failed");
return res;
}
encryptlen += tlen;
/* base64 encode the result */
/* clean up afterwards */
return res;
#else
"crypto is not supported by APR on this platform");
return APR_ENOTIMPL;
#endif
}
/**
* Decrypt the string given as per the current config.
*
* Returns APR_SUCCESS if successful.
*/
{
apr_evp_factory_t *f = NULL;
apr_evp_crypt_t *e = NULL;
char *decoded;
if (res != APR_SUCCESS) {
return res;
}
if (APR_SUCCESS != res) {
"decryption could be configured but not initialised");
return res;
}
/* strip base64 from the string */
/* decrypt the given string */
if (res) {
"decrypt: attempt to decrypt failed");
return res;
}
if (APR_SUCCESS != res) {
"attempt to finish the decryption failed");
return res;
}
decryptedlen += tlen;
decrypted[decryptedlen] = 0;
return APR_SUCCESS;
#else
"crypto is not supported by APR on this platform");
return APR_ENOTIMPL;
#endif
}
/**
* Crypto encoding for the session.
*
* @param r The request pointer.
* @param z A pointer to where the session will be written.
*/
{
"encrypt session failed");
return res;
}
}
return OK;
}
/**
* Crypto decoding for the session.
*
* @param r The request pointer.
* @param z A pointer to where the session will be written.
*/
{
if (res != APR_SUCCESS) {
"decrypt session failed, wrong passphrase?");
return res;
}
}
return OK;
}
/**
* Initialise the SSL in the post_config hook.
*/
{
apr_ssl_init();
return OK;
}
{
/* default cipher AES256-SHA */
return (void *) new;
}
{
session_crypto_dir_conf *new = (session_crypto_dir_conf *) apr_pcalloc(p, sizeof(session_crypto_dir_conf));
return new;
}
{
if (!filepath) {
}
}
return NULL;
}
{
return NULL;
}
{
if (!res) {
}
return res;
}
{
if (!res) {
}
return res;
}
{
return NULL;
}
{
return NULL;
}
{
return NULL;
}
static const command_rec session_crypto_cmds[] =
{
"The passphrase used to encrypt cookies"),
AP_INIT_TAKE1("SessionCryptoCertificateFile", set_crypto_certificate_file, NULL, RSRC_CONF|OR_AUTHCFG,
"The name of a certificate whose public key will be used to encrypt cookies"),
AP_INIT_TAKE1("SessionCryptoCertificateKeyFile", set_crypto_certificate_keyfile, NULL, RSRC_CONF|OR_AUTHCFG,
"The name of a private key which will be used to decrypt cookies"),
"The cipher used to encrypt cookies. Defaults to " DEFAULT_CIPHER),
"The digest used to encrypt cookies. Defaults to " DEFAULT_DIGEST),
"The optional engine used to encrypt cookies, if supported by the underlying crypto "
"toolkit"),
{NULL}
};
static void register_hooks(apr_pool_t * p)
{
}
{
create_session_crypto_dir_config, /* dir config creater */
merge_session_crypto_dir_config, /* dir merger --- default is to
* override */
NULL, /* server config */
NULL, /* merge server config */
session_crypto_cmds, /* command apr_table_t */
register_hooks /* register hooks */
};