From faaa22ecca9f8141a16aec0e1761ab3dcbd3e6eb Mon Sep 17 00:00:00 2001 From: Jamie Cameron Date: Tue, 5 May 2009 01:16:34 +0000 Subject: [PATCH] Yet more work on LDAP and LDIF --- ldap-server/acl_save.cgi | 4 +- ldap-server/config-Ubuntu-Linux-8.10-* | 2 +- ldap-server/delete_acls.cgi | 4 +- ldap-server/down_acl.cgi | 4 +- ldap-server/down_schema.cgi | 4 +- ldap-server/gencert.cgi | 4 +- ldap-server/gencert_form.cgi | 6 +- ldap-server/gencert_ldif.cgi | 43 ++++++++++++ ldap-server/ldap-server-lib.pl | 69 ++++++++++++++++++- ldap-server/save_ldif.cgi | 94 ++++++++++++++++++++++++++ ldap-server/save_schema.cgi | 4 +- ldap-server/save_slapd.cgi | 4 +- ldap-server/up_acl.cgi | 4 +- ldap-server/up_schema.cgi | 4 +- 14 files changed, 228 insertions(+), 22 deletions(-) create mode 100755 ldap-server/gencert_ldif.cgi create mode 100755 ldap-server/save_ldif.cgi diff --git a/ldap-server/acl_save.cgi b/ldap-server/acl_save.cgi index a410df494..b45e71234 100644 --- a/ldap-server/acl_save.cgi +++ b/ldap-server/acl_save.cgi @@ -8,7 +8,7 @@ $access{'acl'} || &error($text{'acl_ecannot'}); &ReadParse(); # Get the current rule -&lock_file($config{'config_file'}); +&lock_slapd_files(); $conf = &get_config(); @access = &find("access", $conf); if (!$in{'new'}) { @@ -85,7 +85,7 @@ else { # Write out access directives &save_directive($conf, "access", @access); &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); # Log and return &webmin_log($in{'delete'} ? "delete" : $in{'new'} ? "create" : "modify", diff --git a/ldap-server/config-Ubuntu-Linux-8.10-* b/ldap-server/config-Ubuntu-Linux-8.10-* index 1c5f04a09..af45b09a5 100644 --- a/ldap-server/config-Ubuntu-Linux-8.10-* +++ b/ldap-server/config-Ubuntu-Linux-8.10-* @@ -1,7 +1,7 @@ config_file=/etc/ldap/slapd.d schema_dir=/etc/ldap/slapd.d/cn=config/cn=schema slapd=slapd -ldap_user=ldap +ldap_user=openldap browse_max=100 start_cmd=/etc/init.d/slapd start stop_cmd=/etc/init.d/slapd stop diff --git a/ldap-server/delete_acls.cgi b/ldap-server/delete_acls.cgi index f95c87e09..6bc122de2 100644 --- a/ldap-server/delete_acls.cgi +++ b/ldap-server/delete_acls.cgi @@ -8,7 +8,7 @@ $access{'acl'} || &error($text{'acl_ecannot'}); &ReadParse(); # Filter out un-wanted rules -&lock_file($config{'config_file'}); +&lock_slapd_files(); $conf = &get_config(); @access = &find("access", $conf); %d = map { $_, 1 } split(/\0/, $in{'d'}); @@ -20,7 +20,7 @@ for($i=0; $i<@access; $i++) { # Save them &save_directive($conf, "access", @newaccess); &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); &webmin_log("delete", "accesses", scalar(keys(%d))); &redirect("edit_acl.cgi"); diff --git a/ldap-server/down_acl.cgi b/ldap-server/down_acl.cgi index e3f8e62e0..fb94ec866 100644 --- a/ldap-server/down_acl.cgi +++ b/ldap-server/down_acl.cgi @@ -7,7 +7,7 @@ $access{'acl'} || &error($text{'acl_ecannot'}); &ReadParse(); # Find it -&lock_file($config{'config_file'}); +&lock_slapd_files(); $conf = &get_config(); @access = &find("access", $conf); $p = &parse_ldap_access($access[$in{'idx'}]); @@ -17,7 +17,7 @@ $p = &parse_ldap_access($access[$in{'idx'}]); ($access[$in{'idx'}], $access[$in{'idx'}+1]); &save_directive($conf, "access", @access); &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); &webmin_log("down", "access", $p->{'what'}); &redirect("edit_acl.cgi"); diff --git a/ldap-server/down_schema.cgi b/ldap-server/down_schema.cgi index 3edafe12e..f38173a5c 100644 --- a/ldap-server/down_schema.cgi +++ b/ldap-server/down_schema.cgi @@ -7,7 +7,7 @@ $access{'schema'} || &error($text{'schema_ecannot'}); &ReadParse(); # Find it includes -&lock_file($config{'config_file'}); +&lock_slapd_files(); $conf = &get_config(); @incs = &find_value("include", $conf); $idx = &indexof($in{'file'}, @incs); @@ -17,7 +17,7 @@ $idx > 0 || &error($text{'schema_emove'}); ($incs[$idx+1], $incs[$idx]) = ($incs[$idx], $incs[$idx+1]); &save_directive($conf, "include", @incs); &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); &webmin_log("sup", undef, $in{'file'}); &redirect("edit_schema.cgi"); diff --git a/ldap-server/gencert.cgi b/ldap-server/gencert.cgi index 0a93364cb..c520daad5 100644 --- a/ldap-server/gencert.cgi +++ b/ldap-server/gencert.cgi @@ -31,11 +31,11 @@ $err = &webmin::parse_ssl_key_form(\%in, $keyfile, $keyfile, $certfile); # Update config to use them -&lock_file($config{'config_file'}); +&lock_slapd_files(); &save_directive($conf, "TLSCertificateFile", $certfile); &save_directive($conf, "TLSCertificateKeyFile", $keyfile); &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); &webmin_log("gencert"); &redirect(""); diff --git a/ldap-server/gencert_form.cgi b/ldap-server/gencert_form.cgi index 39da0ab8c..04de28732 100644 --- a/ldap-server/gencert_form.cgi +++ b/ldap-server/gencert_form.cgi @@ -9,7 +9,8 @@ $access{'slapd'} || &error($text{'slapd_ecannot'}); &ui_print_header(undef, $text{'gencert_title'}, ""); print $text{'gencert_desc'},"

