summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRich Megginson <rmeggins@redhat.com>2007-06-07 22:40:14 +0000
committerRich Megginson <rmeggins@redhat.com>2007-06-07 22:40:14 +0000
commit6fbde87fb096a7919796c9568463a0411bb80b1e (patch)
treebbee049e5715f3bf1b79ed3d556b38e303aec7f9
parenteba4de83e9a81055b1eb83187fe7f1bcda728e0e (diff)
downloadds-6fbde87fb096a7919796c9568463a0411bb80b1e.tar.gz
ds-6fbde87fb096a7919796c9568463a0411bb80b1e.tar.xz
ds-6fbde87fb096a7919796c9568463a0411bb80b1e.zip
Resolves: bug 243205
Description: allow instance creation with no .inf file; allow pre-hashed RootDNPwd Reviewed by: nhosoi (Thanks!) Fix Description: You can now use ds_newinst.pl without (or with) a .inf file like this: ds_newinst.pl General.SuiteSpotUserID=nobody slapd.ServerPort=3890 .... The parameters can be supplied via the command line. The format of the parameter is section.param=value. Normal shell quoting rules apply, so you still have to do something like this: ds_newinst.pl "slapd.Suffix=dc=example, dc=com" for embedded spaces and the like. If you supply a filename (or '-'), it must be the first argument after ds_newinst.pl. If you then supply additional arguments after the filename, these will override the settings in the given inf file. So, for example, you could reuse the same .inf file, except provide a different hostname: ds_newinst.pl basefile.inf General.FullMachineName=bar.example.com This allows you to use the same base .inf file for several machines, and only change certain parameters on a per-machine basis. ds_newinst.pl will now fill in some default values - it will use Net::Domain::hostfqdn for FullMachineName, and your login ID for SuiteSpotUserID (however, not if running ds_newinst.pl as root), and will construct the Suffix and ServerIdentifier based on the FullMachineName. RootDN will default to cn=Directory Manager. ServerRoot is no longer required. Another enhancement is the ability to provide a pre-hashed password for the RootDNPwd parameter, to avoid having to pass around the clear text directory manager password. However, some caveats apply. If the password begins with one of the well known hash algorithms (e.g. {SHA, {SSHA, etc.), ds_newinst will assume it is already hashed. This may cause problems if users expect to be able to provide a clear text password such as {SSHA}text, but I seriously doubt anyone does that (famous last words . . .). Another problem is that the code as it currently stands uses the clear text password to bind to the server after starting the server to add some additional entries and ACIs. This cannot be done if a pre-hashed password is provided (but we're working on a solution to that problem too). write_ldap_info() is no longer needed. Finally, a couple of minor bug fixes. Platforms tested: RHEL4 Flag Day: no Doc impact: Yes. There will be some documentation changes required.
-rw-r--r--ldap/admin/src/cfg_sspt.c39
-rw-r--r--ldap/admin/src/create_instance.c72
-rw-r--r--ldap/admin/src/ds_newinst.pl.in150
3 files changed, 133 insertions, 128 deletions
diff --git a/ldap/admin/src/cfg_sspt.c b/ldap/admin/src/cfg_sspt.c
index 5d6028c3..553fc6e7 100644
--- a/ldap/admin/src/cfg_sspt.c
+++ b/ldap/admin/src/cfg_sspt.c
@@ -1362,39 +1362,6 @@ do_bind(SLAPD_CONFIG* slapd, char* rootdn, char* rootpw)
return connection;
}
-static int
-write_ldap_info(SLAPD_CONFIG* slapd, char* base, char* admnm)
-{
- FILE* fp;
- int ret = 0;
-
- char* fmt = "%s/shared/config/ldap.conf";
- char* infoFileName = PR_smprintf(fmt, slapd->slapd_server_root);
-
- if ((fp = fopen(infoFileName, "w")) == NULL)
- {
- ret = -1;
- }
- else
- {
- fprintf(fp, "url\tldap://%s:%d/",
- slapd->host, slapd->port);
-
- if (base)
- fprintf(fp, "%s", base);
-
- fprintf(fp, "\n");
-
- fprintf(fp, "admnm\t%s\n", admnm);
-
- fclose(fp);
- }
-
- PR_smprintf_free(infoFileName);
-
- return ret;
-}
-
#ifdef TEST_CONFIG
int
config_configEntry(LDAP* connection, QUERY_VARS* query)
@@ -1630,12 +1597,6 @@ config_suitespot(SLAPD_CONFIG* slapd, QUERY_VARS* query)
value_hostPreferencesOU, 0,
0, 0, 0);
}
-
- /*
- ** Write the ldap.info file and the SuiteSpot.ldif file
- */
-
- write_ldap_info(slapd, query->suffix, query->ssAdmID);
}
#ifdef TEST_CONFIG
diff --git a/ldap/admin/src/create_instance.c b/ldap/admin/src/create_instance.c
index 9a97f2bb..52e85bde 100644
--- a/ldap/admin/src/create_instance.c
+++ b/ldap/admin/src/create_instance.c
@@ -144,7 +144,6 @@ static char *ds_gen_orgchart_conf(char *sroot, char *cs_path, server_config_s *c
static char *ds_gen_gw_conf(char *sroot, char *cs_path, server_config_s *cf, int conf_type);
static char *install_ds(char *sroot, server_config_s *cf, char *param_name);
-static int write_ldap_info(char *slapd_server_root, server_config_s *cf);
#if defined (BUILD_PRESENCE)
static char *gen_presence_init_script(char *sroot, server_config_s *cf,
char *cs_path);
@@ -4123,9 +4122,6 @@ static char *install_ds(char *sroot, server_config_s *cf, char *param_name)
}
}
- /* write ldap.conf */
- write_ldap_info( sroot, cf );
-
#ifdef XP_UNIX
ds_become_localuser_name (cf->servuser);
#endif
@@ -4143,6 +4139,17 @@ static char *install_ds(char *sroot, server_config_s *cf, char *param_name)
}
#endif /* XP_WIN32 */
+ /* if an already hashed password is given, we cannot do the configure_suitespot()
+ stuff below, because that requires the clear text password in order to
+ bind to the server. This also means that default entries and default
+ acis will not be added to the server.
+ */
+ if (cf->rootpw == cf->roothashedpw) {
+ if (status)
+ return make_error ("Could not configure server (%d).", status);
+ return NULL;
+ }
+
memset( &query_vars, 0, sizeof(query_vars) );
if (!cf->use_existing_user_ds)
query_vars.suffix = create_instance_strdup( cf->suffix );
@@ -4199,48 +4206,6 @@ static char *install_ds(char *sroot, server_config_s *cf, char *param_name)
return(NULL);
}
-/* write_ldap_info() : writes ldap.conf */
-
-static int
-write_ldap_info( char *slapd_server_root, server_config_s *cf)
-{
- FILE* fp;
- int ret = 0;
-
- char* fmt = "%s/shared/config/ldap.conf";
- char* infoFileName;
-
- if (!slapd_server_root) {
- return -1;
- }
-
- infoFileName = PR_smprintf(fmt, slapd_server_root);
-
- if ((fp = fopen(infoFileName, "w")) == NULL)
- {
- ret = -1;
- }
- else
- {
- fprintf(fp, "url\tldap://%s:%d/",
- cf->servname, atoi(cf->servport));
-
- if (cf->suffix)
- fprintf(fp, "%s", cf->suffix);
-
- fprintf(fp, "\n");
-
- if (cf->cfg_sspt_uid) {
- fprintf(fp, "admnm\t%s\n", cf->cfg_sspt_uid);
- }
-
- fclose(fp);
- }
- PR_smprintf_free(infoFileName);
-
- return ret;
-}
-
/* ----------- Create a new server from configuration variables ----------- */
@@ -4542,8 +4507,17 @@ int parse_form(server_config_s *cf)
cf->rootpw = pw1;
}
- /* Encode the password in SSHA by default */
- cf->roothashedpw = (char *)ds_salted_sha1_pw_enc (cf->rootpw);
+ if (strchr(cf->rootpw, '}') &&
+ (!PL_strncasecmp(cf->rootpw, "{SHA", 4) ||
+ !PL_strncasecmp(cf->rootpw, "{SSHA", 5) ||
+ !PL_strncasecmp(cf->rootpw, "{CRYPT}", 7) ||
+ !PL_strncasecmp(cf->rootpw, "{MD5}", 5))) {
+ /* assume the password is already hashed */
+ cf->roothashedpw = cf->rootpw;
+ } else { /* assume cleartext password */
+ /* Encode the password in SSHA by default */
+ cf->roothashedpw = (char *)ds_salted_sha1_pw_enc (cf->rootpw);
+ }
}
cf->admin_domain = ds_a_get_cgi_var("admin_domain", NULL, NULL);
@@ -4555,7 +4529,7 @@ int parse_form(server_config_s *cf)
}
if ((temp = ds_a_get_cgi_var("use_existing_user_ds", NULL, NULL))) {
- cf->use_existing_config_ds = atoi(temp);
+ cf->use_existing_user_ds = atoi(temp);
} else {
cf->use_existing_user_ds = 0; /* we are creating it */
}
diff --git a/ldap/admin/src/ds_newinst.pl.in b/ldap/admin/src/ds_newinst.pl.in
index bc05b5e1..5c355656 100644
--- a/ldap/admin/src/ds_newinst.pl.in
+++ b/ldap/admin/src/ds_newinst.pl.in
@@ -35,6 +35,7 @@
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
+use Net::Domain qw(hostfqdn);
use IPC::Open2;
use Symbol;
use CGI::Util qw(escape);
@@ -43,9 +44,28 @@ use File::Basename;
sub usage {
my $msg = shift;
- print "Error: $msg\n";
- print "Usage: $0 [-|filename.inf]\n";
- print "Use - to read from stdin\n";
+ print <<EOF;
+Error: $msg
+Usage: $0 [-|filename.inf] [args]
+The filename, if any, should be specified first. After the filename, other args
+can be provided to override settings in the provided file in this format:
+ section.param=value
+e.g.
+ General.FullMachineName=foo.example.com
+or
+ "slapd.Suffix=dc=example, dc=com"
+
+So, for example, if you use
+ $0 filename.inf General.FullMachineName=bar.example.com
+And your filename.inf file has
+ [General]
+ FullMachineName= foo.example.com
+$0 will use bar.example.com for FullMachineName since that was the one passed on the command line
+
+$0 will attempt to generate reasonable default values for some of the parameters, but there are a couple that must be specified:
+ slapd.ServerPort slapd.RootDNPwd
+Also General.SuiteSpotUserID must be specified if running as root. If not running as root, the uid of the user will be used.
+EOF
exit 1
}
@@ -69,7 +89,7 @@ sub getCgiContentAndLength {
# fakes out the ds_newinst program into thinking it is getting cgi input
sub cgiFake {
- my ($sroot, $verbose, $prog, $args) = @_;
+ my ($verbose, $prog, $args) = @_;
# construct content string
my ($content, $length) = &getCgiContentAndLength($args);
@@ -87,9 +107,12 @@ sub cgiFake {
chdir $dir;
my $input = gensym();
my $output = gensym();
+ # make sure the child exit code is reset before starting the fake
+ # cgi program
+ $? = 0;
my $pid = open2($input, $output, "./$exe");
sleep(1); # allow prog to init stdin read buffers
- print $output $content, "\n";
+ print $output $content;
close $output;
if ($?) {
@@ -136,48 +159,81 @@ sub addAndCheck {
$dest->{$dkey} = $source->{$ssec}->{$skey};
}
-my $filename = $ARGV[0];
-usage("$filename not found") if ($filename ne "-" && ! -f $filename);
+sub readInfFile {
+ my $filename = shift;
+ my $fh;
+ if ($filename eq "-") {
+ $fh = \*STDIN;
+ } else {
+ open(IN, $filename) or usage("could not open file $filename: $!");
+ $fh = \*IN;
+ }
+ while (<$fh>) {
+ # e.g. [General]
+ if (/^\[(.*?)\]/) {
+ $curSection = $1;
+ } elsif (/^\s*$/) {
+ next; # skip blank lines
+ } elsif (/^\s*\#/) {
+ next; # skip comment lines
+ } elsif (/^\s*(.*?)\s*=\s*(.*?)\s*$/) {
+ $table{$curSection}->{$1} = $2;
+ }
+ }
+ if ($filename ne "-") {
+ close IN;
+ }
+}
-my $curSection;
-# each key in the table is a section name
-# the value is a hash ref of the items in that section
-# in that hash ref, each key is the config param name,
-# and the value is the config param value
-my %table = ();
+usage("No arguments given") if (!@ARGV);
-my $fh;
-if ($filename eq "-") {
- $fh = \*STDIN;
-} else {
- open(IN, $filename);
- $fh = \*IN;
+# process command line arguments
+for (@ARGV) {
+ if (/^(\w+).(\w+)=(.*)$/) { # e.g. section.param=value
+ $table{$1}->{$2} = $3;
+ } else { # file?
+ readInfFile($_);
+ }
}
-while (<$fh>) {
- # e.g. [General]
- if (/^\[(.*?)\]/) {
- $curSection = $1;
- } elsif (/^\s*$/) {
- next; # skip blank lines
- } elsif (/^\s*\#/) {
- next; # skip comment lines
- } elsif (/^\s*(.*?)\s*=\s*(.*?)\s*$/) {
- $table{$curSection}->{$1} = $2;
- }
+
+#printhash (\%table);
+
+# set default values
+if (!$table{General}->{FullMachineName}) {
+ $table{General}->{FullMachineName} = hostfqdn;
}
-if ($filename ne "-") {
- close IN;
+
+if (!$table{General}->{SuiteSpotUserID}) {
+ if ($> != 0) { # if not root, use the user's uid
+ $table{General}->{SuiteSpotUserID} = getlogin;
+ }
+ # otherwise, the uid must be specified
}
-#printhash (\%table);
+if (!$table{slapd}->{RootDN}) {
+ $table{slapd}->{RootDN} = "cn=Directory Manager";
+}
+
+if (!$table{slapd}->{Suffix}) {
+ my $suffix = $table{General}->{FullMachineName};
+ # convert fqdn to dc= domain components
+ $suffix = "dc=$suffix";
+ $suffix =~ s/\./, dc=/g;
+ $table{slapd}->{Suffix} = $suffix;
+}
+
+if (!$table{slapd}->{ServerIdentifier}) {
+ my $servid = $table{General}->{FullMachineName};
+ # strip out the leftmost domain component
+ $servid =~ s/\..*$//;
+ $table{slapd}->{ServerIdentifier} = $servid;
+}
# next, construct a hash table with our arguments
my %cgiargs = ();
my $package_name = "@package_name@";
-
# the following items are always required
-addAndCheck(\%cgiargs, "sroot", \%table, "General", "ServerRoot");
addAndCheck(\%cgiargs, "servname", \%table, "General", "FullMachineName");
addAndCheck(\%cgiargs, "servuser", \%table, "General", "SuiteSpotUserID");
addAndCheck(\%cgiargs, "rootdn", \%table, "slapd", "RootDN");
@@ -185,6 +241,12 @@ addAndCheck(\%cgiargs, "rootpw", \%table, "slapd", "RootDNPwd");
addAndCheck(\%cgiargs, "servid", \%table, "slapd", "ServerIdentifier");
addAndCheck(\%cgiargs, "suffix", \%table, "slapd", "Suffix");
+if (defined($table{"General"}->{"ServerRoot"})) {
+ $cgiargs{"sroot"} = $table{"General"}->{"ServerRoot"};
+} else {
+ $cgiargs{"sroot"} = '@serverdir@';
+}
+
# either servport or ldapifilepath must be specified - the server must
# listen to something . . .
my $canlisten = 0;
@@ -200,7 +262,7 @@ if (defined($table{"slapd"}->{"ldapifilepath"})) {
$cgiargs{"ldapifilepath"} = $table{"slapd"}->{"ldapifilepath"};
}
if (! $canlisten) {
- usage("Either ServerPort or ldapifilepath must be specified in the slapd section of $filename");
+ usage("Either ServerPort or ldapifilepath must be specified in the slapd section");
}
# the following items are optional
@@ -227,6 +289,15 @@ if ($table{"slapd"}->{"config_dir"}) {
} else {
$cgiargs{"config_dir"} = "@instconfigdir@/slapd-" . $table{"slapd"}->{"ServerIdentifier"};
}
+
+# check to see if this instance already exists
+if (-d $cgiargs{"config_dir"}) {
+ print STDERR "Error: the server already exists at ", $cgiargs{"config_dir"}, "\n";
+ print STDERR "Please remove it first if you really want to recreate it,\n";
+ print STDERR "or use a different ServerIdentifier to create another instance.\n";
+ exit 1;
+}
+
# port number for Admin Server - used to configure some web apps
$cgiargs{adminport} = $table{admin}->{Port};
@@ -300,15 +371,12 @@ if (defined($table{"slapd"}->{"install_full_schema"})) {
# server-side default is on
}
-my $sroot = $cgiargs{sroot};
-
my $prog = "@bindir@/ds_newinst";
if (! -x $prog) {
$prog = "@libdir@/$package_name/ds_newinst";
}
-my $rc = &cgiFake($sroot, $verbose,
- $prog, \%cgiargs);
+my $rc = &cgiFake($verbose, $prog, \%cgiargs);
if (!$rc) {
print "Success! Your new directory server instance was created\n";
@@ -316,6 +384,8 @@ if (!$rc) {
print "Error: Could not create new directory server instance\n";
}
+exit $rc;
+
sub printhash {
my $table = shift;