#!/usr/bin/perl
#
# Copyright 2006-2008 SPARTA, Inc.  All rights reserved.  See the COPYING
# file distributed with this software for details.
#
# DNSSEC-Tools:  dtinitconf
#
#	This script initializes the DNSSEC-Tools configuration file.
#
#		dtinitconf
#

use strict;

use Net::DNS::SEC::Tools::conf;
use Net::DNS::SEC::Tools::defaults;
use Net::DNS::SEC::Tools::tooloptions;

#
# Version information.
#
my $NAME   = "dtinitconf";
my $VERS   = "$NAME version: 1.1";
my $DTVERS = "DNSSEC-Tools Version: 1.4.1";

#
# Common locations for BIND.  These locations were found on:
#
#	FreeBSD 5.4
#	MacOS X 10.4.5
#	SunOS 5.8
#
my @COMMON_BINDLOCS =
(
	"/usr/local/sbin",
	"/usr/sbin",
);

my $DEFAULT_EDITOR = "vi";

#
# Command-line options specifically for this program.
#
my @opts =
(
	"outfile=s",				# Output config file.
	"edit",					# Edit resulting file.
	"overwrite",				# Overwrite existing files.
	"noprompt",				# Don't prompt user.
	"verbose",				# Verbose equivalent.
	"Version",			        # Display the version number.

	"usegui",				# Use option GUI.
	"noentropy_msg",			# Don't give entropy message.
	"nosavekeys",				# Don't save old keys.
	"nousegui",				# Don't use option GUI.

	"admin=s",				# Administrator's email address.
	"binddir=s",				# Path to BIND programs.
	"viewimage=s",				# Path to image viewer.

	"roll-logfile=s",			# Logfile for rollerd.
	"roll-loglevel=s",			# Logging level for rollerd.
	"roll-sleep=i",				# Sleep-time for rollerd.

	"ta-contact=s",				# trustman email contact
	"ta-smtpserver=s",			# trustman smtp server
);

#
# Data required for command-line options.
#
my $alg;				# The encryption algorithm.
my $endtime;				# Endtime of signature validity.
my $ksklife;				# Lifespan of the KSK.
my $ksklen;				# The KSK size.
my $random;				# The source of randomness.
my $zskcnt;				# Count of ZSK keys.
my $zsklife;				# Lifespan of the ZSK.
my $zsklen;				# The ZSK size.

my $admin;				# Administrator's email address.
my $entmsg;				# Display entropy message.
my $keyarch;				# Key archive directory.
my $savekeys;				# Save/delete old keys.
my $usegui;				# Use-GUI flag.

my $editflag;				# Edit resulting config file.
my $helpflag;				# Give usage message.
my $noprompt = 0;			# Don't prompt -- just use defaults.
my $outfile;				# Output filename.
my $overwrite;				# Overwrite existing output file.
my $verbose = 0;			# Give verbose output.
my $version = 0;			# Display the version number.

my $kgopts;				# Options for key-generation program.
my $zcopts;				# Options for zone-checking program.
my $zsopts;				# Options for zone-signing program.

my $rlogfile;				# Logfile for rollerd.
my $rloglevel;				# Logging level for rollerd.
my $rsleep;				# Sleep-time for rollerd.

my $tacontact;				# trustman email contact.
my $tasmtpserver;			# trustman smtp server.

#
# Program paths.
#
my $binddir;				# BIND directory.
my $zonecheck;				# BIND's zone-checking program.
my $keygen;				# BIND's key-generation program.
my $zonesign;				# BIND's zone-signing program.
my $viewimg;				# Image viewer.



main();
exit(0);

