3 changed files with 308 additions and 0 deletions
-
30.gitignore
-
14Makefile.am
-
264mod_entropy.c
@ -0,0 +1,30 @@ |
|||
.*.swp |
|||
*.o |
|||
*.a |
|||
*.gcda |
|||
*.gcno |
|||
.dirstamp |
|||
.deps/ |
|||
Makefile |
|||
Makefile.in |
|||
/config* |
|||
m4/ |
|||
/docs/ |
|||
/INSTALL |
|||
coverage.base |
|||
coverage.run |
|||
coverage.info |
|||
coveragereport/ |
|||
*.m4 |
|||
/autom4te.cache/ |
|||
/compile |
|||
/depcomp |
|||
/docs/ |
|||
/install-sh |
|||
/libtool |
|||
/ltmain.sh |
|||
/missing |
|||
stamp-h1 |
|||
src/taskrambler |
|||
/tests/*Test |
|||
gmon.out |
|||
@ -0,0 +1,14 @@ |
|||
## This is the shared library to be built
|
|||
lib_LTLIBRARIES = libmodentropy.la |
|||
|
|||
## Define the source file for the module
|
|||
libmodentropy_la_SOURCES = mod_entropy.c mod_entropy_get_entropy_bits.c \
|
|||
mod_entropy_add_entropy.c |
|||
libmodentropy_la_LDFLAGS = -lrt -lm |
|||
|
|||
install: libmodentropy.la |
|||
apxs -i -a -n entropy libmodentropy.la |
|||
|
|||
## Define that an include directory is required.
|
|||
#INCLUDES = -I@apache_dir@/include -I/usr/include/apr-1
|
|||
|
|||
@ -0,0 +1,264 @@ |
|||
/** |
|||
* 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> |
|||
*/ |
|||
#define _POSIX_C_SOURCE 199309L |
|||
|
|||
#include <apache2/httpd.h> |
|||
#include <apache2/http_core.h> |
|||
#include <apr-1/apu.h> |
|||
#include <apr-1/apr_general.h> |
|||
#include <apr-1/apr_sha1.h> |
|||
|
|||
#include <time.h> |
|||
#include <math.h> |
|||
#include <fcntl.h> |
|||
#include <errno.h> |
|||
#include <linux/random.h> |
|||
#include <sys/ioctl.h> |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
|
|||
#define min(x, y) ((x)<(y)?(x):(y)) |
|||
|
|||
|
|||
module AP_MODULE_DECLARE_DATA entropy_module; |
|||
|
|||
char * getData(const char *, size_t); |
|||
|
|||
/** |
|||
* This is taken from timer_entropyd and modified so |
|||
* that the constant 1/log(2.0) is not calculated but |
|||
* set directly. |
|||
* |
|||
* As far as i can say this correlates to the shannon |
|||
* entropy algorithm with equal probabilities |
|||
* for entropy where the entropy units are bits. |
|||
* |
|||
* But actually i am no mathemacian and my analysis capabilities |
|||
* are limited. Additionally i have not analysed the linux random |
|||
* character device code, so i trusted the code in timer_entropyd. |
|||
*/ |
|||
static |
|||
int |
|||
get_entropy(const unsigned char * data, size_t ndata) |
|||
{ |
|||
size_t byte_count[256]; |
|||
size_t iterator; |
|||
static double log2inv = 1.442695; //!< 1 / log(2.0): the entropy unit size |
|||
double entropy = 0.0; |
|||
|
|||
memset(byte_count, 0, sizeof(byte_count)); |
|||
|
|||
/** |
|||
* first get the amount each byte occurs in the array |
|||
*/ |
|||
for (iterator = 0; iterator < ndata; iterator++) { |
|||
byte_count[data[iterator]]++; |
|||
} |
|||
|
|||
for (iterator = 0; iterator < 256; iterator++) { |
|||
double probability = (double)byte_count[iterator] / (double)ndata; |
|||
|
|||
if (0.0 < probability) { |
|||
entropy += probability * log2inv * (log(1.0 / probability)); |
|||
} |
|||
} |
|||
|
|||
entropy *= (double)ndata; |
|||
entropy = (entropy < 0.0)? 0.0 : entropy; |
|||
entropy = min((double)(ndata * 8), entropy); |
|||
|
|||
return entropy; |
|||
} |
|||
|
|||
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]; |
|||
|
|||
struct timespec ts; |
|||
|
|||
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 |
|||
*/ |
|||
apr_sha1_update( |
|||
&sha1_ctx, |
|||
connection->client_ip, |
|||
strlen(connection->client_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 |
|||
*/ |
|||
{ |
|||
int i; |
|||
int entropy = get_entropy(digest, APR_SHA1_DIGESTSIZE); |
|||
int fd = open("/dev/random", O_WRONLY|O_NONBLOCK); |
|||
struct rand_pool_info * output; |
|||
|
|||
output = (struct rand_pool_info *)malloc( |
|||
sizeof(struct rand_pool_info) + APR_SHA1_DIGESTSIZE); |
|||
|
|||
output->entropy_count = entropy; |
|||
output->buf_size = APR_SHA1_DIGESTSIZE; |
|||
memcpy(output->buf, digest, APR_SHA1_DIGESTSIZE); |
|||
|
|||
fprintf(stderr, "sha1 so far: "); |
|||
for (i=0; i<APR_SHA1_DIGESTSIZE; i++) { |
|||
fprintf(stderr, "%02x", digest[i]); |
|||
} |
|||
fprintf(stderr, "\n"); |
|||
fprintf(stderr, "entropy bits: %d\n", entropy); |
|||
|
|||
if (ioctl(fd, RNDADDENTROPY, output) == -1) { |
|||
switch(errno) { |
|||
case EBADF: |
|||
fprintf(stderr, "ioctl failed: no valid file descriptor %d\n", fd); |
|||
break; |
|||
|
|||
case EFAULT: |
|||
fprintf(stderr, "ioctl failed: invalid argument: %p\n", output); |
|||
break; |
|||
|
|||
case EINVAL: |
|||
fprintf(stderr, "ioctl failed: invalid request\n", errno); |
|||
break; |
|||
|
|||
case ENOTTY: |
|||
fprintf(stderr, "ioctl failed: discriptor not associated to character device\n", errno); |
|||
break; |
|||
|
|||
case EPERM: |
|||
fprintf(stderr, "ioctl failed: invalid permissions\n", errno); |
|||
break; |
|||
|
|||
default: |
|||
fprintf(stderr, "ioctl(RNDADDENTROPY) failed: %d\n", errno); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
free(output); |
|||
close(fd); |
|||
} |
|||
fflush(stderr); |
|||
|
|||
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: |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue