chiark / gitweb /
cleanup: provide helpful FILLZERO macro (for certain memset calls)
[secnet.git] / random.c
1 #include "secnet.h"
2 #include <stdio.h>
3 #include <fcntl.h>
4 #include <string.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include <assert.h>
8
9 struct rgen_data {
10     closure_t cl;
11     struct random_if ops;
12     struct cloc loc;
13     int fd;
14 };
15
16 static random_fn random_generate;
17 static bool_t random_generate(void *data, int32_t bytes, uint8_t *buff)
18 {
19     struct rgen_data *st=data;
20     int r;
21
22     r= read(st->fd,buff,bytes);
23
24     assert(r == bytes);
25     /* This is totally crap error checking, but AFAICT many callers of
26      * this function do not check the return value.  This is a minimal
27      * change to make the code not fail silently-but-insecurely.
28      *
29      * A proper fix requires either:
30      *  - Declare all random number generation failures as fatal
31      *    errors, and make this return void, and fix all callers,
32      *    and make this call some appropriate function if it fails.
33      *  - Make this have proper error checking (and reporting!)
34      *    and make all callers check the error (and report!);
35      *    this will be tricky, I think, because you have to report
36      *    the errno somewhere.
37      *
38      * There's also the issue that this is only one possible
39      * implementation of a random number source; others may not rely
40      * on reading from a file descriptor, and may not produce
41      * appropriate settings of errno.
42      */
43
44     return True;
45 }
46
47 static list_t *random_apply(closure_t *self, struct cloc loc,
48                             dict_t *context, list_t *args)
49 {
50     struct rgen_data *st;
51     item_t *arg1, *arg2;
52     string_t filename=NULL;
53
54     st=safe_malloc(sizeof(*st),"random_apply");
55
56     st->cl.description="randomsource";
57     st->cl.type=CL_RANDOMSRC;
58     st->cl.apply=NULL;
59     st->cl.interface=&st->ops;
60     st->ops.st=st;
61     st->ops.blocking=False;
62     st->ops.generate=random_generate;
63     st->loc=loc;
64
65     arg1=list_elem(args,0);
66     arg2=list_elem(args,1);
67
68     if (!arg1) {
69         cfgfatal(loc,"randomsource","requires a filename\n");
70     }
71     if (arg1->type != t_string) {
72         cfgfatal(arg1->loc,"randomsource",
73                  "filename (arg1) must be a string\n");
74     }
75     filename=arg1->data.string;
76
77     if (arg2) {
78         if (arg2->type != t_bool) {
79             cfgfatal(arg2->loc,"randomsource",
80                      "blocking parameter (arg2) must be bool\n");
81         }
82         st->ops.blocking=arg2->data.bool;
83     }
84
85     if (!filename) {
86         cfgfatal(loc,"randomsource","requires a filename\n");
87     }
88     st->fd=open(filename,O_RDONLY);
89     if (st->fd<0) {
90         fatal_perror("randomsource (%s:%d): cannot open %s",arg1->loc.file,
91                      arg1->loc.line,filename);
92     }
93     return new_closure(&st->cl);
94 }
95
96 void random_module(dict_t *d)
97 {
98     add_closure(d,"randomfile",random_apply);
99 }