#----------------------------------------------------------------------------
#
# Routine:	main()
#
# Purpose:	Yeah, yeah, a main() isn't necessary.  However, it offends my
#		sense of aesthetics to have great gobs of code on the same
#		level as a pile of globals.
#
#		But what about those globals, you ask...
#
sub main
{
	my $confdir;				# Configuration directory.

	#
	# Force output to be written right away.
	#
	$| = 1;

	#
	# Parse the command line options.
	#
	optsandargs();

	#
	# Ensure our configuration directory exists and is a directory.
	#
	$confdir = getconfdir();
	if(! -e $confdir)
	{
		my $uid = 0;				# UID of confdir.
		my $gid;				# GID of confdir.

		print STDERR "configuration directory \"$confdir\" does not exist; creating...\n\n";

		$gid = getgrnam("dnssec") || -1;
		mkdir($confdir,0755);
		chown($uid,$gid,$confdir);
	}
	elsif(! -d $confdir)
	{
		print STDERR "configuration directory \"$confdir\" is not a directory; unable to continue\n";
		exit(1);
	}

	#
	# Ensure that we can write the output file.
	#
	if(-e $outfile)
	{
		#
		# Convert an output file of "-" to the terminal.
		#
		$outfile = "/dev/tty" if($outfile eq "-");

		#
		# Only overwrite an existing config file if the user wants it.
		#
		if((-f $outfile) && !$overwrite)
		{
			print STDERR "config file \"$outfile\" already exists;\n";
			print STDERR " use -overwrite to overwrite it\n";
			exit(1);
		}

		#
		# Ensure the existing config file is writable.
		#
		if(! -w $outfile)
		{
			print STDERR "\nwarning:  configuration file \"$outfile\" is not writable;\n";
			print STDERR "\t\tthis must be fixed before the final pieces of data are gathered\n\n";
		}
	}
	else
	{
		#
		# Ensure the config directory is writable.
		#
		if(! -w $confdir)
		{
			print STDERR "\nwarning:  configuration directory \"$confdir\" is not writable;\n";
			print STDERR "\t\tthis must be fixed before the final pieces of data are gathered\n\n";
		}
	}

	#
	# Prompt the user for the data, unless they don't want to be prompted.
	#
	if($noprompt)
	{
		guessdata();
	}
	else
	{
		gatherdata();
	}

	#
	# Write the configuration file.
	#
	writeconf();

	#
	# Edit the configuration file.
	#
	editconf();
}

#-----------------------------------------------------------------------------
#
# Routine:	optsandargs()
#
# Purpose:	Parse the command line for options and arguments.
#
sub optsandargs
{
	my $ropts;				# Reference to options hash.
	my %opts = ();				# Options hash.

	#
	# Slurp up the options.
	#
	opts_onerr(1);
	$ropts = opts_cmdopts(@opts);
	%opts = %$ropts 	if($ropts != undef);

	#
	# Get the option values.  If these weren't given on the command
	# line, they'll be taken the DNSSEC-Tools defaults.
	#
	$ksklen    = $opts{'ksklength'} || dnssec_tools_default("ksklength");
	$ksklife   = $opts{'ksklife'}   || dnssec_tools_default("ksklife");
	$zskcnt	   = $opts{'zskcount'}  || dnssec_tools_default("zskcount");
	$zsklen    = $opts{'zsklength'} || dnssec_tools_default("zsklength");
	$zsklife   = $opts{'zsklife'}   || dnssec_tools_default("zsklife");

	$alg	   = $opts{'algorithm'}	|| dnssec_tools_default("algorithm");
	$endtime   = $opts{'endtime'}	|| dnssec_tools_default("enddate");
	$random	   = $opts{'random'}	|| dnssec_tools_default("random");

	$keyarch   = $opts{'archivedir'};
	$savekeys  = $opts{'savekeys'}	  || dnssec_tools_default("savekeys");
	$usegui	   = $opts{'usegui'}	  || dnssec_tools_default("usegui");
	$entmsg	   = $opts{'entropy_msg'} || dnssec_tools_default("entropy_msg");

	$rlogfile  = $opts{'roll_logfile'}  || dnssec_tools_default("roll_logfile");
	$rloglevel = $opts{'roll_loglevel'} || dnssec_tools_default("roll_loglevel");
	$rsleep	   = $opts{'roll_sleep'}    || dnssec_tools_default("roll_sleeptime");

	$tacontact = $opts{'ta_contact'}    || dnssec_tools_default("ta_contact");
	$tasmtpserver = $opts{'ta_smtpserver'}    || dnssec_tools_default("ta_smtpserver");

	$entmsg	   = 0  if(defined($opts{'noentropy_msg'}));
	$savekeys  = 0  if(defined($opts{'nosavekeys'}));
	$usegui	   = 0  if(defined($opts{'nousegui'}));

	$admin	   = $opts{'admin'}	|| dnssec_tools_default("admin");
	$binddir   = $opts{'binddir'};
	$viewimg   = $opts{'viewimage'} || dnssec_tools_default("viewimage");

	$outfile   = $opts{'outfile'}	|| getconffile();
	$overwrite = $opts{'overwrite'};

	$verbose   = $opts{'verbose'}   || $opts{'v'};
	$version   = $opts{'Version'};
	$helpflag  = $opts{'help'};
	$editflag  = $opts{'edit'};
	$noprompt  = $opts{'noprompt'};

	#
	# Display the version number
	#
	version() if($version);

	#
	# Give usage message if desired.
	#
	usage() if($helpflag);

}

#----------------------------------------------------------------------------
#
# Routine:	gatherdata()
#
# Purpose:	Get all our stray little data.
#
sub gatherdata()
{
	get_paths();
	get_key_opts();
	get_zone_opts();
	get_dt_opts();
}

#----------------------------------------------------------------------------
#
# Routine:	guessdata()
#
# Purpose:	Guess at some of our data.
#
sub guessdata()
{
	guess_paths();
}

#----------------------------------------------------------------------------
#
# Routine:	writeconf()
#
# Purpose:	Write the new config file.
#
sub writeconf()
{
	my $kronos = gmtime();		# Timestamp when file was created.

	#
	# If the verbose flag was given, show all the values.
	#
	if($verbose)
	{
		print "writing values to \"$outfile\":\n";

		print "\tadmin      - \"$admin\"\n";
		print "\talgorithm  - \"$alg\"\n";
		print "\trandom     - \"$random\"\n";
		print "\tksklen     - \"$ksklen\"\n";
		print "\tksklife    - \"$ksklife\"\n";
		print "\tzskcount   - \"$zskcnt\"\n\n";
		print "\tzsklen     - \"$zsklen\"\n";
		print "\tzsklife    - \"$zsklife\"\n\n";

		print "\tendtime    - \"$endtime\"\n\n";

		print "\tentropy message flag  - \"$entmsg\"\n";
		print "\told key archive       - \"$keyarch\"\n";
		print "\tsave-old-keys flag    - \"$savekeys\"\n";
		print "\tuse-gui flag          - \"$usegui\"\n\n";

		print "\troll-logfile          - \"$rlogfile\"\n";
		print "\troll-loglevel         - \"$rloglevel\"\n";
		print "\troll-sleep            - \"$rsleep\"\n\n";

		print "\tkeygen     - \"$keygen\"\n";
		print "\tzonecheck  - \"$zonecheck\"\n";
		print "\tzonesign   - \"$zonesign\"\n";
		print "\tviewimage  - \"$viewimg\"\n\n";

		print "\tkeygen options     - \"$kgopts\"\n";
		print "\tzonecheck options  - \"$zcopts\"\n";
		print "\tzonesign  options  - \"$zsopts\"\n\n";

		print "\ttacontact    - \"$tacontact\"\n";
		print "\ttasmtpserver - \"$tasmtpserver\"\n";
		
	}

	open(DTCONF,">$outfile") or die "unable to open \"$outfile\" for writing";

	print DTCONF "#
# DNSSEC-Tools Configuration
#
#	This file contains configuration information for DNSSEC-Tools.
#
#	This was automatically generated by dtinitconf on
#	$kronos (GMT).
#

#
# Settings for DNSSEC-Tools administration.
#
admin-email     $admin

#
# Paths to needed programs.  These may need adjusting for individual hosts.
#
keygen		$keygen
viewimage	$viewimg
zonecheck	$zonecheck
zonesign	$zonesign
zonesigner	/usr/bin/zonesigner
";

	if(($kgopts ne "") || ($zcopts ne "") || ($zsopts ne ""))
	{
		print DTCONF "
#
# Program options.
#
";
	}
	print DTCONF "keygen-opts	$kgopts\n" if($kgopts ne "");
	print DTCONF "zonecheck-opts	$zcopts\n" if($zcopts ne "");
	print DTCONF "zonesign-opts	$zsopts\n" if($zsopts ne "");

	print DTCONF "
#
# Key-related values.
#
algorithm	$alg
ksklen		$ksklen
zsklen		$zsklen
random		$random

#
# Settings for dnssec-signzone.
#
endtime		$endtime		# RRSIGs good for thirty days.

#
# Life-times for keys.  These defaults indicate how long a key has
# between roll-overs.  The values are measured in seconds.
#
# Sample values:
#	3600		hour
#	86400		day
#	604800		week
#	2592000		30-day month
#	15768000	half-year
#	31536000	year
#
ksklife		$ksklife
zsklife		$zsklife

#
# Settings for zonesigner.
#
archivedir	$keyarch
entropy_msg	$entmsg
savekeys	$savekeys
zskcount	$zskcnt

#
# Settings for rollerd.
#
roll_logfile    $rlogfile
roll_loglevel   $rloglevel
roll_sleeptime  $rsleep

#
# Settings for trustman
#
tacontact	$tacontact
tasmtpserver	$tasmtpserver

#
# GUI-usage flag.
#
usegui		$usegui
";

	close(DTCONF);
}

