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")) { |
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); |