Commit 11a6d63570cca4e340f97f529386d3b0cedf3dc3

Authored by Georg Hopp
1 parent d19157cb

initial checkin

  1 +.*.swp
  2 +*.o
  3 +*.a
  4 +*.gcda
  5 +*.gcno
  6 +.dirstamp
  7 +.deps/
  8 +Makefile
  9 +Makefile.in
  10 +/config*
  11 +m4/
  12 +/docs/
  13 +/INSTALL
  14 +coverage.base
  15 +coverage.run
  16 +coverage.info
  17 +coveragereport/
  18 +*.m4
  19 +/autom4te.cache/
  20 +/compile
  21 +/depcomp
  22 +/docs/
  23 +/install-sh
  24 +/libtool
  25 +/ltmain.sh
  26 +/missing
  27 +stamp-h1
  28 +src/taskrambler
  29 +/tests/*Test
  30 +gmon.out
  1 +## This is the shared library to be built
  2 +lib_LTLIBRARIES = libmodentropy.la
  3 +
  4 +## Define the source file for the module
  5 +libmodentropy_la_SOURCES = mod_entropy.c mod_entropy_get_entropy_bits.c \
  6 + mod_entropy_add_entropy.c
  7 +libmodentropy_la_LDFLAGS = -lrt -lm
  8 +
  9 +install: libmodentropy.la
  10 + apxs -i -a -n entropy libmodentropy.la
  11 +
  12 +## Define that an include directory is required.
  13 +#INCLUDES = -I@apache_dir@/include -I/usr/include/apr-1
  14 +
  1 +/**
  2 + * this filter generates a sha1 from the current microtime and request
  3 + * useses this to fill the linux random source.
  4 + *
  5 + * inspired by timed_entropyd.
  6 + *
  7 + * ATTENTION: This module is not portable right now as i don't know
  8 + * howto fill the random source for other systems. It is linux only.
  9 + *
  10 + * Most time was spend in figuring out how to write apache modules.
  11 + *
  12 + * \author Georg Hopp <georg@steffers.org>
  13 + */
  14 +#define _POSIX_C_SOURCE 199309L
  15 +
  16 +#include <apache2/httpd.h>
  17 +#include <apache2/http_core.h>
  18 +#include <apr-1/apu.h>
  19 +#include <apr-1/apr_general.h>
  20 +#include <apr-1/apr_sha1.h>
  21 +
  22 +#include <time.h>
  23 +#include <math.h>
  24 +#include <fcntl.h>
  25 +#include <errno.h>
  26 +#include <linux/random.h>
  27 +#include <sys/ioctl.h>
  28 +#include <sys/types.h>
  29 +#include <sys/stat.h>
  30 +
  31 +#define min(x, y) ((x)<(y)?(x):(y))
  32 +
  33 +
  34 +module AP_MODULE_DECLARE_DATA entropy_module;
  35 +
  36 +char * getData(const char *, size_t);
  37 +
  38 +/**
  39 + * This is taken from timer_entropyd and modified so
  40 + * that the constant 1/log(2.0) is not calculated but
  41 + * set directly.
  42 + *
  43 + * As far as i can say this correlates to the shannon
  44 + * entropy algorithm with equal probabilities
  45 + * for entropy where the entropy units are bits.
  46 + *
  47 + * But actually i am no mathemacian and my analysis capabilities
  48 + * are limited. Additionally i have not analysed the linux random
  49 + * character device code, so i trusted the code in timer_entropyd.
  50 + */
  51 +static
  52 +int
  53 +get_entropy(const unsigned char * data, size_t ndata)
  54 +{
  55 + size_t byte_count[256];
  56 + size_t iterator;
  57 + static double log2inv = 1.442695; //!< 1 / log(2.0): the entropy unit size
  58 + double entropy = 0.0;
  59 +
  60 + memset(byte_count, 0, sizeof(byte_count));
  61 +
  62 + /**
  63 + * first get the amount each byte occurs in the array
  64 + */
  65 + for (iterator = 0; iterator < ndata; iterator++) {
  66 + byte_count[data[iterator]]++;
  67 + }
  68 +
  69 + for (iterator = 0; iterator < 256; iterator++) {
  70 + double probability = (double)byte_count[iterator] / (double)ndata;
  71 +
  72 + if (0.0 < probability) {
  73 + entropy += probability * log2inv * (log(1.0 / probability));
  74 + }
  75 + }
  76 +
  77 + entropy *= (double)ndata;
  78 + entropy = (entropy < 0.0)? 0.0 : entropy;
  79 + entropy = min((double)(ndata * 8), entropy);
  80 +
  81 + return entropy;
  82 +}
  83 +
  84 +static
  85 +int
  86 +header_do_print(void * rec, const char * key, const char * value)
  87 +{
  88 + apr_sha1_ctx_t * sha1_ctx = rec;
  89 +
  90 + apr_sha1_update(sha1_ctx, value, strlen(value));
  91 +
  92 + return 1;
  93 +}
  94 +
  95 +static
  96 +apr_status_t
  97 +entropy_filter_in(
  98 + ap_filter_t * filter,
  99 + apr_bucket_brigade * brigade,
  100 + ap_input_mode_t mode,
  101 + apr_read_type_e block,
  102 + apr_off_t readbytes)
  103 +{
  104 + apr_bucket * bucket;
  105 + apr_status_t status;
  106 + request_rec * request = filter->r;
  107 + conn_rec * connection = filter->c;
  108 + apr_sha1_ctx_t sha1_ctx;
  109 + unsigned char digest[APR_SHA1_DIGESTSIZE];
  110 +
  111 + struct timespec ts;
  112 +
  113 + clock_gettime(CLOCK_REALTIME, &ts);
  114 +
  115 + apr_sha1_init(&sha1_ctx);
  116 +
  117 + /**
  118 + * add current microtime to sha1
  119 + */
  120 + apr_sha1_update_binary(
  121 + &sha1_ctx,
  122 + (const unsigned char *)&ts,
  123 + sizeof(ts));
  124 +
  125 + /**
  126 + * add client ip to sha1
  127 + */
  128 + apr_sha1_update(
  129 + &sha1_ctx,
  130 + connection->client_ip,
  131 + strlen(connection->client_ip));
  132 +
  133 + /**
  134 + * add request line to sha1
  135 + */
  136 + apr_sha1_update(
  137 + &sha1_ctx,
  138 + request->the_request,
  139 + strlen(request->the_request));
  140 +
  141 + /**
  142 + * add all header values to sha1
  143 + */
  144 + apr_table_do(header_do_print, &sha1_ctx, request->headers_in, NULL);
  145 +
  146 + /**
  147 + * get the request body and add it to the sha1
  148 + */
  149 + status = ap_get_brigade(filter->next, brigade, mode, block, readbytes);
  150 +
  151 + if (status == APR_SUCCESS) {
  152 + for (
  153 + bucket = APR_BRIGADE_FIRST(brigade);
  154 + bucket != APR_BRIGADE_SENTINEL(brigade);
  155 + bucket = APR_BUCKET_NEXT(bucket)) {
  156 +
  157 + if (!(APR_BUCKET_IS_METADATA(bucket))) {
  158 + const char * buffer;
  159 + apr_size_t nbuffer;
  160 +
  161 + status = apr_bucket_read(
  162 + bucket,
  163 + &buffer,
  164 + &nbuffer,
  165 + APR_BLOCK_READ);
  166 +
  167 + if (status == APR_SUCCESS) {
  168 + apr_sha1_update(&sha1_ctx, buffer, nbuffer);
  169 + }
  170 + }
  171 + }
  172 + }
  173 +
  174 + /**
  175 + * get the sha1 digest
  176 + */
  177 + apr_sha1_final(digest, &sha1_ctx);
  178 +
  179 + /**
  180 + * fill /dev/random with sha1 from current request
  181 + */
  182 + {
  183 + int i;
  184 + int entropy = get_entropy(digest, APR_SHA1_DIGESTSIZE);
  185 + int fd = open("/dev/random", O_WRONLY|O_NONBLOCK);
  186 + struct rand_pool_info * output;
  187 +
  188 + output = (struct rand_pool_info *)malloc(
  189 + sizeof(struct rand_pool_info) + APR_SHA1_DIGESTSIZE);
  190 +
  191 + output->entropy_count = entropy;
  192 + output->buf_size = APR_SHA1_DIGESTSIZE;
  193 + memcpy(output->buf, digest, APR_SHA1_DIGESTSIZE);
  194 +
  195 + fprintf(stderr, "sha1 so far: ");
  196 + for (i=0; i<APR_SHA1_DIGESTSIZE; i++) {
  197 + fprintf(stderr, "%02x", digest[i]);
  198 + }
  199 + fprintf(stderr, "\n");
  200 + fprintf(stderr, "entropy bits: %d\n", entropy);
  201 +
  202 + if (ioctl(fd, RNDADDENTROPY, output) == -1) {
  203 + switch(errno) {
  204 + case EBADF:
  205 + fprintf(stderr, "ioctl failed: no valid file descriptor %d\n", fd);
  206 + break;
  207 +
  208 + case EFAULT:
  209 + fprintf(stderr, "ioctl failed: invalid argument: %p\n", output);
  210 + break;
  211 +
  212 + case EINVAL:
  213 + fprintf(stderr, "ioctl failed: invalid request\n", errno);
  214 + break;
  215 +
  216 + case ENOTTY:
  217 + fprintf(stderr, "ioctl failed: discriptor not associated to character device\n", errno);
  218 + break;
  219 +
  220 + case EPERM:
  221 + fprintf(stderr, "ioctl failed: invalid permissions\n", errno);
  222 + break;
  223 +
  224 + default:
  225 + fprintf(stderr, "ioctl(RNDADDENTROPY) failed: %d\n", errno);
  226 + break;
  227 + }
  228 + }
  229 +
  230 + free(output);
  231 + close(fd);
  232 + }
  233 + fflush(stderr);
  234 +
  235 + ap_remove_input_filter(filter);
  236 +
  237 + return status;
  238 +}
  239 +
  240 +/**
  241 + * apache module initialization
  242 + */
  243 +static
  244 +void
  245 +entropy_register_hook(apr_pool_t *p)
  246 +{
  247 + ap_register_input_filter(
  248 + "ENTROPY",
  249 + entropy_filter_in,
  250 + NULL,
  251 + AP_FTYPE_CONTENT_SET);
  252 +}
  253 +
  254 +module AP_MODULE_DECLARE_DATA entropy_module = {
  255 + STANDARD20_MODULE_STUFF,
  256 + NULL, /* create per-directory config structure */
  257 + NULL, /* merge per-directory config structures */
  258 + NULL, /* create per-server config structure */
  259 + NULL, /* merge per-server config structures */
  260 + NULL, /* command apr_table_t */
  261 + entropy_register_hook /* register hooks */
  262 +};
  263 +
  264 +// vim: set ts=4 sw=4:
Please register or login to post a comment