/** spool autotrust file */ static void spool_auto_file(FILE* in, int* lineno, FILE* cfg, char* id) { char line[MAX_LINE_LEN]; char* parse; FILE* spool; /* find filename for new file */ while(isspace((int)*id)) id++; if(strlen(id)==0) fatal_exit("AUTROTRUST_FILE must have id, line %d", *lineno); id[strlen(id)-1]=0; /* remove newline */ fake_temp_file("_auto_", id, line, sizeof(line)); /* add option for the file */ fprintf(cfg, "server: auto-trust-anchor-file: \"%s\"\n", line); /* open file and spool to it */ spool = fopen(line, "w"); if(!spool) fatal_exit("could not open %s: %s", line, strerror(errno)); fprintf(stderr, "testbound is spooling key file: %s\n", line); if(!cfg_strlist_insert(&cfgfiles, strdup(line))) fatal_exit("out of memory"); line[sizeof(line)-1] = 0; while(fgets(line, MAX_LINE_LEN-1, in)) { parse = line; (*lineno)++; while(isspace((int)*parse)) parse++; if(strncmp(parse, "AUTOTRUST_END", 13) == 0) { fclose(spool); return; } fputs(line, spool); } fatal_exit("no AUTOTRUST_END in input file"); }
/** process config elements */ static void setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[]) { char configfile[MAX_LINE_LEN]; char line[MAX_LINE_LEN]; char* parse; FILE* cfg; fake_temp_file("_cfg", "", configfile, sizeof(configfile)); add_opts("-c", pass_argc, pass_argv); add_opts(configfile, pass_argc, pass_argv); cfg = fopen(configfile, "w"); if(!cfg) fatal_exit("could not open %s: %s", configfile, strerror(errno)); if(!cfg_strlist_insert(&cfgfiles, strdup(configfile))) fatal_exit("out of memory"); line[sizeof(line)-1] = 0; /* some basic settings to not pollute the host system */ fprintf(cfg, "server: use-syslog: no\n"); fprintf(cfg, " directory: \"\"\n"); fprintf(cfg, " chroot: \"\"\n"); fprintf(cfg, " username: \"\"\n"); fprintf(cfg, " pidfile: \"\"\n"); fprintf(cfg, " val-log-level: 2\n"); while(fgets(line, MAX_LINE_LEN-1, in)) { parse = line; (*lineno)++; while(isspace((int)*parse)) parse++; if(!*parse || parse[0] == ';') continue; if(strncmp(parse, "COMMANDLINE", 11) == 0) { parse[strlen(parse)-1] = 0; /* strip off \n */ add_opts(parse+11, pass_argc, pass_argv); continue; } if(strncmp(parse, "AUTOTRUST_FILE", 14) == 0) { spool_auto_file(in, lineno, cfg, parse+14); continue; } if(strncmp(parse, "CONFIG_END", 10) == 0) { fclose(cfg); return; } fputs(line, cfg); } fatal_exit("No CONFIG_END in input file"); }
int ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname) { char* dup = strdup(fname); if(!dup) return UB_NOMEM; lock_basic_lock(&ctx->cfglock); if(ctx->finalized) { lock_basic_unlock(&ctx->cfglock); free(dup); return UB_AFTERFINAL; } if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) { lock_basic_unlock(&ctx->cfglock); return UB_NOMEM; } lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; }
int ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta) { char* dup = strdup(ta); if(!dup) return UB_NOMEM; lock_basic_lock(&ctx->cfglock); if(ctx->finalized) { lock_basic_unlock(&ctx->cfglock); free(dup); return UB_AFTERFINAL; } if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) { lock_basic_unlock(&ctx->cfglock); return UB_NOMEM; } lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; }
/** Read FILE match content */ static void read_file_content(FILE* in, int* lineno, struct replay_moment* mom) { char line[MAX_LINE_LEN]; char* remain = line; struct config_strlist** last = &mom->file_content; line[MAX_LINE_LEN-1]=0; if(!fgets(line, MAX_LINE_LEN-1, in)) fatal_exit("FILE_BEGIN expected at line %d", *lineno); if(!parse_keyword(&remain, "FILE_BEGIN")) fatal_exit("FILE_BEGIN expected at line %d", *lineno); while(fgets(line, MAX_LINE_LEN-1, in)) { (*lineno)++; if(strncmp(line, "FILE_END", 8) == 0) { return; } if(line[0]) line[strlen(line)-1] = 0; /* remove newline */ if(!cfg_strlist_insert(last, strdup(line))) fatal_exit("malloc failure"); last = &( (*last)->next ); } fatal_exit("no FILE_END in input file"); }
int ub_ctx_hosts(struct ub_ctx* ctx, char* fname) { FILE* in; char buf[1024], ldata[1024]; char* parse, *addr, *name, *ins; lock_basic_lock(&ctx->cfglock); if(ctx->finalized) { lock_basic_unlock(&ctx->cfglock); errno=EINVAL; return UB_AFTERFINAL; } lock_basic_unlock(&ctx->cfglock); if(fname == NULL) { #if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H) /* * If this is Windows NT/XP/2K it's in * %WINDIR%\system32\drivers\etc\hosts. * If this is Windows 95/98/Me it's in %WINDIR%\hosts. */ name = getenv("WINDIR"); if (name != NULL) { int retval=0; snprintf(buf, sizeof(buf), "%s%s", name, "\\system32\\drivers\\etc\\hosts"); if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) { snprintf(buf, sizeof(buf), "%s%s", name, "\\hosts"); retval=ub_ctx_hosts(ctx, buf); } free(name); return retval; } return UB_READFILE; #else fname = "/etc/hosts"; #endif /* WIN32 */ } in = fopen(fname, "r"); if(!in) { /* error in errno! perror(fname) */ return UB_READFILE; } while(fgets(buf, (int)sizeof(buf), in)) { buf[sizeof(buf)-1] = 0; parse=buf; while(*parse == ' ' || *parse == '\t') parse++; if(*parse == '#') continue; /* skip comment */ /* format: <addr> spaces <name> spaces <name> ... */ addr = parse; /* skip addr */ while(isxdigit(*parse) || *parse == '.' || *parse == ':') parse++; if(*parse == '\n' || *parse == 0) continue; if(*parse == '%') continue; /* ignore macOSX fe80::1%lo0 localhost */ if(*parse != ' ' && *parse != '\t') { /* must have whitespace after address */ fclose(in); errno=EINVAL; return UB_SYNTAX; } *parse++ = 0; /* end delimiter for addr ... */ /* go to names and add them */ while(*parse) { while(*parse == ' ' || *parse == '\t' || *parse=='\n') parse++; if(*parse == 0 || *parse == '#') break; /* skip name, allows (too) many printable characters */ name = parse; while('!' <= *parse && *parse <= '~') parse++; if(*parse) *parse++ = 0; /* end delimiter for name */ snprintf(ldata, sizeof(ldata), "%s %s %s", name, str_is_ip6(addr)?"AAAA":"A", addr); ins = strdup(ldata); if(!ins) { /* out of memory */ fclose(in); errno=ENOMEM; return UB_NOMEM; } lock_basic_lock(&ctx->cfglock); if(!cfg_strlist_insert(&ctx->env->cfg->local_data, ins)) { lock_basic_unlock(&ctx->cfglock); fclose(in); free(ins); errno=ENOMEM; return UB_NOMEM; } lock_basic_unlock(&ctx->cfglock); } } fclose(in); return UB_NOERROR; }
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr) { struct sockaddr_storage storage; socklen_t stlen; struct config_stub* s; char* dupl; lock_basic_lock(&ctx->cfglock); if(ctx->finalized) { lock_basic_unlock(&ctx->cfglock); errno=EINVAL; return UB_AFTERFINAL; } if(!addr) { /* disable fwd mode - the root stub should be first. */ if(ctx->env->cfg->forwards && strcmp(ctx->env->cfg->forwards->name, ".") == 0) { s = ctx->env->cfg->forwards; ctx->env->cfg->forwards = s->next; s->next = NULL; config_delstubs(s); } lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; } lock_basic_unlock(&ctx->cfglock); /* check syntax for addr */ if(!extstrtoaddr(addr, &storage, &stlen)) { errno=EINVAL; return UB_SYNTAX; } /* it parses, add root stub in front of list */ lock_basic_lock(&ctx->cfglock); if(!ctx->env->cfg->forwards || strcmp(ctx->env->cfg->forwards->name, ".") != 0) { s = calloc(1, sizeof(*s)); if(!s) { lock_basic_unlock(&ctx->cfglock); errno=ENOMEM; return UB_NOMEM; } s->name = strdup("."); if(!s->name) { free(s); lock_basic_unlock(&ctx->cfglock); errno=ENOMEM; return UB_NOMEM; } s->next = ctx->env->cfg->forwards; ctx->env->cfg->forwards = s; } else { log_assert(ctx->env->cfg->forwards); s = ctx->env->cfg->forwards; } dupl = strdup(addr); if(!dupl) { lock_basic_unlock(&ctx->cfglock); errno=ENOMEM; return UB_NOMEM; } if(!cfg_strlist_insert(&s->addrs, dupl)) { free(dupl); lock_basic_unlock(&ctx->cfglock); errno=ENOMEM; return UB_NOMEM; } lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; }
int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr, int isprime) { char* a; struct config_stub **prev, *elem; /* check syntax for zone name */ if(zone) { uint8_t* nm; int nmlabs; size_t nmlen; if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) { errno=EINVAL; return UB_SYNTAX; } free(nm); } else { zone = "."; } /* check syntax for addr (if not NULL) */ if(addr) { struct sockaddr_storage storage; socklen_t stlen; if(!extstrtoaddr(addr, &storage, &stlen)) { errno=EINVAL; return UB_SYNTAX; } } lock_basic_lock(&ctx->cfglock); if(ctx->finalized) { lock_basic_unlock(&ctx->cfglock); errno=EINVAL; return UB_AFTERFINAL; } /* arguments all right, now find or add the stub */ prev = &ctx->env->cfg->stubs; elem = cfg_stub_find(&prev, zone); if(!elem && !addr) { /* not found and we want to delete, nothing to do */ lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; } else if(elem && !addr) { /* found, and we want to delete */ *prev = elem->next; config_delstub(elem); lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; } else if(!elem) { /* not found, create the stub entry */ elem=(struct config_stub*)calloc(1, sizeof(struct config_stub)); if(elem) elem->name = strdup(zone); if(!elem || !elem->name) { free(elem); lock_basic_unlock(&ctx->cfglock); errno = ENOMEM; return UB_NOMEM; } elem->next = ctx->env->cfg->stubs; ctx->env->cfg->stubs = elem; } /* add the address to the list and set settings */ elem->isprime = isprime; a = strdup(addr); if(!a) { lock_basic_unlock(&ctx->cfglock); errno = ENOMEM; return UB_NOMEM; } if(!cfg_strlist_insert(&elem->addrs, a)) { lock_basic_unlock(&ctx->cfglock); errno = ENOMEM; return UB_NOMEM; } lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; }