#----------------------------------------------------------------------------
#
# Routine:	editconf()
#
# Purpose:	Edit the new config file.
#
sub editconf()
{
	my $eddie;				# User's preferred editor.
	my $cmdstr = "";			# Edit command string.

	return if(!$editflag);

	#
	# Get the editor's path.
	#
	$eddie = $ENV{'EDITOR'};	
	$eddie = $DEFAULT_EDITOR if(!defined($eddie));
	if(!defined($eddie))
	{
		print STDERR "unable to find editor\n";
		return;
	}

	#
	# Try to execute the editor.
	#
	$cmdstr = "$eddie $outfile";
	system($cmdstr);
}

#----------------------------------------------------------------------------
#
# Routine:	get_paths()
#
# Purpose:	This routine gathers path-related data.  The primary task
#		is to figure out the path for BIND programs.  After digging
#		up this path, it's used to create paths for named_checkzone,
#		dnssec_keygen, and dnssec_signzone.
#
sub get_paths()
{
	my $pcret  = 0;				# pathchk() return value.

	print "Path-related Options:\n";

	#
	# If the user didn't give -binddir, we'll go through our internal
	# collection of possible BIND directories.
	#
	if($binddir eq "")
	{
		my @binddirs;				# BIND directories.

		#
		# Get the directories that contain BIND programs.
		#
		@binddirs = findbind();

		#
		# If we found any directories with BIND programs, we'll list
		# the directories for the user.  If we didn't find anything,
		# we'll give a message.
		#
		if(@binddirs > 0)
		{
			#
			# Print the directories that hold BIND programs.
			#
			print "\tThese directories contain BIND programs:\n";
			foreach $binddir (sort(@binddirs))
			{
				print "\t\t$binddir\n";
			}
			print "\n";
		}
		else
		{
			print "\tBIND may not be installed on your system\n";
		}
		$binddir = getval("BIND directory",$binddirs[0]);
		print "\n";
	}
	else
	{
		print "\n\tUsing \"$binddir\" for BIND directory\n\n";
	}

	#
	# Build paths for the BIND programs.
	#
	$keygen	   = "$binddir/dnssec-keygen";
	$zonecheck = "$binddir/named-checkzone";
	$zonesign  = "$binddir/dnssec-signzone";

	#
	# Get the path for an image viewer.
	#
	$viewimg = getval("Image Display Program",$viewimg);

	#
	# Check that the paths all valid.
	#
	print "\n\tChecking validity of paths:\n";
	$pcret += pathchk("BIND directory",$binddir);
	$pcret += pathchk("BIND's named_checkzone",$zonecheck);
	$pcret += pathchk("BIND's dnssec_keygen",$keygen);
	$pcret += pathchk("BIND's dnssec_signzone",$zonesign);
	$pcret += pathchk("Image display program",$viewimg);

	#
	# If any of the paths don't exist, then we'll give the user
	# the option of re-entering the paths.
	#
	if($pcret)
	{
		my $again;				# Re-entry flag.

		$again = getval("\n\tAt least one path did not exist.\n\tWould you like to try again?  ",1,"boolean");

		if($again)
		{
			print "\n";
			$binddir = "";
			get_paths();
		}
	}
	else
	{
		print "\tAll paths are valid.\n";
	}

	print "\n";
}

