You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
4.3 KiB
192 lines
4.3 KiB
/**
|
|
* \file
|
|
*
|
|
* this filter generates a sha1 from the current microtime and request
|
|
* useses this to fill the linux random source.
|
|
*
|
|
* inspired by timed_entropyd.
|
|
*
|
|
* ATTENTION: This module is not portable right now as i don't know
|
|
* howto fill the random source for other systems. It is linux only.
|
|
*
|
|
* Most time was spend in figuring out how to write apache modules.
|
|
*
|
|
* \author Georg Hopp <georg@steffers.org
|
|
*
|
|
* \copyright
|
|
* Copyright © 2012 Georg Hopp
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#define _POSIX_C_SOURCE 199309L
|
|
|
|
#include "httpd.h"
|
|
#include "http_core.h"
|
|
#include "http_connection.h"
|
|
#include "http_config.h"
|
|
#include "http_core.h"
|
|
#include "http_log.h"
|
|
#include "apu.h"
|
|
#include "apr_general.h"
|
|
#include "apr_sha1.h"
|
|
|
|
#include <time.h>
|
|
|
|
|
|
int add_entropy(const unsigned char *, size_t);
|
|
|
|
module AP_MODULE_DECLARE_DATA entropy_module;
|
|
|
|
|
|
/**
|
|
* add header values to sha1
|
|
*/
|
|
static
|
|
int
|
|
header_do_print(void * rec, const char * key, const char * value)
|
|
{
|
|
apr_sha1_ctx_t * sha1_ctx = rec;
|
|
|
|
apr_sha1_update(sha1_ctx, value, strlen(value));
|
|
|
|
return 1;
|
|
}
|
|
|
|
static
|
|
apr_status_t
|
|
entropy_filter_in(
|
|
ap_filter_t * filter,
|
|
apr_bucket_brigade * brigade,
|
|
ap_input_mode_t mode,
|
|
apr_read_type_e block,
|
|
apr_off_t readbytes)
|
|
{
|
|
apr_bucket * bucket;
|
|
apr_status_t status;
|
|
request_rec * request = filter->r;
|
|
conn_rec * connection = filter->c;
|
|
apr_sha1_ctx_t sha1_ctx;
|
|
unsigned char digest[APR_SHA1_DIGESTSIZE];
|
|
ap_version_t ap_version;
|
|
char * remote_ip;
|
|
|
|
struct timespec ts;
|
|
|
|
ap_get_server_revision(&ap_version);
|
|
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
|
|
apr_sha1_init(&sha1_ctx);
|
|
|
|
/**
|
|
* add current microtime to sha1
|
|
*/
|
|
apr_sha1_update_binary(
|
|
&sha1_ctx,
|
|
(const unsigned char *)&ts,
|
|
sizeof(ts));
|
|
|
|
/**
|
|
* add client ip to sha1
|
|
*/
|
|
#if 4 > HTTP_VERSION_MINOR(number)
|
|
remote_ip = connection->remote_ip;
|
|
#else
|
|
remote_ip = connection->client_ip;
|
|
#endif
|
|
|
|
apr_sha1_update(&sha1_ctx, remote_ip, strlen(remote_ip));
|
|
|
|
/**
|
|
* add request line to sha1
|
|
*/
|
|
apr_sha1_update(
|
|
&sha1_ctx,
|
|
request->the_request,
|
|
strlen(request->the_request));
|
|
|
|
/**
|
|
* add all header values to sha1
|
|
*/
|
|
apr_table_do(header_do_print, &sha1_ctx, request->headers_in, NULL);
|
|
|
|
/**
|
|
* get the request body and add it to the sha1
|
|
*/
|
|
status = ap_get_brigade(filter->next, brigade, mode, block, readbytes);
|
|
|
|
if (status == APR_SUCCESS) {
|
|
for (
|
|
bucket = APR_BRIGADE_FIRST(brigade);
|
|
bucket != APR_BRIGADE_SENTINEL(brigade);
|
|
bucket = APR_BUCKET_NEXT(bucket)) {
|
|
|
|
if (!(APR_BUCKET_IS_METADATA(bucket))) {
|
|
const char * buffer;
|
|
apr_size_t nbuffer;
|
|
|
|
status = apr_bucket_read(
|
|
bucket,
|
|
&buffer,
|
|
&nbuffer,
|
|
APR_BLOCK_READ);
|
|
|
|
if (status == APR_SUCCESS) {
|
|
apr_sha1_update(&sha1_ctx, buffer, nbuffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* get the sha1 digest
|
|
*/
|
|
apr_sha1_final(digest, &sha1_ctx);
|
|
|
|
/**
|
|
* fill /dev/random with sha1 from current request
|
|
*/
|
|
add_entropy(digest, APR_SHA1_DIGESTSIZE);
|
|
|
|
/**
|
|
* after we are done remove us from filter queue
|
|
*/
|
|
ap_remove_input_filter(filter);
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* apache module initialization
|
|
*/
|
|
static
|
|
void
|
|
entropy_register_hook(apr_pool_t *p)
|
|
{
|
|
ap_register_input_filter(
|
|
"ENTROPY",
|
|
entropy_filter_in,
|
|
NULL,
|
|
AP_FTYPE_CONTENT_SET);
|
|
}
|
|
|
|
module AP_MODULE_DECLARE_DATA entropy_module = {
|
|
STANDARD20_MODULE_STUFF,
|
|
NULL, /* create per-directory config structure */
|
|
NULL, /* merge per-directory config structures */
|
|
NULL, /* create per-server config structure */
|
|
NULL, /* merge per-server config structures */
|
|
NULL, /* command apr_table_t */
|
|
entropy_register_hook /* register hooks */
|
|
};
|
|
|
|
// vim: set ts=4 sw=4:
|