/***************************************************************** ** loadconfig (file, conf) ** Loads a config file into the "conf" structure pointed to by "z". ** If "z" is NULL then a new conf struct will be dynamically ** allocated. ** If no filename is given the conf struct will be initialized ** by the builtin default config *****************************************************************/ zconf_t *loadconfig (const char *filename, zconf_t *z) { FILE *fp; char buf[1023+1]; unsigned int line; if ( z == NULL ) /* allocate new memory for zconf_t */ { if ( (z = calloc (1, sizeof (zconf_t))) == NULL ) return NULL; if ( filename && *filename ) memcpy (z, &def, sizeof (zconf_t)); /* init new struct with defaults */ } if ( filename == NULL || *filename == '\0' ) /* no file name given... */ { dbg_val0("loadconfig (NULL)\n"); memcpy (z, &def, sizeof (zconf_t)); /* ..then init with defaults */ return z; } dbg_val1 ("loadconfig (%s)\n", filename); set_all_varptr (z); if ( (fp = fopen(filename, "r")) == NULL ) fatal ("Could not open config file \"%s\"\n", filename); line = 0; while (fgets(buf, sizeof(buf), fp)) parseconfigline (buf, ++line, z); fclose(fp); return z; }
zconf_t *loadconfig_fromstr (const char *str, zconf_t *z) { char *buf; char *tok, *toksave; unsigned int line; if ( z == NULL ) { if ( (z = calloc (1, sizeof (zconf_t))) == NULL ) return NULL; memcpy (z, &def, sizeof (zconf_t)); /* init with defaults */ } if ( str == NULL || *str == '\0' ) { dbg_val0("loadconfig_fromstr (NULL)\n"); memcpy (z, &def, sizeof (zconf_t)); /* init with defaults */ return z; } dbg_val1 ("loadconfig_fromstr (\"%s\")\n", str); set_all_varptr (z); /* str is const, so we have to copy it into a new buffer */ if ( (buf = strdup (str)) == NULL ) fatal ("loadconfig_fromstr: Out of memory"); line = 0; tok = strtok_r (buf, STRCONFIG_DELIMITER, &toksave); while ( tok ) { line++; parseconfigline (tok, line, z); tok = strtok_r (NULL, STRCONFIG_DELIMITER, &toksave); } free (buf); return z; }
/***************************************************************** ** ** parse_keyconf (const char *filename, dir, dirsize, int (*func) ()) ** ** Very dumb named.conf parser. ** - For every key definition "func (keyname, algo, secret)" will be called ** *****************************************************************/ static int parse_keyconf (const char *filename, char *dir, size_t dirsize, tsigkey_t *k, const char *lookup) { FILE *fp; int ret; int tok; char path[511+1]; char strval[4095+1]; char key[255+1]; char alg[31+1]; char secret[255+1]; dbg_val ("parse_keyconf: parsing file \"%s\" \n", filename); assert (filename != NULL); assert (dir != NULL && dirsize != 0); assert ( k != NULL); if ( (fp = fopen (filename, "r")) == NULL ) return -1; ret = 0; while ( (tok = gettok (fp, strval, sizeof strval)) != EOF ) { if ( tok > 0 && tok < 256 ) { fprintf (stderr, "parse_keyconf: token found with value %-10d: %c\n", tok, tok); } else if ( tok == TOK_DIR ) { if ( gettok (fp, strval, sizeof (strval)) == TOK_STRING ) { dbg_val2 ("parse_namedconf: directory found \"%s\" (dir is %s)\n", strval, dir); if ( *strval != '/' && *dir ) snprintf (path, sizeof (path), "%s/%s", dir, strval); else snprintf (path, sizeof (path), "%s", strval); snprintf (dir, dirsize, "%s", path); dbg_val ("parse_namedconf: new dir \"%s\" \n", dir); } } else if ( tok == TOK_INCLUDE ) { if ( gettok (fp, strval, sizeof (strval)) == TOK_STRING ) { if ( *strval != '/' && *dir ) snprintf (path, sizeof (path), "%s/%s", dir, strval); else snprintf (path, sizeof (path), "%s", strval); if ( (ret = parse_keyconf (path, dir, dirsize, k, lookup)) != 0 ) return ret; } else { fprintf (stderr, "parse_keyconf: need a filename after \"include\"!\n"); } } else if ( tok == TOK_KEY ) { int nrtok; dbg_val0 ("parse_keyconf: new key found \n"); if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING ) continue; snprintf (key, sizeof key, "%s", strval); /* store the name of the key */ dbg_val ("parse_keyconf: keyname \"%s\" \n", key); nrtok = 0; while ( nrtok < 2 && (tok = gettok (fp, strval, sizeof (strval))) ) { if ( tok == TOK_ALG ) { switch ( gettok (fp, strval, sizeof (strval)) ) { case TOK_HMAC_MD5: case TOK_HMAC_SHA1: case TOK_HMAC_SHA224: case TOK_HMAC_SHA256: case TOK_HMAC_SHA384: case TOK_HMAC_SHA512: snprintf (alg, sizeof alg, "%s", strval); /* this is the algorithm */ break; default: *alg = '\0'; continue; } } else if ( tok == TOK_SECRET ) { if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING ) break; snprintf (secret, sizeof secret, "%s", strval); /* this is the secret */ } nrtok++; } dbg_val5 ("dir %s key %s alg %s secret %s lookup \"%s\"\n", dir, key, alg, secret, lookup ? lookup: "NULL"); if ( lookup == NULL || lookup[0] == '\0' || strcmp (key, lookup) == 0 ) { snprintf (k->name, sizeof (k->name), "%s", key); snprintf (k->algo, sizeof (k->algo), "%s", alg); snprintf (k->secret, sizeof (k->secret), "%s", secret); ret = 1; break; } } else dbg_val3 ("%-10s(%d): %s\n", tok2str(tok), tok, strval); } fclose (fp); dbg_val2 ("parse_keyconf: leaving file \"%s\" ret = %d \n", filename, ret); return ret; }
int main (int argc, char *argv[]) { int c; int opt_index; int action; int major; int minor; const char *file; const char *defconfname = NULL; const char *confname = NULL; char *p; char str[254+1]; zconf_t *refconfig = NULL; zconf_t *config; progname = *argv; if ( (p = strrchr (progname, '/')) ) progname = ++p; view = getnameappendix (progname, "zkt-conf"); defconfname = getdefconfname (view); dbg_val0 ("Load built in config \"%s\"\n"); config = loadconfig ("", (zconf_t *)NULL); /* load built in config */ if ( fileexist (defconfname) ) /* load default config file */ { dbg_val ("Load site wide config file \"%s\"\n", defconfname); config = loadconfig (defconfname, config); } if ( config == NULL ) fatal ("Out of memory\n"); confname = defconfname; opterr = 0; opt_index = 0; action = 0; setconfigversion (100); #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG while ( (c = getopt_long (argc, argv, short_options, long_options, &opt_index)) != -1 ) #else while ( (c = getopt (argc, argv, short_options)) != -1 ) #endif { switch ( c ) { case 'V': /* view name */ view = optarg; defconfname = getdefconfname (view); if ( fileexist (defconfname) ) /* load default config file */ config = loadconfig (defconfname, config); if ( config == NULL ) fatal ("Out of memory\n"); confname = defconfname; break; case 'O': /* read option from commandline */ config = loadconfig_fromstr (optarg, config); break; case 'C': switch ( sscanf (optarg, "%d.%d", &major, &minor) ) { case 2: major = major * 100 + minor; case 1: break; default: usage ("illegal release number"); } setconfigversion (major); break; case 'c': if ( *optarg == '\0' ) usage ("empty config file name"); config = loadconfig (optarg, config); if ( *optarg == '-' || strcmp (optarg, "stdin") == 0 ) confname = "stdout"; else confname = optarg; break; case 'd': /* built-in default config */ config = loadconfig ("", config); /* load built-in config */ confname = defconfname; break; case 's': /* side wide config */ /* this is the default **/ break; case 'a': /* set all flag */ allflag = 1; break; case 'l': /* local config file */ refconfig = dupconfig (config); /* duplicate current config */ confname = LOCALCONF_FILE; if ( fileexist (LOCALCONF_FILE) ) /* try to load local config file */ { dbg_val ("Load local config file \"%s\"\n", LOCALCONF_FILE); config = loadconfig (LOCALCONF_FILE, config); } else if ( !writeflag ) usage ("error: no local config file found"); break; case 't': /* test config */ testflag = 1; break; case 'v': /* version */ fprintf (stderr, "%s version %s compiled for BIND version %d\n", progname, ZKT_VERSION, BIND_VERSION); fprintf (stderr, "ZKT %s\n", ZKT_COPYRIGHT); return 0; break; case 'w': /* write back conf file */ writeflag = 1; break; case 'h': /* print help */ usage (""); break; case ':': snprintf (str, sizeof(str), "option \"-%c\" requires an argument.", optopt); usage (str); break; case '?': if ( isprint (optopt) ) snprintf (str, sizeof(str), "Unknown option \"-%c\".", optopt); else snprintf (str, sizeof (str), "Unknown option char \\x%x.", optopt); usage (str); break; default: abort(); } } c = optind; if ( c >= argc ) /* no arguments given on commandline */ { if ( testflag ) { if ( checkconfig (config) ) fprintf (stderr, "All config file parameter seems to be ok\n"); } else { if ( !writeflag ) /* print to stdout */ confname = "stdout"; if ( refconfig ) /* have we seen a local config file ? */ if ( allflag ) printconfig (confname, config); else printconfigdiff (confname, refconfig, config); else printconfig (confname, config); } } else /* command line argument found: use it as name of zone file */ { long minttl; long maxttl; int keydbfound; char *dnskeydb; file = argv[c++]; dnskeydb = config->keyfile; minttl = 0x7FFFFFFF; maxttl = 0; keydbfound = parsezonefile (file, &minttl, &maxttl, dnskeydb); if ( keydbfound < 0 ) error ("can't parse zone file %s\n", file); if ( dnskeydb && !keydbfound ) { if ( writeflag ) { addkeydb (file, dnskeydb); printf ("\"$INCLUDE %s\" directive added to \"%s\"\n", dnskeydb, file); } else printf ("\"$INCLUDE %s\" should be added to \"%s\" (run with option -w)\n", dnskeydb, file); } if ( minttl < (10 * MINSEC) ) fprintf (stderr, "Min_TTL of %s (%ld seconds) is too low to use it in a signed zone (see RFC4641)\n", timeint2str (minttl), minttl); else fprintf (stderr, "Min_TTL:\t%s\t# (%ld seconds)\n", timeint2str (minttl), minttl); fprintf (stdout, "Max_TTL:\t%s\t# (%ld seconds)\n", timeint2str (maxttl), maxttl); if ( writeflag ) { refconfig = dupconfig (config); /* duplicate current config */ confname = LOCALCONF_FILE; if ( fileexist (LOCALCONF_FILE) ) /* try to load local config file */ { dbg_val ("Load local config file \"%s\"\n", LOCALCONF_FILE); config = loadconfig (LOCALCONF_FILE, config); } setconfigpar (config, "Max_TTL", &maxttl); printconfigdiff (confname, refconfig, config); } } return 0; }