#----------------------------------------------------------------------------
#
# Routine:	guess_paths()
#
# Purpose:	This routine makes guesses at path-related data and is only
#		called when -noprompt was given.  The primary task is to figure
#		out the path for BIND programs.  After digging up this path,
#		it's used to create paths for named_checkzone, dnssec_keygen,
#		and dnssec_signzone.
#
sub guess_paths()
{
	#
	# If the user didn't give -binddir, we'll go through our internal
	# collection of possible BIND directories.
	#
	if($binddir eq "")
	{
		my @binddirs;				# BIND directories.

		#
		# Get the directories that contain BIND programs.
		#
		@binddirs = findbind();

		#
		# If we found any directories with BIND programs, we'll use
		# the first directory.
		#
		$binddir = $binddirs[0] if(@binddirs > 0);
	}

	#
	# Build paths for the BIND programs.
	#
	$keygen	   = "$binddir/dnssec-keygen";
	$zonecheck = "$binddir/named-checkzone";
	$zonesign  = "$binddir/dnssec-signzone";
}

#----------------------------------------------------------------------------
#
# Routine:	get_key_opts()
#
# Purpose:	Get key-related options.
#
sub get_key_opts()
{
	print "Key-related Options:\n";

	$alg	 = getval("Encryption Algorithm",$alg);
	$random	 = getval("Random-number Generator",$random);
	$ksklen	 = getval("KSK Length (in bits)",$ksklen);
	$ksklife = getval("KSK Lifespan (in seconds)",$ksklife);
	$zsklen	 = getval("ZSK Length (in bits)",$zsklen);
	$zsklife = getval("ZSK Lifespan (in seconds)",$zsklife);
	$zskcnt	 = getval("ZSK Count",$zskcnt);

	print "\n";
}

#----------------------------------------------------------------------------
#
# Routine:	get_zone_opts()
#
# Purpose:	Get zone-related options.
#
sub get_zone_opts()
{
	print "Zone-related Options:\n";

	$endtime = getval("End-time",$endtime);

	print "\n";
}

#----------------------------------------------------------------------------
#
# Routine:	get_dt_opts()
#
# Purpose:	Get DNSSEC-Tools-specific options.
#
sub get_dt_opts()
{
	print "DNSSEC-Tools Options:\n";

	$usegui	  = getval("Use DNSSEC-Tools GUI Interface",$usegui,"boolean");
	$entmsg	  = getval("Display Entropy Message in Zonesigner",$entmsg,"boolean");
	$savekeys = getval("Save Old Keys",$savekeys,"boolean");
	$keyarch  = getval("Key Archive Directory","");

	print "\n";

	$kgopts = getval("Key-Generation Options","");
	$zcopts = getval("Zone-Checking Options","");
	$zsopts = getval("Zone-Signing Options","");
	print "\n";

	$rlogfile  = getval("Roll-over Manager's Logfile",$rlogfile,"");
	$rloglevel = getval("Roll-over Manager's Logging Level",$rloglevel,"", "(valid values:  tmi, expire, info, phase, err, fatal)");
	$rsleep	   = getval("Roll-over Manager's Sleep-time",$rsleep,"");

	print "\n";

	$tacontact = getval("TrustMan's contact address",$tacontact,"");
	$tasmtpserver = getval("TrustMan's SMTP server",$tasmtpserver,"");

	print "\n";
}

