int reload(struct conf **confs, const char *conffile, bool firsttime) { if(!firsttime) logp("Reloading config\n"); if(confs_init(confs)) return -1; if(conf_load_global_only(conffile, confs)) return -1; umask(get_mode_t(confs[OPT_UMASK])); // This will turn on syslogging which could not be turned on before // conf_load. log_fzp_set(NULL, confs); #ifndef HAVE_WIN32 if(get_e_burp_mode(confs[OPT_BURP_MODE])==BURP_MODE_SERVER) setup_signals(); #endif // Do not try to change user or group after the first time. if(firsttime && chuser_and_or_chgrp( get_string(confs[OPT_USER]), get_string(confs[OPT_GROUP]))) return -1; return 0; }
static void run_find(const char *buf, FF_PKT *ff, struct conf **confs) { struct strlist *l; const char *conffile=CONFBASE "/burp.conf"; fail_unless(!recursive_delete(CONFBASE)); build_file(conffile, buf); fail_unless(!conf_load_global_only(conffile, confs)); for(l=get_strlist(confs[OPT_STARTDIR]); l; l=l->next) if(l->flag) fail_unless(!find_files_begin(NULL, ff, confs, l->path)); fail_unless(!recursive_delete(CONFBASE)); }
END_TEST static struct cstat *test_cstat_remove_setup(struct conf ***globalcs, const char *cnames[]) { struct cstat *clist=NULL; clean(); fail_unless((*globalcs=confs_alloc())!=NULL); fail_unless(!confs_init(*globalcs)); build_file(GLOBAL_CONF, MIN_SERVER_CONF); fail_unless(!conf_load_global_only(GLOBAL_CONF, *globalcs)); build_clientconfdir_files(cnames); fail_unless(!cstat_get_client_names(&clist, CLIENTCONFDIR)); assert_cstat_list(clist, cnames); return clist; }
END_TEST START_TEST(test_cstat_add_out_of_order) { struct cstat *clist=NULL; struct conf **globalcs; const char *cnames31204[] = {"cli3", "cli1", "cli2", "cli0", "cli4", NULL}; const char *cnames01234[] = {"cli0", "cli1", "cli2", "cli3", "cli4", NULL}; clean(); fail_unless((globalcs=confs_alloc())!=NULL); fail_unless(!confs_init(globalcs)); build_file(GLOBAL_CONF, MIN_SERVER_CONF); fail_unless(!conf_load_global_only(GLOBAL_CONF, globalcs)); build_clientconfdir_files(cnames31204); fail_unless(!cstat_get_client_names(&clist, CLIENTCONFDIR)); assert_cstat_list(clist, cnames01234); test_cstat_remove_teardown(&globalcs, &clist); }
static void run_test(int expected_ret, int slist_entries, enum protocol protocol, void setup_callback(struct asfd *asfd, struct slist *slist)) { int result; struct slist *slist=NULL; const char *conffile=BASE "/burp.conf"; struct asfd *asfd; struct conf **confs; const char *buf; if(protocol==PROTO_1) buf=MIN_CLIENT_CONF "protocol=1\n"; else buf=MIN_CLIENT_CONF "protocol=2\n"; base64_init(); asfd=asfd_mock_setup(&reads, &writes); confs=setup_conf(); fail_unless(recursive_delete(BASE)==0); build_file(conffile, buf); fail_unless(!conf_load_global_only(conffile, confs)); if(slist_entries) slist=build_slist_phase1(BASE, protocol, slist_entries); setup_callback(asfd, slist); result=do_restore_client(asfd, confs, ACTION_RESTORE, 0 /* vss_restore */); fail_unless(result==expected_ret); slist_free(&slist); tear_down(&asfd, &confs); }
int run_bedup(int argc, char *argv[]) { int i=1; int ret=0; int option=0; int nonburp=0; unsigned int maxlinks=DEF_MAX_LINKS; char *groups=NULL; char ext[16]=""; int givenconfigfile=0; const char *configfile=NULL; configfile=get_config_path(); snprintf(ext, sizeof(ext), ".bedup.%d", getpid()); while((option=getopt(argc, argv, "c:dg:hlm:nvV?"))!=-1) { switch(option) { case 'c': configfile=optarg; givenconfigfile=1; break; case 'd': deletedups=1; break; case 'g': groups=optarg; break; case 'l': makelinks=1; break; case 'm': maxlinks=atoi(optarg); break; case 'n': nonburp=1; break; case 'V': printf("%s-%s\n", prog, VERSION); return 0; case 'v': verbose=1; break; case 'h': case '?': return usage(); } } if(nonburp && givenconfigfile) { logp("-n and -c options are mutually exclusive\n"); return 1; } if(nonburp && groups) { logp("-n and -g options are mutually exclusive\n"); return 1; } if(!nonburp && maxlinks!=DEF_MAX_LINKS) { logp("-m option is specified via the configuration file in burp mode (max_hardlinks=)\n"); return 1; } if(deletedups && makelinks) { logp("-d and -l options are mutually exclusive\n"); return 1; } if(deletedups && !nonburp) { logp("-d option requires -n option\n"); return 1; } if(optind>=argc) { if(nonburp) { logp("No directories found after options\n"); return 1; } } else { if(!nonburp) { logp("Do not specify extra arguments.\n"); return 1; } } if(maxlinks<2) { logp("The argument to -m needs to be greater than 1.\n"); return 1; } if(nonburp) { // Read directories from command line. for(i=optind; i<argc; i++) { // Strip trailing slashes, for tidiness. if(argv[i][strlen(argv[i])-1]=='/') argv[i][strlen(argv[i])-1]='\0'; if(process_dir("", argv[i], ext, maxlinks, 0 /* not burp mode */, 0 /* level */)) { ret=1; break; } } } else { struct conf **globalcs=NULL; struct strlist *grouplist=NULL; struct lock *globallock=NULL; if(groups) { char *tok=NULL; if((tok=strtok(groups, ",\n"))) { do { if(strlist_add(&grouplist, tok, 1)) { log_out_of_memory(__func__); return -1; } } while((tok=strtok(NULL, ",\n"))); } if(!grouplist) { logp("unable to read list of groups\n"); return -1; } } // Read directories from config files, and get locks. if(!(globalcs=confs_alloc())) return -1; if(confs_init(globalcs)) return -1; if(conf_load_global_only(configfile, globalcs)) return 1; if(get_e_burp_mode(globalcs[OPT_BURP_MODE])!=BURP_MODE_SERVER) { logp("%s is not a server config file\n", configfile); confs_free(&globalcs); return 1; } logp("Dedup clients from %s\n", get_string(globalcs[OPT_CLIENTCONFDIR])); maxlinks=get_int(globalcs[OPT_MAX_HARDLINKS]); if(grouplist) { struct strlist *g=NULL; logp("in dedup groups:\n"); for(g=grouplist; g; g=g->next) logp("%s\n", g->path); } else { char *lockpath=NULL; // Only get the global lock when doing a global run. // If you are doing individual groups, you are likely // to want to do many different dedup jobs and a // global lock would get in the way. if(!(lockpath=prepend( get_string(globalcs[OPT_LOCKFILE]), ".bedup", "")) || !(globallock=lock_alloc_and_init(lockpath))) return 1; lock_get(globallock); if(globallock->status!=GET_LOCK_GOT) { logp("Could not get lock %s (%d)\n", lockpath, globallock->status); free_w(&lockpath); return 1; } logp("Got %s\n", lockpath); } ret=iterate_over_clients(globalcs, grouplist, ext, maxlinks); confs_free(&globalcs); lock_release(globallock); lock_free(&globallock); strlists_free(&grouplist); } if(!nonburp) { logp("%d client storages scanned\n", ccount); } logp("%llu duplicate %s found\n", count, count==1?"file":"files"); logp("%llu bytes %s%s\n", savedbytes, (makelinks || deletedups)?"saved":"saveable", bytes_to_human(savedbytes)); return ret; }
static int run_child(int *cfd, SSL_CTX *ctx, struct sockaddr_storage *addr, int status_wfd, int status_rfd, const char *conffile, int forking) { int ret=-1; int ca_ret=0; SSL *ssl=NULL; BIO *sbio=NULL; struct conf **confs=NULL; struct conf **cconfs=NULL; struct cntr *cntr=NULL; struct async *as=NULL; const char *cname=NULL; struct asfd *asfd=NULL; int is_status_server=0; if(!(confs=confs_alloc()) || !(cconfs=confs_alloc())) goto end; set_peer_env_vars(addr); // Reload global config, in case things have changed. This means that // the server does not need to be restarted for most conf changes. confs_init(confs); confs_init(cconfs); if(conf_load_global_only(conffile, confs)) goto end; // Hack to keep forking turned off if it was specified as off on the // command line. if(!forking) set_int(confs[OPT_FORK], 0); if(!(sbio=BIO_new_socket(*cfd, BIO_NOCLOSE)) || !(ssl=SSL_new(ctx))) { logp("There was a problem joining ssl to the socket\n"); goto end; } SSL_set_bio(ssl, sbio, sbio); /* Do not try to check peer certificate straight away. Clients can send a certificate signing request when they have no certificate. */ SSL_set_verify(ssl, SSL_VERIFY_PEER /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, 0); if(ssl_do_accept(ssl)) goto end; if(!(as=async_alloc()) || as->init(as, 0) || !(asfd=setup_asfd_ssl(as, "main socket", cfd, ssl))) goto end; asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT])); asfd->ratelimit=get_float(confs[OPT_RATELIMIT]); if(authorise_server(as->asfd, confs, cconfs) || !(cname=get_string(cconfs[OPT_CNAME])) || !*cname) { // Add an annoying delay in case they are tempted to // try repeatedly. log_and_send(as->asfd, "unable to authorise on server"); sleep(1); goto end; } if(!get_int(cconfs[OPT_ENABLED])) { log_and_send(as->asfd, "client not enabled on server"); sleep(1); goto end; } // Set up counters. Have to wait until here to get cname. if(!(cntr=cntr_alloc()) || cntr_init(cntr, cname)) goto end; set_cntr(confs[OPT_CNTR], cntr); set_cntr(cconfs[OPT_CNTR], cntr); /* At this point, the client might want to get a new certificate signed. Clients on 1.3.2 or newer can do this. */ if((ca_ret=ca_server_maybe_sign_client_cert(as->asfd, confs, cconfs))<0) { logp("Error signing client certificate request for %s\n", cname); goto end; } else if(ca_ret>0) { // Certificate signed and sent back. // Everything is OK, but we will close this instance // so that the client can start again with a new // connection and its new certificates. logp("Signed and returned client certificate request for %s\n", cname); ret=0; goto end; } /* Now it is time to check the certificate. */ if(ssl_check_cert(ssl, confs, cconfs)) { log_and_send(as->asfd, "check cert failed on server"); goto end; } if(status_rfd>=0) { is_status_server=1; if(!setup_asfd(as, "status server parent socket", &status_rfd)) goto end; } ret=child(as, is_status_server, status_wfd, confs, cconfs); end: *cfd=-1; if(as && asfd_flush_asio(as->asfd)) ret=-1; async_asfd_free_all(&as); // This closes cfd for us. logp("exit child\n"); if(cntr) cntr_free(&cntr); if(confs) { set_cntr(confs[OPT_CNTR], NULL); confs_free(&confs); } if(cconfs) { set_cntr(cconfs[OPT_CNTR], NULL); confs_free(&cconfs); } return ret; }