// The return code of this is the return code of the standalone process. int champ_chooser_server_standalone(struct conf **globalcs) { int ret=1; struct sdirs *sdirs=NULL; struct conf **cconfs=NULL; const char *orig_client=get_string(globalcs[OPT_ORIG_CLIENT]); if(!(cconfs=confs_alloc())) goto end; confs_init(cconfs); // We need to be given a client name and load the relevant server side // clientconfdir file, because various settings may be overridden // there. if(set_string(cconfs[OPT_CNAME], orig_client) || conf_load_clientconfdir(globalcs, cconfs) || !(sdirs=sdirs_alloc()) || sdirs_init_from_confs(sdirs, cconfs) || champ_chooser_server(sdirs, cconfs, 0 /* resume */)) goto end; ret=0; end: confs_free(&cconfs); sdirs_free(&sdirs); return ret; }
static int check_client_and_password(struct conf **globalcs, const char *password, struct conf **cconfs) { const char *cname; int password_check; // Cannot load it until here, because we need to have the name of the // client. if(conf_load_clientconfdir(globalcs, cconfs)) return -1; cname=get_string(cconfs[OPT_CNAME]); password_check=get_int(cconfs[OPT_PASSWORD_CHECK]); if(!get_string(cconfs[OPT_SSL_PEER_CN])) { logp("ssl_peer_cn unset"); if(cname) { logp("Falling back to using '%s'\n", cname); if(set_string(cconfs[OPT_SSL_PEER_CN], cname)) return -1; } } cname=get_string(cconfs[OPT_CNAME]); if(password_check) { const char *conf_passwd=get_string(cconfs[OPT_PASSWD]); const char *conf_password=get_string(cconfs[OPT_PASSWORD]); if(!conf_password && !conf_passwd) { logp("password rejected for client %s\n", cname); return -1; } // check against plain text if(conf_password && strcmp(conf_password, password)) { logp("password rejected for client %s\n", cname); return -1; } // check against encypted passwd if(conf_passwd && !check_passwd(conf_passwd, password)) { logp("password rejected for client %s\n", cname); return -1; } } if(!get_strlist(cconfs[OPT_KEEP])) { logp("%s: you cannot set the keep value for a client to 0!\n", cname); return -1; } return 0; }
// FIX THIS: need to unit test this. static int do_conf_switch_to_orig_client(struct conf **globalcs, struct conf **cconfs, const char *orig_client, const char *buf) { int ret=-1; int loadrc; struct conf **sconfs=NULL; if(!(sconfs=confs_alloc()) || confs_init(sconfs)) goto end; if(set_string(sconfs[OPT_CNAME], orig_client)) goto end; logp("Client wants to switch to client: %s\n", get_string(sconfs[OPT_CNAME])); // Allow unit testing using a buffer. #ifdef UTEST if(buf) loadrc=conf_load_overrides_buf(globalcs, sconfs, buf); else #endif loadrc=conf_load_clientconfdir(globalcs, sconfs); if(loadrc) { logp("Could not load alternate config: %s", get_string(sconfs[OPT_CNAME])); goto end; } set_int(sconfs[OPT_SEND_CLIENT_CNTR], get_int(cconfs[OPT_SEND_CLIENT_CNTR])); if(!restore_client_allowed(cconfs, sconfs)) goto end; if(set_string(sconfs[OPT_RESTORE_PATH], get_string(cconfs[OPT_RESTORE_PATH]))) goto end; if(set_string(cconfs[OPT_RESTORE_PATH], NULL)) goto end; set_cntr(sconfs[OPT_CNTR], get_cntr(cconfs[OPT_CNTR])); set_cntr(cconfs[OPT_CNTR], NULL); confs_free_content(cconfs); confs_init(cconfs); confs_memcpy(cconfs, sconfs); confs_null(sconfs); if(set_string(cconfs[OPT_RESTORE_CLIENT], get_string(cconfs[OPT_CNAME]))) goto end; if(set_string(cconfs[OPT_ORIG_CLIENT], get_string(cconfs[OPT_CNAME]))) goto end; logp("Switched to client %s\n", get_string(cconfs[OPT_CNAME])); ret=0; end: confs_free(&sconfs); return ret; }
END_TEST static void check_restore_clients(struct cstat *cstat, struct conf **parentconf, const char *restore_clients, int permitted) { struct conf **cconfs=NULL; fail_unless((cconfs=confs_alloc())!=NULL); fail_unless(!confs_init(cconfs)); fail_unless(!set_string(cconfs[OPT_CNAME], "cli1")); build_clientconfdir_file("cli1", restore_clients); fail_unless(!conf_load_clientconfdir(parentconf, cconfs)); fail_unless(!set_string(parentconf[OPT_CNAME], "cli2")); fail_unless(cstat_permitted(cstat, parentconf, cconfs)==permitted); confs_free(&cconfs); }
// FIX THIS: need to unit test this. int conf_switch_to_orig_client(struct conf **globalcs, struct conf **cconfs, const char *orig_client) { int ret=-1; struct conf **sconfs=NULL; if(!(sconfs=confs_alloc()) || confs_init(sconfs)) goto end; if(set_string(sconfs[OPT_CNAME], orig_client)) goto end; logp("Client wants to switch to client: %s\n", get_string(sconfs[OPT_CNAME])); if(conf_load_clientconfdir(globalcs, sconfs)) { logp("Could not load alternate config: %s", get_string(sconfs[OPT_CNAME])); goto end; } set_int(sconfs[OPT_SEND_CLIENT_CNTR], get_int(cconfs[OPT_SEND_CLIENT_CNTR])); if(!restore_client_allowed(cconfs, sconfs)) goto end; if(set_string(sconfs[OPT_RESTORE_PATH], get_string(cconfs[OPT_RESTORE_PATH]))) goto end; if(set_string(cconfs[OPT_RESTORE_PATH], NULL)) goto end; set_cntr(sconfs[OPT_CNTR], get_cntr(cconfs)); set_cntr(cconfs[OPT_CNTR], NULL); confs_free_content(cconfs); confs_init(cconfs); confs_memcpy(cconfs, sconfs); confs_null(sconfs); if(set_string(cconfs[OPT_RESTORE_CLIENT], get_string(cconfs[OPT_CNAME]))) goto end; if(set_string(cconfs[OPT_ORIG_CLIENT], get_string(cconfs[OPT_CNAME]))) goto end; logp("Switched to client %s\n", get_string(cconfs[OPT_CNAME])); ret=0; end: confs_free(&sconfs); return ret; }
static int run_test_confs(struct conf **confs, const char *client) { int ret=-1; struct conf **cconfs=NULL; if(!client) { confs_dump(confs, 0); ret=0; goto end; } if(!(cconfs=confs_alloc())) goto end; confs_init(cconfs); if(set_string(cconfs[OPT_CNAME], client) || set_string(cconfs[OPT_PEER_VERSION], VERSION) || conf_load_clientconfdir(confs, cconfs)) goto end; confs_dump(cconfs, CONF_FLAG_CC_OVERRIDE|CONF_FLAG_INCEXC); end: confs_free(&cconfs); return ret; }
static #endif int cstat_reload_from_client_confs(struct cstat **clist, struct conf **globalcs, struct conf **cconfs) { struct cstat *c; struct stat statp; static time_t global_mtime=0; time_t global_mtime_new=0; const char *globalconffile; int reloaded=0; globalconffile=get_string(globalcs[OPT_CONFFILE]); if(stat(globalconffile, &statp) || !S_ISREG(statp.st_mode)) { logp("Could not stat main conf file %s: %s\n", globalconffile, strerror(errno)); return -1; } global_mtime_new=statp.st_mtime; // FIX THIS: If '. included' conf files have changed, this code will // not detect them. I guess that conf.c should make a list of them. while(1) { for(c=*clist; c; c=c->next) { // Look at the client conf files to see if they have // changed, and reload bits and pieces if they have. if(!c->conffile) continue; if(stat(c->conffile, &statp) || !S_ISREG(statp.st_mode)) { cstat_remove(clist, &c); break; // Go to the beginning of the list. } if(statp.st_mtime==c->conf_mtime && global_mtime_new==global_mtime) { // The conf files have not changed - no need to // do anything. continue; } c->conf_mtime=statp.st_mtime; confs_free_content(cconfs); if(set_string(cconfs[OPT_CNAME], c->name)) return -1; if(conf_load_clientconfdir(globalcs, cconfs)) { // If the file has junk in it, we will keep // trying to reload it after removal. // So, just deny permission to view it. c->permitted=0; continue; } if(set_cstat_from_conf(c, globalcs, cconfs)) return -1; reloaded++; } // Only stop if the end of the list was not reached. if(!c) break; } if(global_mtime!=global_mtime_new) global_mtime=global_mtime_new; return reloaded; }
static int iterate_over_clients(struct conf **globalcs, struct strlist *grouplist, const char *ext, unsigned int maxlinks) { int ret=0; DIR *dirp=NULL; struct conf **cconfs=NULL; struct dirent *dirinfo=NULL; const char *globalclientconfdir=get_string(globalcs[OPT_CLIENTCONFDIR]); signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); if(!(cconfs=confs_alloc())) return -1; if(confs_init(cconfs)) return -1; if(!(dirp=opendir(globalclientconfdir))) { logp("Could not opendir '%s': %s\n", globalclientconfdir, strerror(errno)); return 0; } while((dirinfo=readdir(dirp))) { char *lockfile=NULL; char *lockfilebase=NULL; char *client_lockdir=NULL; struct lock *lock=NULL; if(dirinfo->d_ino==0 // looks_like...() also avoids '.' and '..'. || looks_like_tmp_or_hidden_file(dirinfo->d_name) || !is_regular_file(globalclientconfdir, dirinfo->d_name)) continue; confs_free_content(cconfs); if(confs_init(cconfs)) return -1; if(set_string(cconfs[OPT_CNAME], dirinfo->d_name)) return -1; if(conf_load_clientconfdir(globalcs, cconfs)) { logp("could not load config for client %s\n", dirinfo->d_name); return 0; } if(grouplist) { const char *dedup_group= get_string(cconfs[OPT_DEDUP_GROUP]); if(!dedup_group || !in_group(grouplist, dedup_group)) continue; } if(!(client_lockdir=get_string(cconfs[OPT_CLIENT_LOCKDIR]))) client_lockdir=get_string(cconfs[OPT_DIRECTORY]); if(!(lockfilebase=prepend(client_lockdir, dirinfo->d_name, "/")) || !(lockfile=prepend(lockfilebase, BEDUP_LOCKFILE_NAME, "/"))) { free_w(&lockfilebase); free_w(&lockfile); ret=-1; break; } free_w(&lockfilebase); if(!(lock=lock_alloc_and_init(lockfile))) { ret=-1; break; } lock_get(lock); free_w(&lockfile); if(lock->status!=GET_LOCK_GOT) { logp("Could not get %s\n", lock->path); continue; } logp("Got %s\n", lock->path); // Remember that we got that lock. lock_add_to_list(&locklist, lock); if(process_dir(get_string(cconfs[OPT_DIRECTORY]), dirinfo->d_name, ext, maxlinks, 1 /* burp mode */, 0 /* level */)) { ret=-1; break; } ccount++; } closedir(dirp); locks_release_and_free(&locklist); confs_free(&cconfs); return ret; }