From b64c42bf79db4dfd9199828ff74804ec776b2223 Mon Sep 17 00:00:00 2001 From: Jamie Cameron Date: Mon, 1 Dec 2008 22:38:54 +0000 Subject: [PATCH] Field to edit protocol, SSL browsing fix --- ldap-server/CHANGELOG | 3 + ldap-server/edit_slapd.cgi | 11 +++ ldap-server/lang/en | 4 ++ ldap-server/ldap-server-lib.pl | 120 ++++++++++++++++++++++++++++----- ldap-server/save_slapd.cgi | 16 +++++ 5 files changed, 137 insertions(+), 17 deletions(-) diff --git a/ldap-server/CHANGELOG b/ldap-server/CHANGELOG index e1bc205c3..1e2729717 100644 --- a/ldap-server/CHANGELOG +++ b/ldap-server/CHANGELOG @@ -2,3 +2,6 @@ First version of this module, for configuring the OpenLDAP server and managing its database. ---- Changes since 1.400 ---- Added an option to create an example LDAP group, and made the example user a person. +---- Changes since 1.440 ---- +The protocols served by the LDAP server, such as SSL and non-encrypted, can now be set on the OpenLDAP Server Configuration page. This is only possible on Redhat and Debian-derived systems though, as the protocols are configured in the init script. +Fixed a bug that prevented browsing of the LDAP database in SSL mode, thanks to Paul R. Ganci. diff --git a/ldap-server/edit_slapd.cgi b/ldap-server/edit_slapd.cgi index c9c113ae5..026e9f9e3 100644 --- a/ldap-server/edit_slapd.cgi +++ b/ldap-server/edit_slapd.cgi @@ -86,6 +86,17 @@ print &ui_hidden_table_end("basic"); # SSL section print &ui_hidden_table_start($text{'slapd_header2'}, undef, 2, "ssl", 0, \@tds); +# Protocols to serve +if (&can_get_ldap_protocols()) { + $protos = &get_ldap_protocols(); + @protos = sort { $a cmp $b } keys %$protos; + print &ui_table_row($text{'slapd_protos'}, + &ui_select("protos", + [ grep { $protos->{$_} } @protos ], + [ map { [ $_, $text{'slapd_'.$_} ] } @protos ], + scalar(@protos), 1)); + } + # SSL file options $anycert = 0; foreach $s ([ 'TLSCertificateFile', 'cert' ], diff --git a/ldap-server/lang/en b/ldap-server/lang/en index 850f3ce53..2300ce2cc 100644 --- a/ldap-server/lang/en +++ b/ldap-server/lang/en @@ -73,6 +73,10 @@ slapd_gencert=Generate SSL Certificate slapd_gencertdesc=To run your LDAP server in TLS mode, an SSL certificate and private key must first be generated. Click this button to create a self-signed certificate for your system. slapd_gencertwarn=Warning - your existing certificate will no longer be used. slapd_ecannot=You are not allowed to configure the LDAP server +slapd_protos=LDAP connections to accept +slapd_ldap=LDAP over network +slapd_ldaps=LDAP over SSL +slapd_ldapi=Unix socket file schema_title=Manage Schema schema_file=Name diff --git a/ldap-server/ldap-server-lib.pl b/ldap-server/ldap-server-lib.pl index 8b1f90504..b7346b365 100644 --- a/ldap-server/ldap-server-lib.pl +++ b/ldap-server/ldap-server-lib.pl @@ -36,13 +36,13 @@ if ($net_ldap_error) { } # Work out server name, login and TLS mode -local ($server, $port, $user, $pass, $ssl) = @_; +local ($server, $port, $user, $pass, $ssl); if ($config{'server'}) { # Remote box .. everything must be set $server = $config{'server'}; gethostbyname($server) || return &text('connect_eserver', "$server"); - $port = $config{'port'} || 389; + $port = $config{'port'}; $user = $config{'user'}; $user || return $text{'connect_euser'}; $pass = $config{'pass'}; @@ -54,7 +54,7 @@ else { "$config{'config_file'}"); local $conf = &get_config(); $server = "127.0.0.1"; - $port = $config{'port'} || &find_value("port", $conf) || 389; + $port = $config{'port'} || &find_value("port", $conf); $user = $config{'user'} || &find_value("rootdn", $conf); $user || return $text{'connect_euser2'}; $pass = $config{'pass'} || &find_value("rootpw", $conf); @@ -67,26 +67,28 @@ $ssl = $config{'ssl'}; local @ssls = $ssl eq "" ? ( 1, 0 ) : ( $ssl ); local $ldap; foreach $ssl (@ssls) { - $ldap = Net::LDAP->new($server, port => $port); + my $sslport = $port ? $port : $ssl ? 636 : 389; + $ldap = Net::LDAP->new($server, port => $sslport, + scheme=>$ssl ? 'ldaps' : 'ldap'); if (!$ldap) { # Connection failed .. give up completely - return &text('connect_eldap', "$server", $port); + return &text('connect_eldap', "$server", $sslport); } if ($ssl) { - # Switch to TLS mode + # Switch to TLS mode. It is OK if this fails though local $mesg; eval { $mesg = $ldap->start_tls(); }; - if ($@ || !$mesg || $mesg->code) { - # Failed to switch to SSL mode. If also trying non-SSL, - # continue around the loop. Otherwise, give up - if (@ssls > 1) { - next; - } - else { - return &text('connect_essl', "$server", - $@ ? $@ : &ldap_error($mesg)); - } - } + #if ($@ || !$mesg || $mesg->code) { + # # Failed to switch to SSL mode. If also trying non-SSL, + # # continue around the loop. Otherwise, give up + # if (@ssls > 1) { + # next; + # } + # else { + # return &text('connect_essl', "$server", + # $@ ? $@ : &ldap_error($mesg)); + # } + # } } } $ldap || return "This can't happen!"; @@ -527,5 +529,89 @@ foreach my $b (@{$p->{'by'}}) { $a->{'values'} = \@v; } +# can_get_ldap_protocols() +# Returns 1 if we can get the protocols this LDAP server will serve. Depends +# on the OS, as this is often set in the init script. +sub can_get_ldap_protocols +{ +return $gconfig{'os_type'} eq 'redhat-linux' && + -r "/etc/sysconfig/ldap" || + $gconfig{'os_type'} eq 'debian-linux' && + -r "/etc/default/slapd" && + &get_ldap_protocols(); +} + +# get_ldap_protocols() +# Returns a hash from known LDAP protcols (like ldap, ldaps and ldapi) to +# flags indicating if they are enabled +sub get_ldap_protocols +{ +if ($gconfig{'os_type'} eq 'redhat-linux') { + # Stored in /etc/sysconfig/ldap file + local %ldap; + &read_env_file("/etc/init.d/ldap", \%ldap); + &read_env_file("/etc/sysconfig/ldap", \%ldap); + return { 'ldap' => $ldap{'SLAPD_LDAP'} eq 'yes' ? 1 : 0, + 'ldapi' => $ldap{'SLAPD_LDAPI'} eq 'yes' ? 1 : 0, + 'ldaps' => $ldap{'SLAPD_LDAPS'} eq 'yes' ? 1 : 0, + }; + } +elsif ($gconfig{'os_type'} eq 'debian-linux') { + # Stored in /etc/default/slapd, in SLAPD_SERVICES line + local %ldap; + &read_env_file("/etc/default/slapd", \%ldap); + if ($ldap{'SLAPD_SERVICES'}) { + local @servs = split(/\s+/, $ldap{'SLAPD_SERVICES'}); + local $rv = { 'ldap' => 0, 'ldaps' => 0, 'ldapi' => 0 }; + foreach my $w (@servs) { + if ($w =~ /^(ldap|ldaps|ldapi):\/\/\/$/) { + $rv->{$1} = 1; + } + else { + # Unknown protocol spec .. ignore + return undef; + } + } + return $rv; + } + else { + # Default is non-encrypted only + return { 'ldap' => 1, 'ldaps' => 0, 'ldapi' => 0 }; + } + } +} + +# save_ldap_protocols(&protos) +# Updates the OS-specific file containing enabled LDAP protocols. Also does +# locking on the file. +sub save_ldap_protocols +{ +local ($protos) = @_; +if ($gconfig{'os_type'} eq 'redhat-linux') { + # Stored in /etc/sysconfig/ldap file + local %ldap; + &lock_file("/etc/sysconfig/ldap"); + &read_env_file("/etc/sysconfig/ldap", \%ldap); + $ldap{'SLAPD_LDAP'} = $protos->{'ldap'} ? 'yes' : 'no' + if (defined($protos->{'ldap'})); + $ldap{'SLAPD_LDAPI'} = $protos->{'ldapi'} ? 'yes' : 'no' + if (defined($protos->{'ldapi'})); + $ldap{'SLAPD_LDAPS'} = $protos->{'ldaps'} ? 'yes' : 'no' + if (defined($protos->{'ldaps'})); + &write_env_file("/etc/sysconfig/ldap", \%ldap); + &unlock_file("/etc/sysconfig/ldap"); + } +elsif ($gconfig{'os_type'} eq 'debian-linux') { + # Update /etc/default/slapd SLAPD_SERVICES line + local %ldap; + &lock_file("/etc/default/slapd"); + &read_env_file("/etc/default/slapd", \%ldap); + $ldap{'SLAPD_SERVICES'} = + join(" ", map { $_.":///" } grep { $protos->{$_} } keys %$protos); + &write_env_file("/etc/default/slapd", \%ldap); + &unlock_file("/etc/default/slapd"); + } +} + 1; diff --git a/ldap-server/save_slapd.cgi b/ldap-server/save_slapd.cgi index 6dfb39f0a..e5e814394 100644 --- a/ldap-server/save_slapd.cgi +++ b/ldap-server/save_slapd.cgi @@ -65,6 +65,12 @@ else { &save_directive($conf, 'timelimit', $in{'timelimit'}); } +# LDAP protocols +if (&can_get_ldap_protocols()) { + @newprotos = split(/\0/, $in{'protos'}); + @newprotos || &error($text{'slapd_eprotos'}); + } + # SSL file options foreach $s ([ 'TLSCertificateFile', 'cert' ], [ 'TLSCertificateKeyFile', 'key' ], @@ -87,6 +93,16 @@ if ($save_config) { &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("");