dav/config.c

changeset 252
6b8e287269fc
parent 247
3020d1b5e7bd
child 254
d7c4ba50b7d8
equal deleted inserted replaced
251:7534cb97b9ab 252:6b8e287269fc
33 #include <ucx/map.h> 33 #include <ucx/map.h>
34 #include <errno.h> 34 #include <errno.h>
35 #include <libxml/tree.h> 35 #include <libxml/tree.h>
36 36
37 #include "config.h" 37 #include "config.h"
38 #include "main.h"
38 #include <libidav/utils.h> 39 #include <libidav/utils.h>
39 40
40 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) 41 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b)
41 #define xstrEQ(a,b) !xmlStrcasecmp(BAD_CAST a, BAD_CAST b) 42 #define xstrEQ(a,b) !xmlStrcasecmp(BAD_CAST a, BAD_CAST b)
43
44 #define print_error(...) \
45 do {\
46 fprintf(stderr, "Error (config.xml): " __VA_ARGS__); \
47 fprintf(stderr, "Abort.\n"); \
48 } while(0);
49 #define print_warning(...) \
50 fprintf(stderr, "Warning (config.xml): " __VA_ARGS__);
42 51
43 #ifdef _WIN32 52 #ifdef _WIN32
44 #define ENV_HOME getenv("USERPROFILE") 53 #define ENV_HOME getenv("USERPROFILE")
45 #else 54 #else
46 #define ENV_HOME getenv("HOME") 55 #define ENV_HOME getenv("HOME")
47 #endif /* _WIN32 */ 56 #endif /* _WIN32 */
48 57
49 static UcxMap *repos; 58 static UcxMap *repos;
50 static UcxMap *keys; 59 static UcxMap *keys;
51 static Proxy *http_proxy;
52 static Proxy *https_proxy;
53 60
54 int check_config_dir(void) { 61 int check_config_dir(void) {
55 char *file = util_concat_path(ENV_HOME, ".dav"); 62 char *file = util_concat_path(ENV_HOME, ".dav");
56 int ret = 0; 63 int ret = 0;
57 if(util_mkdir(file, S_IRWXU)) { 64 if(util_mkdir(file, S_IRWXU)) {
71 xmlDocSetRootElement(doc, root); 78 xmlDocSetRootElement(doc, root);
72 xmlSaveFormatFileEnc(file, doc, "UTF-8", 1); 79 xmlSaveFormatFileEnc(file, doc, "UTF-8", 1);
73 xmlFreeDoc(doc); 80 xmlFreeDoc(doc);
74 } 81 }
75 82
76 void load_config(DavContext *ctx) { 83 int load_config(DavContext *ctx) {
77 context = ctx; 84 context = ctx;
78 // TODO: free the config somewhere 85 // TODO: free the config somewhere
79 repos = ucx_map_new(16); 86 repos = ucx_map_new(16);
80 keys = ucx_map_new(16); 87 keys = ucx_map_new(16);
81 http_proxy = calloc(1, sizeof(Proxy));
82 https_proxy = calloc(1, sizeof(Proxy));
83 if(check_config_dir()) { 88 if(check_config_dir()) {
84 return; 89 return 1;
85 } 90 }
86 91
87 char *file = util_concat_path(ENV_HOME, ".dav/config.xml"); 92 char *file = util_concat_path(ENV_HOME, ".dav/config.xml");
88 93
89 struct stat s; 94 struct stat s;
95 } 100 }
96 default: { 101 default: {
97 perror("Cannot load config.xml"); 102 perror("Cannot load config.xml");
98 } 103 }
99 } 104 }
100 return; 105 return 1;
101 } 106 }
102 107
103 xmlDoc *doc = xmlReadFile(file, NULL, 0); 108 xmlDoc *doc = xmlReadFile(file, NULL, 0);
104 free(file); 109 free(file);
105 if(!doc) { 110 if(!doc) {
106 fprintf(stderr, "Cannot load config.xml\n"); 111 fprintf(stderr, "Cannot load config.xml\n");
107 return; 112 return 1;
108 } 113 }
109 114
110 xmlNode *xml_root = xmlDocGetRootElement(doc); 115 xmlNode *xml_root = xmlDocGetRootElement(doc);
111 xmlNode *node = xml_root->children; 116 xmlNode *node = xml_root->children;
112 while(node) { 117 int ret = 0;
118 while(node && !ret) {
113 if(node->type == XML_ELEMENT_NODE) { 119 if(node->type == XML_ELEMENT_NODE) {
114 if(xstreq(node->name, "repository")) { 120 if(xstreq(node->name, "repository")) {
115 load_repository(node); 121 ret = load_repository(node);
116 } else if(xstreq(node->name, "key")) { 122 } else if(xstreq(node->name, "key")) {
117 load_key(node); 123 ret = load_key(node);
118 } else if (xstreq(node->name, "http-proxy")) { 124 } else if (xstreq(node->name, "http-proxy")) {
119 load_proxy(node, HTTP_PROXY); 125 ret = load_proxy(ctx->http_proxy, node, HTTP_PROXY);
120 } else if (xstreq(node->name, "https-proxy")) { 126 } else if (xstreq(node->name, "https-proxy")) {
121 load_proxy(node, HTTPS_PROXY); 127 ret = load_proxy(ctx->https_proxy, node, HTTPS_PROXY);
128 } else {
129 fprintf(stderr, "Unknown config element: %s\n", node->name);
130 ret = 1;
122 } 131 }
123 } 132 }
124 node = node->next; 133 node = node->next;
125 } 134 }
126 135
127 xmlFreeDoc(doc); 136 xmlFreeDoc(doc);
137 return ret;
128 } 138 }
129 139
130 void free_config(void) { 140 void free_config(void) {
131 UcxMapIterator i = ucx_map_iterator(repos); 141 if(repos) {
132 UcxKey k; 142 UcxMapIterator i = ucx_map_iterator(repos);
133 Repository *repo; 143 UcxKey k;
134 UCX_MAP_FOREACH(k, repo, i) { 144 Repository *repo;
135 if(repo->default_key) { 145 UCX_MAP_FOREACH(k, repo, i) {
136 free(repo->default_key); 146 if(repo->default_key) {
137 } 147 free(repo->default_key);
138 if(repo->name) { 148 }
139 free(repo->name); 149 if(repo->name) {
140 } 150 free(repo->name);
141 if(repo->password) { 151 }
142 free(repo->password); 152 if(repo->password) {
143 } 153 free(repo->password);
144 if(repo->url) { 154 }
145 free(repo->url); 155 if(repo->url) {
146 } 156 free(repo->url);
147 if(repo->user) { 157 }
148 free(repo->user); 158 if(repo->user) {
149 } 159 free(repo->user);
150 if(repo->cert) { 160 }
151 free(repo->cert); 161 if(repo->cert) {
152 } 162 free(repo->cert);
153 free(repo); 163 }
154 } 164 free(repo);
155 ucx_map_free(repos); 165 }
156 166 ucx_map_free(repos);
157 ucx_map_free(keys); 167 }
168 if(keys) {
169 ucx_map_free(keys);
170 }
158 } 171 }
159 172
160 Repository* repository_new(void) { 173 Repository* repository_new(void) {
161 Repository *repo = calloc(1, sizeof(Repository)); 174 Repository *repo = calloc(1, sizeof(Repository));
162 repo->encrypt_name = false; 175 repo->encrypt_name = false;
167 repo->ssl_version = CURL_SSLVERSION_DEFAULT; 180 repo->ssl_version = CURL_SSLVERSION_DEFAULT;
168 repo->authmethods = CURLAUTH_BASIC; 181 repo->authmethods = CURLAUTH_BASIC;
169 return repo; 182 return repo;
170 } 183 }
171 184
172 void load_repository(xmlNode *reponode) { 185 int load_repository(xmlNode *reponode) {
173 xmlNode *node = reponode->children;
174 Repository *repo = repository_new(); 186 Repository *repo = repository_new();
175 while(node) { 187 {
176 if(node->type == XML_ELEMENT_NODE) { 188 xmlNode *node = reponode->children;
177 char *name = (char*)node->name; 189 int ret = 0;
178 char *value = util_xml_get_text(node); 190 while(node && !ret) {
179 if(value) { 191 if(node->type == XML_ELEMENT_NODE) {
180 if(repo_add_config(repo, name, value)) { 192 char *name = (char*)node->name;
181 fprintf( 193 char *value = util_xml_get_text(node);
182 stderr, 194 ret = repo_add_config(repo, name, value);
183 "Unkown repository config element: %s\n", 195 }
184 name); 196 node = node->next;
185 } 197 }
186 } 198 if(ret) {
187 } 199 free(repo);
188 node = node->next; 200 return 1;
201 }
189 } 202 }
190 203
191 if(!repo->name) { 204 if(!repo->name) {
192 fprintf( 205 print_error("missing name for repository.\n");
193 stderr, 206 return 1;
194 "Cannot load config.xml: missing name for repository.\n");
195 fprintf(stderr, "Abort.\n");
196 exit(-1);
197 } 207 }
198 if(!repo->url) { 208 if(!repo->url) {
199 fprintf( 209 print_error("missing url for repository '%s'.\n", repo->name);
200 stderr, 210 return 1;
201 "Cannot load config.xml: "
202 "missing url for repository '%s'.\n", repo->name);
203 fprintf(stderr, "Abort.\n");
204 exit(-1);
205 } 211 }
206 212
207 ucx_map_cstr_put(repos, repo->name, repo); 213 ucx_map_cstr_put(repos, repo->name, repo);
208 } 214 return 0;
209 215 }
210 int repo_add_config(Repository *repo, char *key, char *value) { 216
217 int repo_add_config(Repository *repo, char *key, char *value) {
218 /* every key needs a value */
219 if(!value) {
220 /* TODO: maybe this should only be reported, if the key is valid
221 * But this makes the code very ugly.
222 */
223 print_error("missing value for config element: %s\n", key);
224 return 1;
225 }
226
211 if(xstreq(key, "name")) { 227 if(xstreq(key, "name")) {
212 repo->name = strdup(value); 228 repo->name = strdup(value);
213 } else if(xstreq(key, "url")) { 229 } else if(xstreq(key, "url")) {
214 repo->url = strdup(value); 230 repo->url = strdup(value);
215 } else if(xstreq(key, "user")) { 231 } else if(xstreq(key, "user")) {
261 repo->ssl_version = CURL_SSLVERSION_TLSv1_2; 277 repo->ssl_version = CURL_SSLVERSION_TLSv1_2;
262 } 278 }
263 #endif 279 #endif
264 #endif 280 #endif
265 else { 281 else {
266 fprintf(stderr, "Unknown ssl version: %s\n", value); 282 print_warning("unknown ssl version: %s\n", value);
267 } 283 }
268 } else if(xstreq(key, "authmethods")) { 284 } else if(xstreq(key, "authmethods")) {
269 repo->authmethods = CURLAUTH_NONE; 285 repo->authmethods = CURLAUTH_NONE;
270 const char *delims = " \r\n"; 286 const char *delims = " \r\n";
271 char *meths = strdup(value); 287 char *meths = strdup(value);
282 } else if(xstrEQ(value, "any")) { 298 } else if(xstrEQ(value, "any")) {
283 repo->authmethods = CURLAUTH_ANY; 299 repo->authmethods = CURLAUTH_ANY;
284 } else if(xstrEQ(value, "none")) { 300 } else if(xstrEQ(value, "none")) {
285 /* skip */ 301 /* skip */
286 } else { 302 } else {
287 fprintf(stderr, "Unknown authentication method: %s\n", value); 303 print_warning("unknown authentication method: %s\n", value);
288 } 304 }
289 meth = strtok(NULL, delims); 305 meth = strtok(NULL, delims);
290 } 306 }
291 free(meths); 307 free(meths);
292 } else { 308 } else {
293 return -1; 309 print_error("unkown repository config element: %s\n", key);
310 return 1;
294 } 311 }
295 return 0; 312 return 0;
296 } 313 }
297 314
298 void load_proxy(xmlNode *proxynode, int type) { 315 int load_proxy(DavProxy *proxy, xmlNode *proxynode, int type) {
299 Proxy *proxy;
300 const char *stype; 316 const char *stype;
301 if (type == HTTPS_PROXY) { 317 if(type == HTTPS_PROXY) {
302 proxy = https_proxy;
303 stype = "https"; 318 stype = "https";
304 } else if (type == HTTP_PROXY) { 319 } else if(type == HTTP_PROXY) {
305 proxy = http_proxy;
306 stype = "http"; 320 stype = "http";
307 } 321 }
308 322
323 if(!proxy) {
324 print_error("no memory reserved for %s proxy.\n", stype);
325 return 1;
326 }
327
309 xmlNode *node = proxynode->children; 328 xmlNode *node = proxynode->children;
310 while(node) { 329 int ret = 0;
330 while(node && !ret) {
311 if(node->type == XML_ELEMENT_NODE) { 331 if(node->type == XML_ELEMENT_NODE) {
312 char *value = util_xml_get_text(node); 332 char *value = util_xml_get_text(node);
313 if(!value) { 333 int reportmissingvalue = 0;
314 // next 334 if(xstreq(node->name, "url")) {
315 } else if(xstreq(node->name, "url")) { 335 if(!(reportmissingvalue = !value)) {
316 proxy->url = strdup(value); 336 proxy->url = strdup(value);
337 }
317 } else if(xstreq(node->name, "user")) { 338 } else if(xstreq(node->name, "user")) {
318 proxy->user = strdup(value); 339 if(!(reportmissingvalue = !value)) {
340 proxy->username = strdup(value);
341 }
319 } else if(xstreq(node->name, "password")) { 342 } else if(xstreq(node->name, "password")) {
320 proxy->password = util_base64decode(value); 343 if(!(reportmissingvalue = !value)) {
344 proxy->password = util_base64decode(value);
345 }
321 } else if(xstreq(node->name, "no")) { 346 } else if(xstreq(node->name, "no")) {
322 proxy->no = strdup(value); 347 if(!(reportmissingvalue = !value)) {
348 proxy->no_proxy = strdup(value);
349 }
350 } else {
351 print_error("invalid element for proxy config: %s\n",
352 node->name);
353 ret = 1;
354 }
355 if (reportmissingvalue) {
356 print_error("missing value for proxy configuration "
357 "element '%s'.\n", node->name);
358 ret = 1;
323 } 359 }
324 } 360 }
325 node = node->next; 361 node = node->next;
326 } 362 }
327 363
328 if(!proxy->url) { 364 if(!ret && !proxy->url) {
329 fprintf(stderr, 365 print_error("missing url for %s proxy.\n", stype);
330 "Cannot load config.xml: missing url for %s proxy.\n", stype); 366 return 1;
331 fprintf(stderr, "Abort.\n"); 367 }
332 exit(-1); 368
333 } 369 return ret;
334 } 370 }
335 371
336 void load_key(xmlNode *keynode) { 372 int load_key(xmlNode *keynode) {
337 xmlNode *node = keynode->children; 373 xmlNode *node = keynode->children;
338 Key *key = calloc(1, sizeof(Key)); 374 Key *key = calloc(1, sizeof(Key));
339 key->type = KEY_AES256; 375 key->type = KEY_AES256;
340 376
341 int error = 0; 377 int error = 0;
351 sstr_t key_data = load_key_file(value); 387 sstr_t key_data = load_key_file(value);
352 if(key_data.length > 0) { 388 if(key_data.length > 0) {
353 key->data = key_data.ptr; 389 key->data = key_data.ptr;
354 key->length = key_data.length; 390 key->length = key_data.length;
355 } else { 391 } else {
356 fprintf(stderr, "Error: Cannot key from file: %s\n", value); 392 print_error("cannot get key from file: %s\n", value);
357 error = 1; 393 error = 1;
358 } 394 }
359 } else if(xstreq(node->name, "type")) { 395 } else if(xstreq(node->name, "type")) {
360 if(!strcmp(value, "aes128")) { 396 if(!strcmp(value, "aes128")) {
361 key->type = KEY_AES128; 397 key->type = KEY_AES128;
362 } else if(!strcmp(value, "aes256")) { 398 } else if(!strcmp(value, "aes256")) {
363 key->type = KEY_AES256; 399 key->type = KEY_AES256;
364 } else { 400 } else {
365 fprintf(stderr, "Error: unknown key type %s\n", value); 401 print_error("unknown key type %s\n", value);
366 error = 1; 402 error = 1;
367 } 403 }
368 } 404 }
369 405
370 } 406 }
371 node = node->next; 407 node = node->next;
372 } 408 }
373 409
374 if(!error && key->name) { 410 if(!error && key->name) {
375 error = 0; 411 error = 0;
412 size_t expected_length = 0;
376 if(key->type == KEY_AES128) { 413 if(key->type == KEY_AES128) {
377 if(key->length < 16) { 414 expected_length = 16;
378 fprintf(
379 stderr,
380 "Error: Key %s is too small (%zu < 16)\n",
381 key->name,
382 key->length);
383 error = 1;
384 }
385 key->length = 16;
386 } 415 }
387 if(key->type == KEY_AES256) { 416 if(key->type == KEY_AES256) {
388 if(key->length < 32) { 417 expected_length = 32;
389 fprintf( 418 }
390 stderr, 419 if(key->length < expected_length) {
391 "Error: Key %s is too small (%zu < 32)\n", 420 print_error("key %s is too small (%zu < %zu)\n",
392 key->name, 421 key->name,
393 key->length); 422 key->length,
394 error = 1; 423 expected_length);
395 } 424 error = 1;
396 key->length = 32;
397 } 425 }
398 426
399 // add key to context 427 // add key to context
400 if(!error) { 428 if(!error) {
401 ucx_map_cstr_put(keys, key->name, key); 429 ucx_map_cstr_put(keys, key->name, key);
407 if(error) { 435 if(error) {
408 if(key->data) { 436 if(key->data) {
409 free(key->data); 437 free(key->data);
410 } 438 }
411 free(key); 439 free(key);
440 return 1;
441 } else {
442 return 0;
412 } 443 }
413 } 444 }
414 445
415 sstr_t load_key_file(char *filename) { 446 sstr_t load_key_file(char *filename) {
416 sstr_t k; 447 sstr_t k;
470 if(!name) { 501 if(!name) {
471 return NULL; 502 return NULL;
472 } 503 }
473 return ucx_map_cstr_get(keys, name); 504 return ucx_map_cstr_get(keys, name);
474 } 505 }
475
476 Proxy* get_http_proxy(void) {
477 return http_proxy;
478 }
479
480 Proxy* get_https_proxy(void) {
481 return https_proxy;
482 }
483
484 506
485 int add_repository(Repository *repo) { 507 int add_repository(Repository *repo) {
486 char *file = util_concat_path(ENV_HOME, ".dav/config.xml"); 508 char *file = util_concat_path(ENV_HOME, ".dav/config.xml");
487 xmlDoc *doc = xmlReadFile(file, NULL, 0); 509 xmlDoc *doc = xmlReadFile(file, NULL, 0);
488 if(!doc) { 510 if(!doc) {

mercurial