Line data Source code
1 : #include "burp.h"
2 : #include "alloc.h"
3 : #include "conf.h"
4 : #include "fsops.h"
5 : #include "handy.h"
6 : #include "lock.h"
7 : #include "log.h"
8 : #include "msg.h"
9 : #include "pathcmp.h"
10 : #include "prepend.h"
11 : #include "strlist.h"
12 : #include "server/timestamp.h"
13 : #include "client/glob_windows.h"
14 : #include "conffile.h"
15 :
16 : // This will strip off everything after the last quote. So, configs like this
17 : // should work:
18 : // exclude_regex = "[A-Z]:/pagefile.sys" # swap file (Windows XP, 7, 8)
19 : // Return 1 for quotes removed, -1 for error, 0 for OK.
20 2322 : static int remove_quotes(const char *f, char **v, char quote)
21 : {
22 2322 : char *dp=NULL;
23 2322 : char *sp=NULL;
24 2322 : char *copy=NULL;
25 :
26 : // If it does not start with a quote, leave it alone.
27 2322 : if(**v!=quote) return 0;
28 :
29 4 : if(!(copy=strdup_w(*v, __func__)))
30 : return -1;
31 :
32 8 : for(dp=*v, sp=copy+1; *sp; sp++)
33 : {
34 6 : if(*sp==quote)
35 : {
36 : // Found a matching quote. Stop here.
37 2 : *dp='\0';
38 2 : for(sp++; *sp && isspace(*sp); sp++) { }
39 : // Do not complain about trailing comments.
40 2 : if(*sp && *sp!='#')
41 0 : logp("ignoring trailing characters after quote in config '%s = %s'\n", f, copy);
42 : return 1;
43 : }
44 4 : else if(*sp=='\\')
45 : {
46 0 : sp++;
47 0 : *dp=*sp;
48 0 : dp++;
49 0 : if(*sp!=quote
50 0 : && *sp!='\\')
51 0 : logp("unknown escape sequence '\\%c' in config '%s = %s' - treating it as '%c'\n", *sp, f, copy, *sp);
52 : }
53 : else
54 : {
55 4 : *dp=*sp;
56 4 : dp++;
57 : }
58 : }
59 2 : logp("Did not find closing quote in config '%s = %s'\n", f, copy);
60 2 : *dp='\0';
61 2 : return 1;
62 : }
63 :
64 : // Get field and value pair.
65 1177 : int conf_get_pair(char buf[], char **f, char **v)
66 : {
67 1177 : char *cp=NULL;
68 1177 : char *eq=NULL;
69 :
70 : // strip leading space
71 1177 : for(cp=buf; *cp && isspace(*cp); cp++) { }
72 1177 : if(!*cp || *cp=='#')
73 : {
74 14 : *f=NULL;
75 14 : *v=NULL;
76 14 : return 0;
77 : }
78 1163 : *f=cp;
79 1163 : if(!(eq=strchr(*f, '='))) return -1;
80 1162 : *eq='\0';
81 :
82 : // Strip white space from before the equals sign.
83 1162 : for(cp=eq-1; *cp && isspace(*cp); cp--) *cp='\0';
84 : // Skip white space after the equals sign.
85 1162 : for(cp=eq+1; *cp && isspace(*cp); cp++) { }
86 1162 : *v=cp;
87 : // Strip white space at the end of the line.
88 1162 : for(cp+=strlen(cp)-1; *cp && isspace(*cp); cp--) { *cp='\0'; }
89 :
90 : // FIX THIS: Make this more sophisticated - it should understand
91 : // escapes, for example.
92 :
93 1162 : switch(remove_quotes(*f, v, '\''))
94 : {
95 : case -1: return -1;
96 : case 1: break;
97 : default:
98 : // If single quotes were not removed, try to remove
99 : // double quotes.
100 1160 : if(remove_quotes(*f, v, '\"')<0) return -1;
101 : break;
102 : }
103 :
104 1162 : if(!*f || !**f || !*v || !**v) return -1;
105 :
106 1162 : return 0;
107 : }
108 :
109 : static int conf_error(const char *conf_path, int line)
110 : {
111 1 : logp("%s: parse error on line %d\n", conf_path, line);
112 : return -1;
113 : }
114 :
115 2 : static int get_file_size(const char *v, uint64_t *dest, const char *conf_path, int line)
116 : {
117 : // Store in bytes, allow k/m/g.
118 2 : const char *cp=NULL;
119 2 : *dest=strtoul(v, NULL, 10);
120 2 : for(cp=v; *cp && (isspace(*cp) || isdigit(*cp)); cp++) { }
121 2 : if(tolower(*cp)=='k') *dest*=1024;
122 2 : else if(tolower(*cp)=='m') *dest*=1024*1024;
123 2 : else if(tolower(*cp)=='g') *dest*=1024*1024*1024;
124 2 : else if(!*cp || *cp=='b')
125 : { }
126 : else
127 : {
128 0 : logp("Unknown file size type '%s' - please use b/kb/mb/gb\n",
129 : cp);
130 0 : return conf_error(conf_path, line);
131 : }
132 : return 0;
133 : }
134 :
135 426 : static int pre_post_override(struct conf *c,
136 : struct conf *pre, struct conf *post)
137 : {
138 426 : const char *override=get_string(c);
139 426 : if(!override) return 0;
140 5 : if(set_string(pre, override)
141 5 : || set_string(post, override))
142 : return -1;
143 : return 0;
144 : }
145 :
146 : #ifdef HAVE_LINUX_OS
147 : struct fstype
148 : {
149 : const char *str;
150 : uint64_t flag;
151 : };
152 :
153 : static struct fstype fstypes[]={
154 : { "debugfs", 0x64626720 },
155 : { "devfs", 0x00001373 },
156 : { "devpts", 0x00001CD1 },
157 : { "devtmpfs", 0x00009FA0 },
158 : { "ecryptfs", 0x0000f15f },
159 : { "ext2", 0x0000EF53 },
160 : { "ext3", 0x0000EF53 },
161 : { "ext4", 0x0000EF53 },
162 : { "iso9660", 0x00009660 },
163 : { "jfs", 0x3153464A },
164 : { "nfs", 0x00006969 },
165 : { "ntfs", 0x5346544E },
166 : { "proc", 0x00009fa0 },
167 : { "reiserfs", 0x52654973 },
168 : { "securityfs", 0x73636673 },
169 : { "sysfs", 0x62656572 },
170 : { "smbfs", 0x0000517B },
171 : { "usbdevfs", 0x00009fa2 },
172 : { "xfs", 0x58465342 },
173 : { "ramfs", 0x858458f6 },
174 : { "romfs", 0x00007275 },
175 : { "tmpfs", 0x01021994 },
176 : { "zfs", 0x2fc12fc1 },
177 : { NULL, 0 },
178 : };
179 : /* Use this C code to figure out what f_type gets set to.
180 : #include <stdio.h>
181 : #include <sys/vfs.h>
182 :
183 : int main(int argc, char *argv[])
184 : {
185 : int i=0;
186 : struct statfs buf;
187 : if(argc<1)
188 : {
189 : printf("not enough args\n");
190 : return -1;
191 : }
192 : if(statfs(argv[1], &buf))
193 : {
194 : printf("error\n");
195 : return -1;
196 : }
197 : printf("0x%08X\n", buf.f_type);
198 : return 0;
199 : }
200 : */
201 :
202 : #endif
203 :
204 0 : static int fstype_to_flag(const char *fstype, long *flag)
205 : {
206 : #ifdef HAVE_LINUX_OS
207 0 : int i=0;
208 0 : for(i=0; fstypes[i].str; i++)
209 : {
210 0 : if(!strcmp(fstypes[i].str, fstype))
211 : {
212 0 : *flag=fstypes[i].flag;
213 0 : return 0;
214 : }
215 : }
216 : #else
217 : return 0;
218 : #endif
219 : return -1;
220 : }
221 :
222 5 : static int get_compression(const char *v)
223 : {
224 5 : const char *cp=v;
225 5 : if(!strncmp(v, "gzip", strlen("gzip"))
226 5 : || !(strncmp(v, "zlib", strlen("zlib"))))
227 0 : cp=v+strlen("gzip"); // Or "zlib".
228 5 : if(strlen(cp)==1 && isdigit(*cp))
229 5 : return atoi(cp);
230 : return -1;
231 : }
232 :
233 1149 : static int load_conf_field_and_value(struct conf **c,
234 : const char *f, // field
235 : const char *v, // value
236 : const char *conf_path,
237 : int line)
238 : {
239 1149 : if(!strcmp(f, "compression"))
240 : {
241 5 : int compression=get_compression(v);
242 5 : if(compression<0) return -1;
243 5 : set_int(c[OPT_COMPRESSION], compression);
244 : }
245 1144 : else if(!strcmp(f, "ssl_compression"))
246 : {
247 0 : int compression=get_compression(v);
248 0 : if(compression<0) return -1;
249 0 : set_int(c[OPT_SSL_COMPRESSION], compression);
250 : }
251 1144 : else if(!strcmp(f, "ratelimit"))
252 : {
253 0 : float f=0;
254 0 : f=atof(v);
255 : // User is specifying Mega bits per second.
256 : // Need to convert to bytes per second.
257 0 : f=(f*1024*1024)/8;
258 0 : if(!f)
259 : {
260 0 : logp("ratelimit should be greater than zero\n");
261 0 : return -1;
262 : }
263 0 : set_float(c[OPT_RATELIMIT], f);
264 : }
265 : else
266 : {
267 : int i=0;
268 51330 : for(i=0; i<OPT_MAX; i++)
269 : {
270 52469 : if(strcmp(c[i]->field, f)) continue;
271 1139 : switch(c[i]->conf_type)
272 : {
273 : case CT_STRING:
274 823 : return set_string(c[i], v);
275 : case CT_UINT:
276 41 : return set_int(c[i], atoi(v));
277 : case CT_FLOAT:
278 0 : return set_float(c[i], atof(v));
279 : break;
280 : case CT_MODE_T:
281 0 : return set_mode_t(c[i],
282 0 : strtol(v, NULL, 8));
283 : case CT_SSIZE_T:
284 : {
285 2 : uint64_t s=0;
286 : return
287 2 : get_file_size(v, &s, conf_path, line)
288 2 : || set_uint64_t(c[i], s);
289 : }
290 : case CT_E_BURP_MODE:
291 86 : return set_e_burp_mode(c[i],
292 : str_to_burp_mode(v));
293 : case CT_E_PROTOCOL:
294 14 : return set_e_protocol(c[i],
295 : str_to_protocol(v));
296 : case CT_E_RECOVERY_METHOD:
297 1 : return set_e_recovery_method(c[i],
298 : str_to_recovery_method(v));
299 : case CT_STRLIST:
300 172 : return add_to_strlist(c[i], v,
301 172 : !strcmp(c[i]->field, "include"));
302 : case CT_E_RSHASH:
303 : break;
304 : case CT_CNTR:
305 : break;
306 : // No default so we get a warning if something
307 : // was missed;
308 : }
309 : }
310 : }
311 : return 0;
312 : }
313 :
314 : // Recursing, so need to define this ahead of conf_parse_line.
315 : static int conf_load_lines_from_file(const char *conf_path,
316 : struct conf **confs);
317 :
318 0 : static int deal_with_dot_inclusion(const char *conf_path,
319 : char **extrafile, struct conf **confs)
320 : {
321 0 : int ret=-1;
322 0 : char *copy=NULL;
323 : #ifndef HAVE_WIN32
324 0 : int i=0;
325 : glob_t globbuf;
326 0 : if(**extrafile!='/')
327 : #else
328 : if(strlen(*extrafile)>2
329 : && (*extrafile)[1]!=':')
330 : #endif
331 : {
332 : // It is relative to the directory that the
333 : // current conf file is in.
334 0 : char *cp=NULL;
335 0 : char *tmp=NULL;
336 0 : if(!(copy=strdup_w(conf_path, __func__)))
337 : goto end;
338 0 : if((cp=strrchr(copy, '/'))) *cp='\0';
339 0 : if(!(tmp=prepend_s(copy, *extrafile)))
340 : {
341 0 : log_out_of_memory(__func__);
342 0 : goto end;
343 : }
344 0 : free_w(extrafile);
345 0 : *extrafile=tmp;
346 : }
347 : #ifndef HAVE_WIN32
348 : // Treat it is a glob expression.
349 : memset(&globbuf, 0, sizeof(globbuf));
350 0 : glob(*extrafile, 0, NULL, &globbuf);
351 0 : for(i=0; (unsigned int)i<globbuf.gl_pathc; i++)
352 0 : if((ret=conf_load_lines_from_file(globbuf.gl_pathv[i], confs)))
353 : goto end;
354 : #else
355 : ret=conf_load_lines_from_file(*extrafile, confs);
356 : #endif
357 :
358 : end:
359 0 : free_w(©);
360 0 : return ret;
361 : }
362 :
363 1162 : static int conf_parse_line(struct conf **confs, const char *conf_path,
364 : char buf[], int line)
365 : {
366 1162 : int ret=-1;
367 1162 : char *f=NULL; // field
368 1162 : char *v=NULL; // value
369 1162 : char *extrafile=NULL;
370 :
371 1162 : if(!strncmp(buf, ". ", 2))
372 : {
373 : // The conf file specifies another file to include.
374 0 : char *np=NULL;
375 :
376 0 : if(!(extrafile=strdup_w(buf+2, __func__))) goto end;
377 :
378 0 : if((np=strrchr(extrafile, '\n'))) *np='\0';
379 0 : if(!*extrafile) goto end;
380 :
381 0 : ret=deal_with_dot_inclusion(conf_path, &extrafile, confs);
382 0 : goto end;
383 : }
384 :
385 1162 : if(conf_get_pair(buf, &f, &v)) goto end;
386 1161 : if(f && v
387 1149 : && load_conf_field_and_value(confs, f, v, conf_path, line))
388 : goto end;
389 : ret=0;
390 : end:
391 1162 : free_w(&extrafile);
392 1162 : return ret;
393 : }
394 :
395 : static void conf_problem(const char *conf_path, const char *msg, int *r)
396 : {
397 6 : logp("%s: %s\n", conf_path, msg);
398 6 : (*r)--;
399 : }
400 :
401 : #ifdef HAVE_IPV6
402 : // These should work for IPv4 connections too.
403 : #define DEFAULT_ADDRESS_MAIN "::"
404 : #define DEFAULT_ADDRESS_STATUS "::1"
405 : #else
406 : // Fall back to IPv4 address if IPv6 is not compiled in.
407 : #define DEFAULT_ADDRESS_MAIN "0.0.0.0"
408 : #define DEFAULT_ADDRESS_STATUS "127.0.0.1"
409 : #endif
410 :
411 39 : static int server_conf_checks(struct conf **c, const char *path, int *r)
412 : {
413 : // FIX THIS: Most of this could be done by flags.
414 39 : if(!get_string(c[OPT_ADDRESS])
415 39 : && set_string(c[OPT_ADDRESS], DEFAULT_ADDRESS_MAIN))
416 : return -1;
417 39 : if(!get_string(c[OPT_DIRECTORY]))
418 : conf_problem(path, "directory unset", r);
419 39 : if(!get_string(c[OPT_DEDUP_GROUP]))
420 : conf_problem(path, "dedup_group unset", r);
421 39 : if(!get_string(c[OPT_CLIENTCONFDIR]))
422 : conf_problem(path, "clientconfdir unset", r);
423 39 : if(get_e_recovery_method(c[OPT_WORKING_DIR_RECOVERY_METHOD])==RECOVERY_METHOD_UNSET)
424 : conf_problem(path, "working_dir_recovery_method unset", r);
425 39 : if(!get_string(c[OPT_SSL_DHFILE]))
426 : conf_problem(path, "ssl_dhfile unset", r);
427 39 : if(get_string(c[OPT_ENCRYPTION_PASSWORD]))
428 : conf_problem(path,
429 : "encryption_password should not be set on the server!", r);
430 39 : if(!get_string(c[OPT_STATUS_ADDRESS])
431 39 : && set_string(c[OPT_STATUS_ADDRESS], DEFAULT_ADDRESS_STATUS))
432 : return -1;
433 39 : if(!get_string(c[OPT_STATUS_PORT])) // carry on if not set.
434 0 : logp("%s: status_port unset", path);
435 39 : if(!get_int(c[OPT_MAX_CHILDREN]))
436 : conf_problem(path, "max_children unset", r);
437 39 : if(!get_int(c[OPT_MAX_STATUS_CHILDREN]))
438 : conf_problem(path, "max_status_children unset", r);
439 39 : if(!get_strlist(c[OPT_KEEP]))
440 : conf_problem(path, "keep unset", r);
441 39 : if(get_int(c[OPT_MAX_HARDLINKS])<2)
442 : conf_problem(path, "max_hardlinks too low", r);
443 39 : if(get_int(c[OPT_MAX_CHILDREN])<=0)
444 : conf_problem(path, "max_children too low", r);
445 39 : if(get_int(c[OPT_MAX_STATUS_CHILDREN])<=0)
446 : conf_problem(path, "max_status_children too low", r);
447 39 : if(get_int(c[OPT_MAX_STORAGE_SUBDIRS])<=1000)
448 : conf_problem(path, "max_storage_subdirs too low", r);
449 39 : if(!get_string(c[OPT_TIMESTAMP_FORMAT])
450 39 : && set_string(c[OPT_TIMESTAMP_FORMAT], DEFAULT_TIMESTAMP_FORMAT))
451 : return -1;
452 39 : if(get_string(c[OPT_CA_CONF]))
453 : {
454 1 : int ca_err=0;
455 1 : if(!get_string(c[OPT_CA_NAME]))
456 : {
457 0 : logp("ca_conf set, but ca_name not set\n");
458 0 : ca_err++;
459 : }
460 1 : if(!get_string(c[OPT_CA_SERVER_NAME]))
461 : {
462 0 : logp("ca_conf set, but ca_server_name not set\n");
463 0 : ca_err++;
464 : }
465 1 : if(!get_string(c[OPT_CA_BURP_CA]))
466 : {
467 0 : logp("ca_conf set, but ca_burp_ca not set\n");
468 0 : ca_err++;
469 : }
470 1 : if(!get_string(c[OPT_SSL_DHFILE]))
471 : {
472 0 : logp("ca_conf set, but ssl_dhfile not set\n");
473 0 : ca_err++;
474 : }
475 1 : if(!get_string(c[OPT_SSL_CERT_CA]))
476 : {
477 0 : logp("ca_conf set, but ssl_cert_ca not set\n");
478 0 : ca_err++;
479 : }
480 1 : if(!get_string(c[OPT_SSL_CERT]))
481 : {
482 0 : logp("ca_conf set, but ssl_cert not set\n");
483 0 : ca_err++;
484 : }
485 1 : if(!get_string(c[OPT_SSL_KEY]))
486 : {
487 0 : logp("ca_conf set, but ssl_key not set\n");
488 0 : ca_err++;
489 : }
490 1 : if(ca_err) return -1;
491 : }
492 39 : if(get_string(c[OPT_MANUAL_DELETE]))
493 : {
494 0 : if(!is_absolute(get_string(c[OPT_MANUAL_DELETE])))
495 : {
496 0 : logp("ERROR: Please use an absolute manual_delete path.\n");
497 0 : return -1;
498 : }
499 : }
500 :
501 : return 0;
502 : }
503 :
504 : #ifdef HAVE_WIN32
505 : #undef X509_NAME
506 : #include <openssl/x509.h>
507 : #endif
508 :
509 0 : static char *extract_cn(X509_NAME *subj)
510 : {
511 : int nid;
512 : int index;
513 : ASN1_STRING *d;
514 : X509_NAME_ENTRY *e;
515 :
516 0 : nid=OBJ_txt2nid("CN");
517 0 : if((index=X509_NAME_get_index_by_NID(subj, nid, -1))<0
518 0 : || !(e=X509_NAME_get_entry(subj, index))
519 0 : || !(d=X509_NAME_ENTRY_get_data(e)))
520 : return NULL;
521 : #if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
522 0 : return (char *)ASN1_STRING_data(d);
523 : #else
524 : return (char *)ASN1_STRING_get0_data(d);
525 : #endif
526 : }
527 :
528 45 : static void mangle_cname(char **cname, struct conf **c)
529 : {
530 45 : if(!get_int(c[OPT_CNAME_FQDN]))
531 0 : strip_fqdn(cname);
532 45 : if(get_int(c[OPT_CNAME_LOWERCASE]))
533 0 : strlwr(*cname);
534 45 : }
535 :
536 45 : static int get_cname_from_ssl_cert(struct conf **c)
537 : {
538 45 : int ret=-1;
539 45 : struct fzp *fzp=NULL;
540 45 : X509 *cert=NULL;
541 45 : X509_NAME *subj=NULL;
542 45 : char *path=get_string(c[OPT_SSL_CERT]);
543 45 : const char *cn=NULL;
544 45 : char *copy=NULL;
545 :
546 45 : if(!path || !(fzp=fzp_open(path, "rb"))) return 0;
547 :
548 0 : if(!(cert=fzp_PEM_read_X509(fzp)))
549 : {
550 0 : logp("unable to parse %s in: %s\n", path, __func__);
551 0 : goto end;
552 : }
553 0 : if(!(subj=X509_get_subject_name(cert)))
554 : {
555 0 : logp("unable to get subject from %s in: %s\n", path, __func__);
556 0 : goto end;
557 : }
558 :
559 0 : if(!(cn=extract_cn(subj)))
560 : {
561 0 : logp("could not get CN from %s\n", path);
562 0 : goto end;
563 : }
564 0 : if(!(copy=strdup_w(cn, __func__)))
565 : goto end;
566 0 : mangle_cname(©, c);
567 0 : if(set_string(c[OPT_CNAME], copy))
568 : goto end;
569 0 : logp("cname from cert: %s\n", cn);
570 0 : if(strcmp(copy, cn))
571 0 : logp("cname mangled to: %s\n", copy);
572 :
573 : ret=0;
574 : end:
575 0 : if(cert) X509_free(cert);
576 0 : fzp_close(&fzp);
577 0 : free_w(©);
578 0 : return ret;
579 : }
580 :
581 : #ifdef HAVE_WIN32
582 : #include <winsock2.h>
583 : #include <ws2tcpip.h>
584 : #endif
585 :
586 45 : static int get_fqdn(struct conf **c)
587 : {
588 45 : int ret=-1;
589 : int gai_result;
590 : struct addrinfo hints;
591 45 : struct addrinfo *info=NULL;
592 45 : char hostname[1024]="";
593 45 : char *fqdn=NULL;
594 45 : hostname[1023] = '\0';
595 45 : if(gethostname(hostname, 1023))
596 : {
597 0 : logp("gethostname() failed: %s\n", strerror(errno));
598 0 : goto end;
599 : }
600 :
601 : memset(&hints, 0, sizeof hints);
602 : hints.ai_family=AF_UNSPEC;
603 45 : hints.ai_socktype=SOCK_STREAM;
604 45 : hints.ai_flags=AI_CANONNAME;
605 :
606 45 : if((gai_result=getaddrinfo(hostname, NULL, &hints, &info)))
607 : {
608 0 : logp("getaddrinfo in %s: %s\n", __func__,
609 : gai_strerror(gai_result));
610 0 : goto end;
611 : }
612 :
613 : //for(p=info; p; p=p->ai_next)
614 : // Just use the first one.
615 45 : if(!info)
616 : {
617 0 : logp("Got no hostname in %s\n", __func__);
618 0 : goto end;
619 : }
620 :
621 45 : if(!(fqdn=strdup_w(info->ai_canonname, __func__)))
622 : goto end;
623 45 : mangle_cname(&fqdn, c);
624 :
625 45 : if(set_string(c[OPT_CNAME], fqdn))
626 : goto end;
627 45 : logp("cname from hostname: %s\n", get_string(c[OPT_CNAME]));
628 :
629 45 : ret=0;
630 : end:
631 45 : if(info) freeaddrinfo(info);
632 45 : free_w(&fqdn);
633 45 : return ret;
634 : }
635 :
636 84 : const char *confs_get_lockfile(struct conf **confs)
637 : {
638 84 : const char *lockfile=get_string(confs[OPT_LOCKFILE]);
639 84 : if(!lockfile) lockfile=get_string(confs[OPT_PIDFILE]);
640 84 : return lockfile;
641 : }
642 :
643 84 : static int general_conf_checks(struct conf **c, const char *path, int *r)
644 : {
645 84 : if(!confs_get_lockfile(c))
646 : conf_problem(path, "lockfile unset", r);
647 84 : if(!get_string(c[OPT_SSL_CERT]))
648 : conf_problem(path, "ssl_cert unset", r);
649 84 : if(!get_string(c[OPT_SSL_CERT_CA]))
650 : conf_problem(path, "ssl_cert_ca unset", r);
651 84 : return 0;
652 : }
653 :
654 45 : static int client_conf_checks(struct conf **c, const char *path, int *r)
655 : {
656 45 : const char *autoupgrade_os=get_string(c[OPT_AUTOUPGRADE_OS]);
657 45 : if(!get_string(c[OPT_CNAME]))
658 : {
659 45 : if(get_cname_from_ssl_cert(c)) return -1;
660 : // There was no error. This is probably a new install.
661 : // Try getting the fqdn and using that.
662 45 : if(!get_string(c[OPT_CNAME]))
663 : {
664 45 : if(get_fqdn(c)) return -1;
665 45 : if(!get_string(c[OPT_CNAME]))
666 : conf_problem(path, "client name unset", r);
667 : }
668 : }
669 45 : if(!get_string(c[OPT_PASSWORD]))
670 : {
671 45 : logp("password not set, falling back to \"password\"\n");
672 45 : if(set_string(c[OPT_PASSWORD], "password"))
673 : return -1;
674 : }
675 45 : if(!get_string(c[OPT_SERVER]))
676 : conf_problem(path, "server unset", r);
677 45 : if(!get_string(c[OPT_STATUS_PORT])) // carry on if not set.
678 0 : logp("%s: status_port unset\n", path);
679 45 : if(!get_string(c[OPT_SSL_PEER_CN]))
680 : {
681 1 : const char *server=get_string(c[OPT_SERVER]);
682 1 : logp("ssl_peer_cn unset\n");
683 1 : if(!server)
684 : {
685 0 : logp("falling back to '%s'\n", server);
686 0 : if(set_string(c[OPT_SSL_PEER_CN], server))
687 : return -1;
688 : }
689 : }
690 45 : if(autoupgrade_os
691 0 : && strstr(autoupgrade_os, ".."))
692 : conf_problem(path,
693 : "autoupgrade_os must not contain a '..' component", r);
694 45 : if(get_string(c[OPT_CA_BURP_CA]))
695 : {
696 1 : if(!get_string(c[OPT_CA_CSR_DIR]))
697 : conf_problem(path,
698 : "ca_burp_ca set, but ca_csr_dir not set\n", r);
699 1 : if(!get_string(c[OPT_SSL_CERT_CA]))
700 : conf_problem(path,
701 : "ca_burp_ca set, but ssl_cert_ca not set\n", r);
702 1 : if(!get_string(c[OPT_SSL_CERT]))
703 : conf_problem(path,
704 : "ca_burp_ca set, but ssl_cert not set\n", r);
705 1 : if(!get_string(c[OPT_SSL_KEY]))
706 : conf_problem(path,
707 : "ca_burp_ca set, but ssl_key not set\n", r);
708 : }
709 :
710 45 : if(!r)
711 : {
712 : struct strlist *l;
713 0 : logp("Listing configured paths:\n");
714 0 : for(l=get_strlist(c[OPT_INCEXCDIR]); l; l=l->next)
715 0 : logp("%s: %s\n", l->flag?"include":"exclude", l->path);
716 0 : logp("Listing starting paths:\n");
717 0 : for(l=get_strlist(c[OPT_STARTDIR]); l; l=l->next)
718 0 : if(l->flag) logp("%s\n", l->path);
719 : }
720 : return 0;
721 : }
722 :
723 142 : static int finalise_keep_args(struct conf **c)
724 : {
725 : struct strlist *k;
726 142 : struct strlist *last=NULL;
727 142 : uint64_t mult=1;
728 227 : for(k=get_strlist(c[OPT_KEEP]); k; k=k->next)
729 : {
730 170 : if(!(k->flag=atoi(k->path)))
731 : {
732 0 : logp("'keep' value cannot be set to '%s'\n", k->path);
733 0 : return -1;
734 : }
735 85 : mult*=k->flag;
736 :
737 : // An error if you try to keep backups every second
738 : // for 100 years.
739 85 : if(mult>52560000)
740 : {
741 0 : logp("Your 'keep' values are far too high. High enough to keep a backup every second for 10 years. Please lower them to something sensible.\n");
742 0 : return -1;
743 : }
744 85 : last=k;
745 : }
746 : // If more than one keep value is set, add one to the last one.
747 : // This is so that, for example, having set 7, 4, 6, then
748 : // a backup of age 7*4*6=168 or more is guaranteed to be kept.
749 : // Otherwise, only 7*4*5=140 would be guaranteed to be kept.
750 142 : k=get_strlist(c[OPT_KEEP]);
751 142 : if(k && k->next) last->flag++;
752 : return 0;
753 : }
754 :
755 44 : static int incexc_munge(struct conf **c, struct strlist *s)
756 : {
757 : #ifdef HAVE_WIN32
758 : convert_backslashes(&s->path);
759 : #endif
760 44 : if(!is_absolute(s->path))
761 : {
762 1 : logp("ERROR: Please use absolute include/exclude paths.\n");
763 : return -1;
764 : }
765 43 : if(add_to_strlist(c[OPT_INCEXCDIR], s->path, s->flag))
766 : return -1;
767 : return 0;
768 : }
769 :
770 146 : static int finalise_incexc_dirs(struct conf **c)
771 : {
772 146 : struct strlist *s=NULL;
773 :
774 184 : for(s=get_strlist(c[OPT_INCLUDE]); s; s=s->next)
775 39 : if(incexc_munge(c, s)) return -1;
776 150 : for(s=get_strlist(c[OPT_EXCLUDE]); s; s=s->next)
777 5 : if(incexc_munge(c, s)) return -1;
778 : return 0;
779 : }
780 :
781 6 : static int add_to_cross_filesystem(struct conf **c, const char *path)
782 : {
783 6 : if(strlist_find(get_strlist(c[OPT_FSCHGDIR]), path, 0))
784 : return 0;
785 6 : return add_to_strlist(c[OPT_FSCHGDIR], path, 0);
786 : }
787 :
788 : // This decides which directories to start backing up, and which
789 : // are subdirectories which don't need to be started separately.
790 145 : static int finalise_start_dirs(struct conf **c)
791 : {
792 145 : struct strlist *s=NULL;
793 145 : struct strlist *last_ie=NULL;
794 145 : struct strlist *last_sd=NULL;
795 :
796 : // Make sure that the startdir list starts empty, or chaos will ensue.
797 145 : conf_free_content(c[OPT_STARTDIR]);
798 :
799 182 : for(s=get_strlist(c[OPT_INCLUDE]); s; s=s->next)
800 : {
801 : #ifdef HAVE_WIN32
802 : convert_backslashes(&s->path);
803 : #endif
804 38 : if(!is_absolute(s->path))
805 : {
806 0 : logp("ERROR: Please use absolute include/exclude paths.\n");
807 0 : return -1;
808 : }
809 :
810 : // Ensure that we do not backup the same directory twice.
811 38 : if(last_ie && !strcmp(s->path, last_ie->path))
812 : {
813 1 : logp("Directory appears twice in conf: %s\n",
814 : s->path);
815 1 : return -1;
816 : }
817 : // If it is not a subdirectory of the most recent start point,
818 : // we have found another start point.
819 37 : if(!get_strlist(c[OPT_STARTDIR])
820 14 : || !last_sd || !is_subdir(last_sd->path, s->path))
821 : {
822 : // Do not use strlist_add_sorted, because last_sd is
823 : // relying on incexcdir already being sorted.
824 31 : if(add_to_strlist(c[OPT_STARTDIR], s->path, s->flag))
825 : return -1;
826 : last_sd=s;
827 : }
828 : else
829 : {
830 : // If it is not a starting directory, it should at
831 : // least be included as a cross_filesystem entry.
832 6 : if(add_to_cross_filesystem(c, s->path))
833 : return -1;
834 : }
835 37 : last_ie=s;
836 : }
837 : return 0;
838 : }
839 :
840 : // The glob stuff should only run on the client side.
841 49 : static int finalise_glob(struct conf **c)
842 : {
843 49 : int ret=-1;
844 : #ifdef HAVE_WIN32
845 : if(glob_windows(c)) goto end;
846 : #else
847 : int i;
848 : glob_t globbuf;
849 : struct strlist *l;
850 49 : struct strlist *last=NULL;
851 : memset(&globbuf, 0, sizeof(globbuf));
852 52 : for(l=get_strlist(c[OPT_INCGLOB]); l; l=l->next)
853 : {
854 3 : glob(l->path, last?GLOB_APPEND:0, NULL, &globbuf);
855 3 : last=l;
856 : }
857 :
858 3 : for(i=0; (unsigned int)i<globbuf.gl_pathc; i++)
859 3 : if(add_to_strlist_include_uniq(c[OPT_INCLUDE], globbuf.gl_pathv[i]))
860 : goto end;
861 :
862 49 : globfree(&globbuf);
863 : #endif
864 49 : ret=0;
865 : end:
866 49 : return ret;
867 : }
868 :
869 : // Reeval the glob after script pre
870 2 : int reeval_glob(struct conf **c)
871 : {
872 2 : if(finalise_glob(c))
873 : return -1;
874 :
875 2 : if(finalise_incexc_dirs(c)
876 2 : || finalise_start_dirs(c)) return -1;
877 :
878 : return 0;
879 : }
880 :
881 : // Set the flag of the first item in a list that looks at extensions to the
882 : // maximum number of characters that need to be checked, plus one. This is for
883 : // a bit of added efficiency.
884 432 : static void set_max_ext(struct strlist *list)
885 : {
886 432 : int max=0;
887 432 : struct strlist *l=NULL;
888 436 : for(l=list; l; l=l->next)
889 : {
890 4 : int s=strlen(l->path);
891 4 : if(s>max) max=s;
892 : }
893 432 : if(list) list->flag=max+1;
894 432 : }
895 :
896 288 : static int finalise_fstypes(struct conf **c, int opt)
897 : {
898 : struct strlist *l;
899 : // Set the strlist flag for the excluded fstypes
900 288 : for(l=get_strlist(c[opt]); l; l=l->next)
901 : {
902 0 : l->flag=0;
903 0 : if(!strncasecmp(l->path, "0x", 2))
904 : {
905 0 : l->flag=strtol((l->path)+2, NULL, 16);
906 0 : logp("Excluding file system type 0x%08lX\n", l->flag);
907 : }
908 : else
909 : {
910 0 : if(fstype_to_flag(l->path, &(l->flag)))
911 : {
912 0 : logp("Unknown exclude fs type: %s\n", l->path);
913 0 : l->flag=0;
914 : }
915 : }
916 : }
917 288 : return 0;
918 : }
919 :
920 10 : static int setup_script_arg_override(struct conf *c, struct conf *args)
921 : {
922 : struct strlist *s;
923 10 : set_strlist(args, NULL);
924 30 : for(s=get_strlist(c); s; s=s->next)
925 20 : if(add_to_strlist(args, s->path, s->flag))
926 : return -1;
927 : return 0;
928 : }
929 :
930 426 : static int setup_script_arg_overrides(struct conf *c,
931 : struct conf *pre_args, struct conf *post_args)
932 : {
933 426 : if(!get_strlist(c)) return 0;
934 10 : return setup_script_arg_override(c, pre_args)
935 5 : || setup_script_arg_override(c, post_args);
936 : }
937 :
938 : #ifndef UTEST
939 : static
940 : #endif
941 144 : int conf_finalise(struct conf **c)
942 : {
943 144 : int s_script_notify=0;
944 144 : if(finalise_fstypes(c, OPT_EXCFS)) return -1;
945 144 : if(finalise_fstypes(c, OPT_INCFS)) return -1;
946 :
947 144 : strlist_compile_regexes(get_strlist(c[OPT_INCREG]));
948 144 : strlist_compile_regexes(get_strlist(c[OPT_EXCREG]));
949 :
950 144 : set_max_ext(get_strlist(c[OPT_INCEXT]));
951 144 : set_max_ext(get_strlist(c[OPT_EXCEXT]));
952 144 : set_max_ext(get_strlist(c[OPT_EXCOM]));
953 :
954 144 : if(get_e_burp_mode(c[OPT_BURP_MODE])==BURP_MODE_CLIENT
955 47 : && finalise_glob(c)) return -1;
956 :
957 144 : if(finalise_incexc_dirs(c)
958 143 : || finalise_start_dirs(c)) return -1;
959 :
960 142 : if(finalise_keep_args(c)) return -1;
961 :
962 142 : if((s_script_notify=get_int(c[OPT_S_SCRIPT_NOTIFY])))
963 : {
964 4 : set_int(c[OPT_S_SCRIPT_PRE_NOTIFY], s_script_notify);
965 4 : set_int(c[OPT_S_SCRIPT_POST_NOTIFY], s_script_notify);
966 : }
967 :
968 : // These override the specific pre/post script paths with the general
969 : // one. For example, if 'server_script' is set, its value is used for
970 : // 'server_script_pre' and 'server_script_post'.
971 142 : if(pre_post_override(c[OPT_B_SCRIPT],
972 : c[OPT_B_SCRIPT_PRE], c[OPT_B_SCRIPT_POST])
973 142 : || pre_post_override(c[OPT_R_SCRIPT],
974 : c[OPT_R_SCRIPT_PRE], c[OPT_R_SCRIPT_POST])
975 142 : || pre_post_override(c[OPT_S_SCRIPT],
976 : c[OPT_S_SCRIPT_PRE], c[OPT_S_SCRIPT_POST])
977 : // And these do the same for the script arguments.
978 142 : || setup_script_arg_overrides(c[OPT_B_SCRIPT_ARG],
979 : c[OPT_B_SCRIPT_PRE_ARG], c[OPT_B_SCRIPT_POST_ARG])
980 142 : || setup_script_arg_overrides(c[OPT_R_SCRIPT_ARG],
981 : c[OPT_R_SCRIPT_PRE_ARG], c[OPT_R_SCRIPT_POST_ARG])
982 142 : || setup_script_arg_overrides(c[OPT_S_SCRIPT_ARG],
983 : c[OPT_S_SCRIPT_PRE_ARG], c[OPT_S_SCRIPT_POST_ARG]))
984 : return -1;
985 :
986 : // We are now done with these. Clear them, otherwise they interfere.
987 142 : set_string(c[OPT_S_SCRIPT], NULL);
988 142 : set_strlist(c[OPT_S_SCRIPT_ARG], NULL);
989 142 : return 0;
990 : }
991 :
992 84 : static int conf_finalise_global_only(const char *conf_path, struct conf **confs)
993 : {
994 84 : int r=0;
995 :
996 84 : if(!get_string(confs[OPT_PORT]))
997 : conf_problem(conf_path, "port unset", &r);
998 :
999 : // Let the caller check the 'keep' value.
1000 :
1001 84 : if(!get_string(confs[OPT_SSL_KEY_PASSWORD])
1002 84 : && set_string(confs[OPT_SSL_KEY_PASSWORD], ""))
1003 0 : r--;
1004 :
1005 84 : if(general_conf_checks(confs, conf_path, &r)) r--;
1006 :
1007 84 : switch(get_e_burp_mode(confs[OPT_BURP_MODE]))
1008 : {
1009 : case BURP_MODE_SERVER:
1010 39 : if(server_conf_checks(confs, conf_path, &r)) r--;
1011 : break;
1012 : case BURP_MODE_CLIENT:
1013 45 : if(client_conf_checks(confs, conf_path, &r)) r--;
1014 : break;
1015 : case BURP_MODE_UNSET:
1016 : default:
1017 0 : logp("%s: mode unset - need 'server' or 'client'\n",
1018 : conf_path);
1019 0 : r--;
1020 0 : break;
1021 : }
1022 :
1023 84 : return r;
1024 : }
1025 :
1026 149 : static int conf_load_lines_from_file(const char *conf_path, struct conf **confs)
1027 : {
1028 149 : int ret=0;
1029 149 : int line=0;
1030 149 : FILE *fp=NULL;
1031 149 : char buf[4096]="";
1032 :
1033 149 : if(!(fp=fopen(conf_path, "r")))
1034 : {
1035 7 : logp("could not open '%s' for reading.\n", conf_path);
1036 7 : return -1;
1037 : }
1038 1296 : while(fgets(buf, sizeof(buf), fp))
1039 : {
1040 1154 : line++;
1041 1154 : if(conf_parse_line(confs, conf_path, buf, line))
1042 : {
1043 : conf_error(conf_path, line);
1044 1 : ret=-1;
1045 : }
1046 : }
1047 142 : if(fp) fclose(fp);
1048 142 : return ret;
1049 : }
1050 :
1051 : #ifndef UTEST
1052 : static
1053 : #endif
1054 3 : int conf_load_lines_from_buf(const char *buf, struct conf **c)
1055 : {
1056 3 : int ret=0;
1057 3 : int line=0;
1058 3 : char *tok=NULL;
1059 3 : char *copy=NULL;
1060 :
1061 3 : if(!buf) return 0;
1062 :
1063 3 : if(!(copy=strdup_w(buf, __func__))) return -1;
1064 3 : if(!(tok=strtok(copy, "\n")))
1065 : {
1066 0 : logp("unable to parse conf buffer\n");
1067 0 : free_w(©);
1068 0 : return -1;
1069 : }
1070 : do
1071 : {
1072 8 : line++;
1073 8 : if(conf_parse_line(c, "", tok, line))
1074 : {
1075 : ret=-1;
1076 : break;
1077 : }
1078 8 : } while((tok=strtok(NULL, "\n")));
1079 3 : free_w(©);
1080 :
1081 3 : return ret;
1082 : }
1083 :
1084 : /* The server runs this when parsing a restore file on the server. */
1085 10 : int conf_parse_incexcs_path(struct conf **c, const char *path)
1086 : {
1087 10 : free_incexcs(c);
1088 10 : if(conf_load_lines_from_file(path, c)
1089 6 : || conf_finalise(c))
1090 : return -1;
1091 : return 0;
1092 : }
1093 :
1094 : /* The client runs this when the server overrides the incexcs. */
1095 3 : int conf_parse_incexcs_buf(struct conf **c, const char *incexc)
1096 : {
1097 3 : free_incexcs(c);
1098 3 : if(conf_load_lines_from_buf(incexc, c)
1099 3 : || conf_finalise(c))
1100 : return -1;
1101 : return 0;
1102 : }
1103 :
1104 53 : static int conf_set_from_global(struct conf **globalc, struct conf **cc)
1105 : {
1106 53 : int i=0;
1107 8533 : for(i=0; i<OPT_MAX; i++)
1108 : {
1109 8480 : if(!(cc[i]->flags & CONF_FLAG_CC_OVERRIDE))
1110 5565 : continue;
1111 2915 : switch(cc[i]->conf_type)
1112 : {
1113 : case CT_STRING:
1114 742 : set_string(cc[i], get_string(globalc[i]));
1115 742 : break;
1116 : case CT_UINT:
1117 1431 : set_int(cc[i], get_int(globalc[i]));
1118 1431 : break;
1119 : case CT_FLOAT:
1120 0 : set_float(cc[i], get_float(globalc[i]));
1121 0 : break;
1122 : case CT_MODE_T:
1123 0 : set_mode_t(cc[i], get_mode_t(globalc[i]));
1124 0 : break;
1125 : case CT_SSIZE_T:
1126 106 : set_uint64_t(cc[i], get_uint64_t(globalc[i]));
1127 106 : break;
1128 : case CT_E_BURP_MODE:
1129 0 : set_e_burp_mode(cc[i], get_e_burp_mode(globalc[i]));
1130 0 : break;
1131 : case CT_E_PROTOCOL:
1132 53 : set_e_protocol(cc[i], get_e_protocol(globalc[i]));
1133 53 : break;
1134 : case CT_E_RECOVERY_METHOD:
1135 53 : set_e_recovery_method(cc[i], get_e_recovery_method(globalc[i]));
1136 53 : break;
1137 : case CT_E_RSHASH:
1138 53 : set_e_rshash(cc[i], get_e_rshash(globalc[i]));
1139 53 : break;
1140 : case CT_STRLIST:
1141 : // Done later.
1142 : break;
1143 : case CT_CNTR:
1144 : break;
1145 : // No default so that there are warnings if anything
1146 : // was missed.
1147 : }
1148 : }
1149 :
1150 : // If ssl_peer_cn is not set, default it to the client name.
1151 53 : if(!get_string(globalc[OPT_SSL_PEER_CN])
1152 42 : && set_string(cc[OPT_SSL_PEER_CN], get_string(cc[OPT_CNAME])))
1153 : return -1;
1154 :
1155 : return 0;
1156 : }
1157 :
1158 472 : static int append_strlist(struct conf *dst, struct conf *src)
1159 : {
1160 : struct strlist *s;
1161 539 : for(s=get_strlist(src); s; s=s->next)
1162 67 : if(add_to_strlist(dst, s->path, s->flag))
1163 : return -1;
1164 : return 0;
1165 : }
1166 :
1167 : // Instead of adding onto the end of the list, this replaces the list.
1168 49 : static int conf_set_from_global_arg_list_overrides(struct conf **globalc,
1169 : struct conf **cc)
1170 : {
1171 49 : int i=0;
1172 7889 : for(i=0; i<OPT_MAX; i++)
1173 : {
1174 7840 : if(cc[i]->conf_type!=CT_STRLIST) continue;
1175 1519 : if(!(cc[i]->flags & CONF_FLAG_CC_OVERRIDE)) continue;
1176 441 : if(cc[i]->flags & CONF_FLAG_STRLIST_REPLACE)
1177 : {
1178 : // If there was no cc[i] strlist set, use the global.
1179 392 : if(!get_strlist(cc[i])
1180 374 : && append_strlist(cc[i], globalc[i]))
1181 : return -1;
1182 : }
1183 : else
1184 : {
1185 : struct conf tmpconf;
1186 : // A bit painful.
1187 49 : tmpconf.conf_type=cc[i]->conf_type;
1188 49 : tmpconf.flags=cc[i]->flags;
1189 : memset(&tmpconf.data, 0, sizeof(tmpconf.data));
1190 49 : if(append_strlist(&tmpconf, globalc[i])
1191 49 : || append_strlist(&tmpconf, cc[i]))
1192 0 : return -1;
1193 49 : set_strlist(cc[i], get_strlist(&tmpconf));
1194 : }
1195 : }
1196 : return 0;
1197 : }
1198 :
1199 34 : static int conf_init_save_cname_and_version(struct conf **cconfs)
1200 : {
1201 34 : int ret=-1;
1202 34 : char *cname=NULL;
1203 34 : char *cversion=NULL;
1204 34 : char *orig_cname=get_string(cconfs[OPT_CNAME]);
1205 34 : char *orig_cversion=get_string(cconfs[OPT_PEER_VERSION]);
1206 :
1207 34 : if((orig_cname && !(cname=strdup_w(orig_cname, __func__)))
1208 34 : || (orig_cversion
1209 10 : && !(cversion=strdup_w(orig_cversion, __func__))))
1210 : goto end;
1211 :
1212 34 : set_string(cconfs[OPT_CNAME], NULL);
1213 34 : set_string(cconfs[OPT_PEER_VERSION], NULL);
1214 34 : if(confs_init(cconfs)) goto end;
1215 34 : set_string(cconfs[OPT_CNAME], cname);
1216 34 : set_string(cconfs[OPT_PEER_VERSION], cversion);
1217 34 : ret=0;
1218 : end:
1219 34 : free_w(&cname);
1220 34 : free_w(&cversion);
1221 34 : return ret;
1222 : }
1223 :
1224 53 : static int do_conf_load_overrides(struct conf **globalcs, struct conf **cconfs,
1225 : const char *path, const char *buf)
1226 : {
1227 : // Some client settings can be globally set in the server conf and
1228 : // overridden in the client specific conf.
1229 53 : if(conf_set_from_global(globalcs, cconfs)) return -1;
1230 53 : if(buf) { if(conf_load_lines_from_buf(buf, cconfs)) return -1; }
1231 53 : else { if(conf_load_lines_from_file(path, cconfs)) return -1; }
1232 49 : if(conf_set_from_global_arg_list_overrides(globalcs, cconfs)
1233 49 : || conf_finalise(cconfs))
1234 : return -1;
1235 : return 0;
1236 : }
1237 :
1238 : #ifndef UTEST
1239 : static
1240 : #endif
1241 19 : int conf_load_overrides(struct conf **globalcs, struct conf **cconfs,
1242 : const char *path)
1243 : {
1244 53 : return do_conf_load_overrides(globalcs, cconfs, path, NULL);
1245 : }
1246 :
1247 34 : int conf_load_clientconfdir(struct conf **globalcs, struct conf **cconfs)
1248 : {
1249 34 : int ret=-1;
1250 34 : char *path=NULL;
1251 34 : const char *cname=NULL;
1252 :
1253 34 : if(conf_init_save_cname_and_version(cconfs)) goto end;
1254 34 : cname=get_string(cconfs[OPT_CNAME]);
1255 34 : if(looks_like_tmp_or_hidden_file(cname))
1256 : {
1257 0 : logp("client name '%s' is invalid\n", cname);
1258 0 : goto end;
1259 : }
1260 :
1261 34 : if(!(path=prepend_s(get_string(globalcs[OPT_CLIENTCONFDIR]), cname)))
1262 : goto end;
1263 68 : ret=conf_load_overrides(globalcs, cconfs, path);
1264 : end:
1265 34 : free_w(&path);
1266 34 : return ret;
1267 : }
1268 :
1269 86 : static int do_load_global_only(struct conf **globalcs,
1270 : const char *path, const char *buf)
1271 : {
1272 86 : if(set_string(globalcs[OPT_CONFFILE], path)) return -1;
1273 86 : if(buf) { if(conf_load_lines_from_buf(buf, globalcs)) return -1; }
1274 86 : else { if(conf_load_lines_from_file(path, globalcs)) return -1; }
1275 86 : if(conf_finalise(globalcs)
1276 84 : || conf_finalise_global_only(path, globalcs))
1277 : return -1;
1278 : return 0;
1279 :
1280 : }
1281 :
1282 86 : int conf_load_global_only(const char *path, struct conf **globalcs)
1283 : {
1284 86 : return do_load_global_only(globalcs, path, NULL);
1285 : }
1286 :
1287 4 : static int restore_client_allowed(struct conf **cconfs, struct conf **sconfs)
1288 : {
1289 : struct strlist *r;
1290 7 : for(r=get_strlist(sconfs[OPT_RESTORE_CLIENTS]); r; r=r->next)
1291 6 : if(!strcmp(r->path, get_string(cconfs[OPT_CNAME])))
1292 : return 1;
1293 1 : logp("Access to client is not allowed: %s\n",
1294 : get_string(sconfs[OPT_CNAME]));
1295 1 : return 0;
1296 : }
1297 :
1298 : // FIX THIS: need to unit test this.
1299 5 : int conf_switch_to_orig_client(struct conf **globalcs,
1300 : struct conf **cconfs, const char *orig_client)
1301 : {
1302 5 : int ret=-1;
1303 5 : struct conf **sconfs=NULL;
1304 5 : if(!(sconfs=confs_alloc())
1305 5 : || confs_init(sconfs)) goto end;
1306 5 : if(set_string(sconfs[OPT_CNAME], orig_client))
1307 : goto end;
1308 5 : logp("Client wants to switch to client: %s\n",
1309 5 : get_string(sconfs[OPT_CNAME]));
1310 :
1311 5 : if(conf_load_clientconfdir(globalcs, sconfs))
1312 : {
1313 1 : logp("Could not load alternate config: %s",
1314 1 : get_string(sconfs[OPT_CNAME]));
1315 1 : goto end;
1316 : }
1317 4 : set_int(sconfs[OPT_SEND_CLIENT_CNTR],
1318 4 : get_int(cconfs[OPT_SEND_CLIENT_CNTR]));
1319 :
1320 4 : if(!restore_client_allowed(cconfs, sconfs))
1321 : goto end;
1322 :
1323 3 : if(set_string(sconfs[OPT_RESTORE_PATH],
1324 3 : get_string(cconfs[OPT_RESTORE_PATH])))
1325 : goto end;
1326 3 : if(set_string(cconfs[OPT_RESTORE_PATH], NULL))
1327 : goto end;
1328 3 : set_cntr(sconfs[OPT_CNTR], get_cntr(cconfs));
1329 3 : set_cntr(cconfs[OPT_CNTR], NULL);
1330 3 : confs_free_content(cconfs);
1331 3 : confs_init(cconfs);
1332 3 : confs_memcpy(cconfs, sconfs);
1333 3 : confs_null(sconfs);
1334 3 : if(set_string(cconfs[OPT_RESTORE_CLIENT],
1335 3 : get_string(cconfs[OPT_CNAME]))) goto end;
1336 3 : if(set_string(cconfs[OPT_ORIG_CLIENT],
1337 3 : get_string(cconfs[OPT_CNAME]))) goto end;
1338 :
1339 3 : logp("Switched to client %s\n", get_string(cconfs[OPT_CNAME]));
1340 3 : ret=0;
1341 : end:
1342 5 : confs_free(&sconfs);
1343 5 : return ret;
1344 : }
1345 :
1346 25 : char *config_default_path(void)
1347 : {
1348 : static char path[256]="";
1349 : #ifdef HAVE_WIN32
1350 : char *pfenv=NULL;
1351 :
1352 : // Burp used to always install to 'C:/Program Files/Burp/', but as
1353 : // of 1.3.11, it changed to %PROGRAMFILES%. Still want the old way
1354 : // to work though. So check %PROGRAMFILES% first, then fall back.
1355 : if((pfenv=getenv("PROGRAMFILES")))
1356 : {
1357 : struct stat statp;
1358 : snprintf(path, sizeof(path), "%s/Burp/burp.conf", pfenv);
1359 : if(!lstat(path, &statp)
1360 : && !S_ISDIR(statp.st_mode))
1361 : return path;
1362 : }
1363 : snprintf(path, sizeof(path), "C:/Program Files/Burp/burp.conf");
1364 : #else
1365 : snprintf(path, sizeof(path), "%s", SYSCONFDIR "/burp.conf");
1366 : #endif
1367 25 : return path;
1368 : }
|