\n"; -print &ui_form_start("gencert.cgi", "post"); +print &ui_form_start(&get_config_type() == 1 ? "gencert.cgi" + : "gencert_ldif.cgi", "post"); print &ui_table_start($text{'gencert_header'}, undef, 2, [ "width=30%" ]); # Generic key options @@ -24,7 +25,8 @@ if (&get_config_type() == 1) { } else { $conf = &get_ldif_config(); - $cert = &find_ldif_value($s->[0], $conf, &get_config_db()); + $cert = &find_ldif_value( + "olcTLSCertificateFile", $conf, &get_config_db()); } if ($cert) { print &ui_table_row($text{'gencert_dest'}, diff --git a/ldap-server/gencert_ldif.cgi b/ldap-server/gencert_ldif.cgi new file mode 100755 index 000000000..eb0d32ff8 --- /dev/null +++ b/ldap-server/gencert_ldif.cgi @@ -0,0 +1,43 @@ +#!/usr/local/bin/perl +# Actually generate the cert, and update the LDIF format config file + +require './ldap-server-lib.pl'; +&local_ldap_server() == 1 || &error($text{'slapd_elocal'}); +$access{'slapd'} || &error($text{'slapd_ecannot'}); +&foreign_require("webmin", "webmin-lib.pl"); +&ReadParse(); +&error_setup($text{'gencert_err'}); +$conf = &get_ldif_config(); +$confdb = &get_config_db(); + +# Work out dest files +if ($in{'dest_def'}) { + $keyfile = &find_ldif_value("olcTLSCertificateKeyFile", $conf, $confdb); + $certfile = &find_ldif_value("olcTLSCertificateFile", $conf, $confdb); + } +else { + # In some dir + -d $in{'dest'} || &error($text{'gencert_edest'}); + $keyfile = $in{'dest'}."/ldap.key"; + $certfile = $in{'dest'}."/ldap.cert"; + } + +# Do it +$err = &webmin::parse_ssl_key_form(\%in, $keyfile, + $certfile eq $keyfile ? undef : $certfile); +&error($err) if ($err); + +# Make readable by LDAP user +&set_ownership_permissions($config{'ldap_user'}, undef, undef, + $keyfile, $certfile); + +# Update config to use them +&lock_slapd_files(); +&save_ldif_directive($conf, "olcTLSCertificateFile", $confdb, $certfile); +&save_ldif_directive($conf, "olcTLSCertificateKeyFile", $confdb, $keyfile); +&flush_file_lines(); +&unlock_slapd_files(); + +&webmin_log("gencert"); +&redirect(""); + diff --git a/ldap-server/ldap-server-lib.pl b/ldap-server/ldap-server-lib.pl index 9765353c8..fbf1dfdf1 100644 --- a/ldap-server/ldap-server-lib.pl +++ b/ldap-server/ldap-server-lib.pl @@ -411,7 +411,49 @@ if (@old) { $file = $old[0]->{'file'}; } else { - # XXX file for first directive of that class + local ($first) = grep { lc($_->{'class'}) eq lc($cls) } @$conf; + $first || &error("No LDIF-format config file found for $cls"); + $file = $first->{'file'}; + } +local $lref = &read_file_lines($file); +for(my $i=0; $i<@old || $i<@values; $i++) { + local ($line, @unqvalues, @qvalues, $len); + if (defined($values[$i])) { + # Work out new line + @unqvalues = ref($values[$i]) eq 'ARRAY' ? + @{$values[$i]} : + ref($values[$i]) eq 'HASH' ? + @{$values[$i]->{'values'}} : + ( $values[$i] ); + $line = $name.": ".join(" ", @unqvalues); + } + if (defined($old[$i]) && defined($values[$i])) { + # Update some directive + $lref->[$old[$i]->{'line'}] = $line; + if (&indexof($values[$i], @$conf) < 0) { + $old[$i]->{'values'} = \@unqvalues; + } + } + elsif (defined($old[$i]) && !defined($values[$i])) { + # Remove some directive (from cache too) + splice(@$lref, $old[$i]->{'line'}, 1); + local $idx = &indexof($old[$i], @$conf); + splice(@$conf, $idx, 1) if ($idx >= 0); + foreach my $c (@$conf) { + if ($c->{'line'} > $old[$i]->{'line'}) { + $c->{'line'} --; + } + } + } + elsif (!defined($old[$i]) && defined($values[$i])) { + # Add some directive + local $newdir = { 'name' => $name, + 'line' => scalar(@$lref), + 'file' => $file, + 'values' => \@unqvalues }; + push(@$lref, $line); + push(@$conf, $newdir); + } } } @@ -756,5 +798,30 @@ elsif (&get_config_type() == 2) { return undef; } +# lock_slapd_files() +# Lock all LDAP config file(s) +sub lock_slapd_files +{ +if (&get_config_type() == 2) { + @ldap_lock_files = &recursive_find_ldif($config{'config_file'}); + } +else { + @ldap_lock_files = ( $config{'config_file'} ); + } +foreach my $f (@ldap_lock_files) { + &lock_file($f); + } +} + +# unlock_slapd_files() +# Un-lock all LDAP config file(s) +sub unlock_slapd_files +{ +foreach my $f (@ldap_lock_files) { + &lock_file($f); + } +@ldap_lock_files = ( ); +} + 1; diff --git a/ldap-server/save_ldif.cgi b/ldap-server/save_ldif.cgi new file mode 100755 index 000000000..fe8c81e33 --- /dev/null +++ b/ldap-server/save_ldif.cgi @@ -0,0 +1,94 @@ +#!/usr/local/bin/perl +# Update local LDAP server LDIF file configuration options + +require './ldap-server-lib.pl'; +&error_setup($text{'slapd_err'}); +$access{'slapd'} || &error($text{'slapd_ecannot'}); +&local_ldap_server() == 1 || &error($text{'slapd_elocal'}); +&ReadParse(); + +&lock_slapd_files(); +$conf = &get_ldif_config(); + +# Validate and store inputs + +# Top-level DN +$defdb = &get_default_db(); +$in{'suffix'} =~ /=/ || &error($text{'slapd_esuffix'}); +&save_ldif_directive($conf, 'olcSuffix', $defdb, $in{'suffix'}); + +# Admin login +$in{'rootdn'} =~ /=/ || &error($text{'slapd_erootdn'}); +&save_ldif_directive($conf, 'olcRootDN', $defdb, $in{'rootdn'}); + +# Admin password +if (!$in{'rootchange_def'}) { + $in{'rootchange'} =~ /\S/ || &error($text{'slapd_erootpw'}); + $crypt = &unix_crypt($in{'rootchange'}, substr(time(), -2)); + &save_ldif_directive($conf, 'olcRootPW', $defdb, "{crypt}".$crypt); + $config{'pass'} = $in{'rootchange'}; + $save_config = 1; + } + +# Cache sizes +if (!$in{'dbcachesize_def'}) { + $in{'dbcachesize'} =~ /^\d+$/ || &error($text{'slapd_edbcachesize'}); + &save_ldif_directive($conf, 'olcDbCachesize', $defdb, + $in{'dbcachesize'}); + } +else { + &save_ldif_directive($conf, 'olcDbCachesize', $defdb, undef); + } + +# Size limit +if ($in{'sizelimit_def'}) { + &save_ldif_directive($conf, 'olcSizeLimit', $defdb, undef); + } +else { + $in{'sizelimit'} =~ /^[1-9]\d*$/ || &error($text{'slapd_esizelimit'}); + &save_ldif_directive($conf, 'olcSizeLimit', $defdb, $in{'sizelimit'}); + } + +# LDAP protocols +if (&can_get_ldap_protocols()) { + @newprotos = split(/\0/, $in{'protos'}); + @newprotos || &error($text{'slapd_eprotos'}); + } + +# SSL file options +$confdb = &get_config_db(); +foreach $s ([ 'olcTLSCertificateFile', 'cert' ], + [ 'olcTLSCertificateKeyFile', 'key' ], + [ 'olcTLSCACertificateFile', 'ca' ]) { + if ($in{$s->[1].'_def'}) { + &save_ldif_directive($conf, $s->[0], $confdb, undef); + } + else { + &valid_pem_file($in{$s->[1]}, $s->[1]) || + &error($text{'slapd_e'.$s->[1]}); + &save_ldif_directive($conf, $s->[0], $confdb, $in{$s->[1]}); + } + } + +# Write out the files +&flush_file_lines(); +&unlock_slapd_files(); +if ($save_config) { + &lock_file($module_config_file); + &save_module_config(); + &unlock_file($module_config_file); + } +if (&can_get_ldap_protocols()) { + $protos = &get_ldap_protocols(); + foreach $p (keys %$protos) { + $protos->{$p} = 0; + } + foreach $p (@newprotos) { + $protos->{$p} = 1; + } + &save_ldap_protocols($protos); + } +&webmin_log('slapd'); + +&redirect(""); + diff --git a/ldap-server/save_schema.cgi b/ldap-server/save_schema.cgi index b42419213..8a4c50455 100644 --- a/ldap-server/save_schema.cgi +++ b/ldap-server/save_schema.cgi @@ -21,10 +21,10 @@ push(@incs, split(/\0/, $in{'d'})); @incs = &unique(@incs); # Write out -&lock_file($config{'config_file'}); +&lock_slapd_files(); &save_directive($conf, "include", @incs); &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); &webmin_log("schema"); &redirect(""); diff --git a/ldap-server/save_slapd.cgi b/ldap-server/save_slapd.cgi index e5e814394..64d82da69 100644 --- a/ldap-server/save_slapd.cgi +++ b/ldap-server/save_slapd.cgi @@ -7,7 +7,7 @@ $access{'slapd'} || &error($text{'slapd_ecannot'}); &local_ldap_server() == 1 || &error($text{'slapd_elocal'}); &ReadParse(); -&lock_file($config{'config_file'}); +&lock_slapd_files(); $conf = &get_config(); # Validate and store inputs @@ -87,7 +87,7 @@ foreach $s ([ 'TLSCertificateFile', 'cert' ], # Write out the files &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); if ($save_config) { &lock_file($module_config_file); &save_module_config(); diff --git a/ldap-server/up_acl.cgi b/ldap-server/up_acl.cgi index be6692b34..659816af2 100644 --- a/ldap-server/up_acl.cgi +++ b/ldap-server/up_acl.cgi @@ -7,7 +7,7 @@ $access{'acl'} || &error($text{'acl_ecannot'}); &ReadParse(); # Find it -&lock_file($config{'config_file'}); +&lock_slapd_files(); $conf = &get_config(); @access = &find("access", $conf); $p = &parse_ldap_access($access[$in{'idx'}]); @@ -17,7 +17,7 @@ $p = &parse_ldap_access($access[$in{'idx'}]); ($access[$in{'idx'}], $access[$in{'idx'}-1]); &save_directive($conf, "access", @access); &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); &webmin_log("up", "access", $p->{'what'}); &redirect("edit_acl.cgi"); diff --git a/ldap-server/up_schema.cgi b/ldap-server/up_schema.cgi index ae477473f..bb0e9be10 100644 --- a/ldap-server/up_schema.cgi +++ b/ldap-server/up_schema.cgi @@ -7,7 +7,7 @@ $access{'schema'} || &error($text{'schema_ecannot'}); &ReadParse(); # Find it includes -&lock_file($config{'config_file'}); +&lock_slapd_files(); $conf = &get_config(); @incs = &find_value("include", $conf); $idx = &indexof($in{'file'}, @incs); @@ -17,7 +17,7 @@ $idx > 0 || &error($text{'schema_emove'}); ($incs[$idx-1], $incs[$idx]) = ($incs[$idx], $incs[$idx-1]); &save_directive($conf, "include", @incs); &flush_file_lines($config{'config_file'}); -&unlock_file($config{'config_file'}); +&unlock_slapd_files(); &webmin_log("sup", undef, $in{'file'}); &redirect("edit_schema.cgi");