#----------------------------------------------------------------------------
#
# Routine:	getval()
#
# Purpose:	Prompt a user for input, providing a default.  If the return
#		key is hit without anything else being entered, the default
#		value is returned.  Otherwise, the user's input is returned
#		(minus the trailing newline.)
#
sub getval()
{
	my $prompt = shift;				# User prompt.
	my $defval = shift;				# Default value.
	my $type   = shift;				# Value type.
	my $secstr = shift;				# Secondary string.

	my $defstr;					# Default string.
	my $val;					# User's value.

	#
	# Set up the default we'll actually print.
	#
	$defstr = $defval;
	$defstr = "no default" if($defval eq "");

	#
	# If this is a boolean, we'll use friendly words.
	#
	if($type eq "boolean")
	{
		if($defval) { $defval = "yes"; }
		else	    { $defval = "no";  }
		$defstr = $defval;
	}

	#
	# Prompt for the value and read it in.
	#
	if(defined($secstr))
	{
		print"\t$prompt [$defstr]\n";
		print"\t    $secstr:  " if(defined($secstr));
	}
	else
	{
		print"\t$prompt [$defstr]:  ";
	}
	$val = <STDIN>;

	#
	# Get rid of the trailing newline.  If we're left with nothing,
	# then we'll use the default value.
	#
	$val =~ s/\n$//;
	$val = $defval if($val eq "");

	#
	# If this was a boolean field, we'll translate "yes" and "no" into
	# one or zero.  We'll also be sure that good boolean values were
	# submitted.  If not, an error message is given and we start all
	# over again.
	#
	if($type eq "boolean")
	{
		#
		# If this was "yes" or "no", make the translation.
		#
		$val = lc($val);
		if(($val eq "yes") || ($val eq "ye") || ($val eq "y")	||
		   ($val eq "no") || ($val eq "n"))
		{
			if(($val eq "yes") || ($val eq "ye") || ($val eq "y"))
			{
				$val = 1;
			}
			else
			{
				$val = 0;
			}
		}
		else
		{
			#
			# If the whole value is an integer, we'll use it as
			# a boolean.  If not, then we were give an invalid
			# response -- complain and try again.
			#
			if($val =~ /^[0-9]+$/)
			{
				$val = 1 * $val;
			}
			else
			{
				print STDERR "\ninvalid boolean value; you must use \"yes\", \"no\", \"1\", or \"0\"\n\n";
				return(getval($prompt,$defval,$type,$secstr));
			}
		}
	}

	#
	# Return the value.
	#
	return($val);
}

#----------------------------------------------------------------------------
#
# Routine:	findbind()
#
# Purpose:	This routine collects a set of directories that hold the
#		BIND programs used by DNSSEC-Tools.  The following sources
#		are checked:
#			- directories in the path
#			- directories that commonly are used for BIND
#			- DNSSEC-Tools defaults
#
#		The list of collected directories are returned to the caller.
#
sub findbind()
{
	my $binddir;				# BIND directory.
	my $pbg;				# Path to BIND programs.

	my $paths;				# Path environment variable.
	my @paths;				# Split-out paths.
	my %hfound = ();			# Directories with BIND progs.
	my @found;				# Directories with BIND progs.

	#
	# Look in the environment and in some common directories for a set
	# of BIND programs.  Any time we find the program, we'll mark a hash
	# entry for its directory.
	#
	foreach my $bind ("dnssec-keygen", "dnssec-signzone", "named-checkzone")
	{
		#
		# Look in our path for the BIND program.
		#
		$paths = $ENV{'PATH'};
		@paths = split /:/, $paths;
		foreach my $path (@paths)
		{
			$pbg = "$path/$bind";
			next if(! -e $pbg);
			$hfound{$path} = 1;
		}

		#
		# Look in a set of common locations for the BIND program.
		#
		foreach my $path (@COMMON_BINDLOCS)
		{
			$pbg = "$path/$bind";
			next if(! -e $pbg);
			$hfound{$path} = 1;
		}
	}

	#
	# Look for the BIND tools in our defaults.
	#
	$pbg = dnssec_tools_default("keygen");
	$pbg =~ s/\/dnssec-keygen$//;
	$hfound{$pbg} = 1;
	$pbg = dnssec_tools_default("zonecheck");
	$pbg =~ s/\/named-checkzone$//;
	$hfound{$pbg} = 1;
	$pbg = dnssec_tools_default("zonesign");
	$pbg =~ s/\/dnssec-signzone$//;
	$hfound{$pbg} = 1;

	#
	# Return the directories we found with BIND programs.
	#
	@found = keys(%hfound);
	return(@found);
}

#----------------------------------------------------------------------------
#
# Routine:	pathchk()
#
# Purpose:	Check for existence of a path.  If it doesn't exist, an
#		error message will be printed.
#
sub pathchk()
{
	my $descr = shift;			# Description of path to check.
	my $path  = shift;			# Path to check.

	return(0) if(-e $path);

	print "\t\t$descr ($path) does not exist\n";
	return(1);
}

#----------------------------------------------------------------------
#
# Routine:	version()
#
# Purpose:	Print the version number(s) and exit.
#
sub version
{
	print STDERR "$VERS\n";
	print STDERR "$DTVERS\n";

	exit(1);
}

