Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 231 lines (193 sloc) 6.959 kb
956a0e9 @nicolasff Added simplistic config file.
authored
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
7107ed0 @nicolasff Better conf parsing.
authored
4 #include <ctype.h>
1209922 @nicolasff Parsed and stored disabled commands.
authored
5 #include <arpa/inet.h>
03af442 @nicolasff Drop privileges.
authored
6 #include <unistd.h>
7 #include <pwd.h>
8 #include <grp.h>
956a0e9 @nicolasff Added simplistic config file.
authored
9
9833000 @nicolasff Switched conf file to JSON.
authored
10 #include <jansson.h>
23c904a @nicolasff Working HTTP Basic Auth.
authored
11 #include <evhttp.h>
37b1281 @nicolasff Base64 encode of user:password for HTTP Basic Auth.
authored
12 #include <libb64/cencode.h>
956a0e9 @nicolasff Added simplistic config file.
authored
13 #include "conf.h"
a7bf6f7 @nicolasff ACL refactoring.
authored
14 #include "acl.h"
956a0e9 @nicolasff Added simplistic config file.
authored
15
41388a5 @nicolasff Parsed ACLs.
authored
16 static struct acl *
17 conf_parse_acls(json_t *jtab);
1209922 @nicolasff Parsed and stored disabled commands.
authored
18
956a0e9 @nicolasff Added simplistic config file.
authored
19 struct conf *
20 conf_read(const char *filename) {
21
1209922 @nicolasff Parsed and stored disabled commands.
authored
22 json_t *j;
9833000 @nicolasff Switched conf file to JSON.
authored
23 json_error_t error;
956a0e9 @nicolasff Added simplistic config file.
authored
24 struct conf *conf;
c7f855f @nicolasff Refactoring in JSON conf loader.
authored
25 void *kv;
956a0e9 @nicolasff Added simplistic config file.
authored
26
9833000 @nicolasff Switched conf file to JSON.
authored
27 /* defaults */
956a0e9 @nicolasff Added simplistic config file.
authored
28 conf = calloc(1, sizeof(struct conf));
9833000 @nicolasff Switched conf file to JSON.
authored
29 conf->redis_host = strdup("127.0.0.1");
956a0e9 @nicolasff Added simplistic config file.
authored
30 conf->redis_port = 6379;
9833000 @nicolasff Switched conf file to JSON.
authored
31 conf->http_host = strdup("0.0.0.0");
956a0e9 @nicolasff Added simplistic config file.
authored
32 conf->http_port = 7379;
85d242f @nicolasff Add HTTP limits (security feature).
authored
33 conf->http_max_request_size = 128*1024*1024;
5b7aa50 @nicolasff Partial rewrite, adding WebSockets, threads, pool.
authored
34 conf->http_threads = 4;
03af442 @nicolasff Drop privileges.
authored
35 conf->user = getuid();
36 conf->group = getgid();
bec19d0 @nicolasff Merge branch 'slog' of https://github.com/mrb/webdis into slog
authored
37 conf->logfile = "webdis.log";
4741fed @nicolasff Log refactoring.
authored
38 conf->verbosity = WEBDIS_NOTICE;
2a84258 @nicolasff Add daemonize support.
authored
39 conf->daemonize = 0;
0bb096a @nicolasff Add database switch in config file.
authored
40 conf->database = 0;
fd404c4 @nicolasff Configurable pool size.
authored
41 conf->pool_size_per_thread = 2;
956a0e9 @nicolasff Added simplistic config file.
authored
42
9833000 @nicolasff Switched conf file to JSON.
authored
43 j = json_load_file(filename, 0, &error);
44 if(!j) {
45 fprintf(stderr, "Error: %s (line %d)\n", error.text, error.line);
46 return conf;
47 }
956a0e9 @nicolasff Added simplistic config file.
authored
48
c7f855f @nicolasff Refactoring in JSON conf loader.
authored
49 for(kv = json_object_iter(j); kv; kv = json_object_iter_next(j, kv)) {
1209922 @nicolasff Parsed and stored disabled commands.
authored
50 json_t *jtmp = json_object_iter_value(kv);
51
c7f855f @nicolasff Refactoring in JSON conf loader.
authored
52 if(strcmp(json_object_iter_key(kv), "redis_host") == 0 && json_typeof(jtmp) == JSON_STRING) {
53 free(conf->redis_host);
54 conf->redis_host = strdup(json_string_value(jtmp));
55 } else if(strcmp(json_object_iter_key(kv), "redis_port") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
1cace80 @nicolasff Lint.
authored
56 conf->redis_port = (short)json_integer_value(jtmp);
f4e2893 @nicolasff Added support for Redis AUTH command.
authored
57 } else if(strcmp(json_object_iter_key(kv), "redis_auth") == 0 && json_typeof(jtmp) == JSON_STRING) {
58 conf->redis_auth = strdup(json_string_value(jtmp));
c7f855f @nicolasff Refactoring in JSON conf loader.
authored
59 } else if(strcmp(json_object_iter_key(kv), "http_host") == 0 && json_typeof(jtmp) == JSON_STRING) {
60 free(conf->http_host);
61 conf->http_host = strdup(json_string_value(jtmp));
62 } else if(strcmp(json_object_iter_key(kv), "http_port") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
1cace80 @nicolasff Lint.
authored
63 conf->http_port = (short)json_integer_value(jtmp);
85d242f @nicolasff Add HTTP limits (security feature).
authored
64 } else if(strcmp(json_object_iter_key(kv), "http_max_request_size") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
65 conf->http_max_request_size = (size_t)json_integer_value(jtmp);
5b7aa50 @nicolasff Partial rewrite, adding WebSockets, threads, pool.
authored
66 } else if(strcmp(json_object_iter_key(kv), "threads") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
67 conf->http_threads = (short)json_integer_value(jtmp);
4a9918d @nicolasff ACL now working again.
authored
68 } else if(strcmp(json_object_iter_key(kv), "acl") == 0 && json_typeof(jtmp) == JSON_ARRAY) {
41388a5 @nicolasff Parsed ACLs.
authored
69 conf->perms = conf_parse_acls(jtmp);
03af442 @nicolasff Drop privileges.
authored
70 } else if(strcmp(json_object_iter_key(kv), "user") == 0 && json_typeof(jtmp) == JSON_STRING) {
71 struct passwd *u;
72 if((u = getpwnam(json_string_value(jtmp)))) {
73 conf->user = u->pw_uid;
74 }
75 } else if(strcmp(json_object_iter_key(kv), "group") == 0 && json_typeof(jtmp) == JSON_STRING) {
76 struct group *g;
77 if((g = getgrnam(json_string_value(jtmp)))) {
78 conf->group = g->gr_gid;
79 }
c16249f @mrb first pass at a simple log
mrb authored
80 } else if(strcmp(json_object_iter_key(kv),"logfile") == 0 && json_typeof(jtmp) == JSON_STRING){
bec19d0 @nicolasff Merge branch 'slog' of https://github.com/mrb/webdis into slog
authored
81 conf->logfile = strdup(json_string_value(jtmp));
82 } else if(strcmp(json_object_iter_key(kv),"verbosity") == 0 && json_typeof(jtmp) == JSON_INTEGER){
752c00b @nicolasff Saved a few syscalls and opening/closing the log. Log either to a fil…
authored
83 int tmp = json_integer_value(jtmp);
84 if(tmp < 0) conf->verbosity = WEBDIS_ERROR;
85 else if(tmp > (int)WEBDIS_DEBUG) conf->verbosity = WEBDIS_DEBUG;
86 else conf->verbosity = (log_level)tmp;
2a84258 @nicolasff Add daemonize support.
authored
87 } else if(strcmp(json_object_iter_key(kv), "daemonize") == 0 && json_typeof(jtmp) == JSON_TRUE) {
88 conf->daemonize = 1;
33f9a2f @nicolasff Disabled Websockets by default.
authored
89 } else if(strcmp(json_object_iter_key(kv), "websockets") == 0 && json_typeof(jtmp) == JSON_TRUE) {
90 conf->websockets = 1;
0bb096a @nicolasff Add database switch in config file.
authored
91 } else if(strcmp(json_object_iter_key(kv), "database") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
92 conf->database = json_integer_value(jtmp);
fd404c4 @nicolasff Configurable pool size.
authored
93 } else if(strcmp(json_object_iter_key(kv), "pool_size") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
94 conf->pool_size_per_thread = json_integer_value(jtmp);
94fb611 @nicolasff Added support for a default root object (fix #26)
authored
95 } else if(strcmp(json_object_iter_key(kv), "default_root") == 0 && json_typeof(jtmp) == JSON_STRING) {
96 conf->default_root = strdup(json_string_value(jtmp));
c7f855f @nicolasff Refactoring in JSON conf loader.
authored
97 }
956a0e9 @nicolasff Added simplistic config file.
authored
98 }
99
9833000 @nicolasff Switched conf file to JSON.
authored
100 json_decref(j);
101
956a0e9 @nicolasff Added simplistic config file.
authored
102 return conf;
103 }
104
41388a5 @nicolasff Parsed ACLs.
authored
105 void
106 acl_read_commands(json_t *jlist, struct acl_commands *ac) {
1209922 @nicolasff Parsed and stored disabled commands.
authored
107
41388a5 @nicolasff Parsed ACLs.
authored
108 unsigned int i, n, cur;
1209922 @nicolasff Parsed and stored disabled commands.
authored
109
41388a5 @nicolasff Parsed ACLs.
authored
110 /* count strings in the array */
111 for(i = 0, n = 0; i < json_array_size(jlist); ++i) {
112 json_t *jelem = json_array_get(jlist, (size_t)i);
113 if(json_typeof(jelem) == JSON_STRING) {
114 n++;
115 }
116 }
1209922 @nicolasff Parsed and stored disabled commands.
authored
117
41388a5 @nicolasff Parsed ACLs.
authored
118 /* allocate block */
119 ac->commands = calloc((size_t)n, sizeof(char*));
120 ac->count = n;
121
122 /* add all disabled commands */
123 for(i = 0, cur = 0; i < json_array_size(jlist); ++i) {
124 json_t *jelem = json_array_get(jlist, i);
125 if(json_typeof(jelem) == JSON_STRING) {
126 size_t sz;
127 const char *s = json_string_value(jelem);
128 sz = strlen(s);
129
130 ac->commands[cur] = calloc(1 + sz, 1);
131 memcpy(ac->commands[cur], s, sz);
132 cur++;
133 }
134 }
135 }
1209922 @nicolasff Parsed and stored disabled commands.
authored
136
41388a5 @nicolasff Parsed ACLs.
authored
137 struct acl *
138 conf_parse_acl(json_t *j) {
1209922 @nicolasff Parsed and stored disabled commands.
authored
139
41388a5 @nicolasff Parsed ACLs.
authored
140 json_t *jcidr, *jbasic, *jlist;
141 unsigned short mask_bits = 0;
1209922 @nicolasff Parsed and stored disabled commands.
authored
142
41388a5 @nicolasff Parsed ACLs.
authored
143 struct acl *a = calloc(1, sizeof(struct acl));
144
145 /* parse CIDR */
146 if((jcidr = json_object_get(j, "ip")) && json_typeof(jcidr) == JSON_STRING) {
147 const char *s;
148 char *p, *ip;
1209922 @nicolasff Parsed and stored disabled commands.
authored
149
41388a5 @nicolasff Parsed ACLs.
authored
150 s = json_string_value(jcidr);
de5c283 @nicolasff Added IP range restriction.
authored
151 p = strchr(s, '/');
1209922 @nicolasff Parsed and stored disabled commands.
authored
152 if(!p) {
153 ip = strdup(s);
154 } else {
1cace80 @nicolasff Lint.
authored
155 ip = calloc((size_t)(p - s + 1), 1);
156 memcpy(ip, s, (size_t)(p - s));
157 mask_bits = (unsigned short)atoi(p+1);
1209922 @nicolasff Parsed and stored disabled commands.
authored
158 }
4a9918d @nicolasff ACL now working again.
authored
159 a->cidr.enabled = 1;
3f510d3 @nicolasff Fixed ACL mask bug.
authored
160 a->cidr.mask = (mask_bits == 0 ? 0xffffffff : (0xffffffff << (32 - mask_bits)));
41388a5 @nicolasff Parsed ACLs.
authored
161 a->cidr.subnet = ntohl(inet_addr(ip)) & a->cidr.mask;
162 free(ip);
163 }
1209922 @nicolasff Parsed and stored disabled commands.
authored
164
41388a5 @nicolasff Parsed ACLs.
authored
165 /* parse basic_auth */
166 if((jbasic = json_object_get(j, "http_basic_auth")) && json_typeof(jbasic) == JSON_STRING) {
37b1281 @nicolasff Base64 encode of user:password for HTTP Basic Auth.
authored
167
168 /* base64 encode */
169 base64_encodestate b64;
170 int pos;
171 char *p;
172 const char *plain = json_string_value(jbasic);
173 size_t len, plain_len = strlen(plain) + 0;
174 len = (plain_len + 8) * 8 / 6;
175 a->http_basic_auth = calloc(len, 1);
176
177 base64_init_encodestate(&b64);
178 pos = base64_encode_block(plain, (int)plain_len, a->http_basic_auth, &b64); /* FIXME: check return value */
179 base64_encode_blockend(a->http_basic_auth + pos, &b64);
180
17c0c59 @nicolasff Small refactoring.
authored
181 /* end string with \0 rather than \n */
37b1281 @nicolasff Base64 encode of user:password for HTTP Basic Auth.
authored
182 if((p = strchr(a->http_basic_auth + pos, '\n'))) {
183 *p = 0;
184 }
41388a5 @nicolasff Parsed ACLs.
authored
185 }
186
187 /* parse enabled commands */
4a9918d @nicolasff ACL now working again.
authored
188 if((jlist = json_object_get(j, "enabled")) && json_typeof(jlist) == JSON_ARRAY) {
189 acl_read_commands(jlist, &a->enabled);
41388a5 @nicolasff Parsed ACLs.
authored
190 }
191
192 /* parse disabled commands */
4a9918d @nicolasff ACL now working again.
authored
193 if((jlist = json_object_get(j, "disabled")) && json_typeof(jlist) == JSON_ARRAY) {
194 acl_read_commands(jlist, &a->disabled);
41388a5 @nicolasff Parsed ACLs.
authored
195 }
196
197 return a;
198 }
199
200 struct acl *
201 conf_parse_acls(json_t *jtab) {
202
4a9918d @nicolasff ACL now working again.
authored
203 struct acl *head = NULL, *tail = NULL, *tmp;
41388a5 @nicolasff Parsed ACLs.
authored
204
4a9918d @nicolasff ACL now working again.
authored
205 unsigned int i;
206 for(i = 0; i < json_array_size(jtab); ++i) {
207 json_t *val = json_array_get(jtab, i);
41388a5 @nicolasff Parsed ACLs.
authored
208
209 tmp = conf_parse_acl(val);
4a9918d @nicolasff ACL now working again.
authored
210 if(head == NULL && tail == NULL) {
211 head = tail = tmp;
212 } else {
213 tail->next = tmp;
214 tail = tmp;
215 }
216 }
217
218 return head;
219 }
220
956a0e9 @nicolasff Added simplistic config file.
authored
221 void
222 conf_free(struct conf *conf) {
223
224 free(conf->redis_host);
f4e2893 @nicolasff Added support for Redis AUTH command.
authored
225 free(conf->redis_auth);
226
956a0e9 @nicolasff Added simplistic config file.
authored
227 free(conf->http_host);
228
229 free(conf);
230 }
Something went wrong with that request. Please try again.