#----------------------------------------------------------------------------
#
# Routine:	usage()
#
sub usage()
{
	print STDERR "usage:  dtinitconf [options]\n";

	print STDERR "\toptions:\n";

	print STDERR "\t\t-algorithm <algorithm>\n";
	print STDERR "\t\t-endtime <endtime>\n";
	print STDERR "\t\t-random <randomdev>\n\n";

	print STDERR "\t\t-ksklength <keylen>\n";
	print STDERR "\t\t-ksklife <lifespan>\n";
	print STDERR "\t\t-zskcount <ZSK-count>\n\n";
	print STDERR "\t\t-zsklength <keylen>\n";
	print STDERR "\t\t-zsklife <lifespan>\n\n";

	print STDERR "\t\t-archivedir <directory>\n";
	print STDERR "\t\t-binddir <directory>\n";
	print STDERR "\t\t-entropy_msg\n";
	print STDERR "\t\t-noentropy_msg\n";
	print STDERR "\t\t-savekeys\n";
	print STDERR "\t\t-nosavekeys\n\n";

	print STDERR "\t\t-usegui\n";
	print STDERR "\t\t-nousegui\n\n";

	print STDERR "\t\t-roll-logfile <logfile>\n";
	print STDERR "\t\t-roll-loglevel <loglevel>\n";
	print STDERR "\t\t-roll-sleep <sleep-time>\n\n";

	print STDERR "\t\t-ta-contact <contact email>\n";
	print STDERR "\t\t-ta-smtpserver <hostname>\n\n";

	print STDERR "\t\t-outfile <conffile>\n";
	print STDERR "\t\t-overwrite\n";
	print STDERR "\t\t-noprompt\n";
	print STDERR "\t\t-edit\n";
	print STDERR "\t\t-verbose\n";
	print STDERR "\t\t-Version\n";
	print STDERR "\t\t-help\n";

	exit(0);
}

1;

##############################################################################
#

=pod

=head1 NAME

dtinitconf - Creates a DNSSEC-Tools configuration file

=head1 SYNOPSIS

  dtinitconf [options]

=head1 DESCRIPTION

The B<dtinitconf> program initializes the DNSSEC-Tools configuration file.
By default, the actual configuration file will be created, though the created
file can be specified by the user.  Existing files, whether the default or one
specified by the user, will not be overwritten unless specifically directed
by the user.

Each configuration field can be individually specified on the command line.
The user will also be prompted for the fields, with default values taken from
the DNSSEC-Tools B<defaults.pm> module.  If the I<-noprompt> option is given,
then a default configuration file (modulo command-line arguments) will be
created.

Configuration entries are created for several BIND programs.  Several
locations on the system are searched to find the locations of these programs. 
First, the directories in the path environment variable are checked; the
names of any directories that contain the BIND programs are saved.  Next,
several common locations for BIND programs are checked; again, the names of
directories that contain the BIND programs are saved.  After collecting these
directories, the user is presented with this list and may choose to use
whichever set is desired.  If no directories are found that contain the BIND
programs, the user is prompted for the proper location.

If the configuration file's parent directory does not exist, then an attempt
is made to create the directory.  The new directory's ownership will be set
to I<root> for the owner and I<dnssec> for the group, assuming the I<dnssec>
group exists.

=head1 OPTIONS

B<dtinitconf> takes options that control the contents of the newly generated
DNSSEC-Tools configuration file.  Each configuration file entry has a
corresponding command-line option.  The options, described below, are ordered
in logical groups.

=head2 Key-related Options

These options deal with different aspects of creating and managing
encryption keys.

=over 4

=item I<-algorithm algorithm>

Selects the cryptographic algorithm. The value of algorithm must be one that
is recognized by B<dnssec-keygen>.

=item I<-ksklength keylen>

The default KSK key length to be passed to B<dnssec-keygen>.

=item I<-ksklife lifespan>

The default length of time between KSK roll-overs.  This is measured in   
seconds.

This value is B<only> used for key roll-over.  Keys do not have a life-time
in any other sense.

=item I<-zskcount ZSK-count>

The default number of ZSK keys that will be created for a zone.

=item I<-zsklength keylen>

The default ZSK key length to be passed to B<dnssec-keygen>.

=item I<-zsklife lifespan>

The default length of time between ZSK roll-overs.  This is measured in   
seconds.

This value is B<only> used for key roll-over.  Keys do not have a life-time
in any other sense.

=item I<-random randomdev>

The random device generator to be passed to B<dnssec-keygen>.

=back

=head2 Zone-related Options

These options deal with different aspects of zone signing.

=over 4

=item I<-endtime endtime>

The zone default expiration time to be passed to B<dnssec-signzone>.

=back

=head2 DNSSEC-Tools Options

These options deal specifically with functionality provided by DNSSEC-Tools.

=over 4

=item I<-admin email-address>

B<admin> is the email address of the DNSSEC-Tools administrator.  This is the
default address used by the I<dt_adminmail()> routine.

=item I<-archivedir directory>

B<directory> is the archived-key directory.  Old encryption keys are moved to
this directory, but only if they are to be saved and not deleted.

=item I<-binddir directory>

B<directory> is the directory holding the BIND programs.

=item I<-entropy_msg>

A flag indicating that B<zonesigner> should display a message about entropy
generation.  This is primarily dependent on the implementation of a system's
random number generation.

=item I<-noentropy_msg>

A flag indicating that B<zonesigner> should not display a message about
entropy generation.  This is primarily dependent on the implementation of
a system's random number generation.

=item I<-roll-logfile logfile>

B<logfile> is the logfile for the B<rollerd> daemon.

=item I<-roll-loglevel loglevel>

B<loglevel> is the logging level for the B<rollerd> daemon.

=item I<-roll-sleep sleep-time>

B<sleep-time> is the sleep-time for the B<rollerd> daemon.

=item I<-savekeys>

A flag indicating that old keys should be moved to the archive directory.

=item I<-nosavekeys>

A flag indicating that old keys should not be moved to the archive directory
but will instead be left in place.

=item I<-usegui>

A flag indicating that the GUI for specifying command options may be used.

=item I<-nousegui>

A flag indicating that the GUI for specifying command options should not be
used.

=back

=head2 dtinitconf Options

These options deal specifically with B<dtinitconf>.

=over 4

=item I<-outfile conffile>

The configuration file will be written to B<conffile>.  If this is
not given, then the default configuration file (as returned by
I<Net::DNS::SEC::Tools::conf::getconffile()>) will be used.

If B<conffile> is given as B<->, then the new configuration file will be
written to the standard output.

B<conffile> must be writable.

=item I<-overwrite>

If I<-overwrite> is specified, existing output files may be overwritten.
Without I<-overwrite>, if the output file is found to exist then B<dtinitconf>
will give an error message and exit.

=item I<-noprompt>

If I<-noprompt> is specified, the user will not be prompted for any input.
The configuration file will be created from command-line options and
DNSSEC-Tools defaults.  Guesses will be made for the BIND paths, based on
the PATH environment variable.

B<WARNING>:  After using the I<-noprompt> option, the configuration file
B<must> be checked to ensure that the defaults are appropriate and acceptable
for the installation.

=item I<-edit>

If I<-edit> is specified, the output file will be edited after it has been
created.  The EDITOR environment variable is consulted for the editor to
use.  If the EDITOR environment variable isn't defined, then the B<vi>
editor will be used.

=item I<-verbose>

Provide verbose output.

=item I<-help>

Display a usage message and exit.

=back

=head1 COPYRIGHT

Copyright 2006-2008 SPARTA, Inc.  All rights reserved.  See the COPYING file
included with the DNSSEC-Tools package for details.

=head1 AUTHOR

Wayne Morrison, tewok@users.sourceforge.net

=head1 SEE ALSO

B<dnssec-keygen(8)>,
B<dnssec-signzone(8)>,
B<named-checkzone(8)>,
B<rollerd(8)>,
B<zonesigner(8)>

B<Net::DNS::SEC::Tools::conf.pm(3)>,
B<Net::DNS::SEC::Tools::defaults.pm(3)>,
B<Net::DNS::SEC::Tools::dnssectools.pm(3)>,
B<Net::DNS::SEC::Tools::tooloptions.pm(3)>,
B<QWizard.pm(3)>

B<dnssec-tools.conf(5)>

=cut
