Better handling of uris in LDAP config
authorJamie Cameron <jcameron@webmin.com>
Thu, 7 Aug 2008 19:36:26 +0000 (19:36 +0000)
committerJamie Cameron <jcameron@webmin.com>
Thu, 7 Aug 2008 19:36:26 +0000 (19:36 +0000)
ldap-client/edit_server.cgi
ldap-client/lang/en
ldap-client/save_server.cgi
ldap-useradmin/lang/en
ldap-useradmin/ldap-useradmin-lib.pl

index 96db557..a9e30d9 100755 (executable)
@@ -18,7 +18,7 @@ if ($uri) {
        $i = 0;
        foreach $u (split(/\s+/, $uri), undef) {
                local ($proto, $host, $port);
-               if ($u =~ /^(ldap|ldaps):\/\/([a-z0-9\_\-\.]+)(:(\d+))?/) {
+               if ($u =~ /^(ldap|ldaps|ldapi):\/\/([a-z0-9\_\-\.]+)(:(\d+))?/) {
                        ($proto, $host, $port) = ($1, $2, $4);
                        }
                $utable .= &ui_columns_row([
@@ -26,7 +26,8 @@ if ($uri) {
                    &ui_opt_textbox("uport_$i", $port, 5, $text{'default'}),
                    &ui_select("uproto_$i", $proto,
                               [ [ 'ldap', $text{'server_ldap'} ],
-                                [ 'ldaps', $text{'server_ldaps'} ] ]),
+                                [ 'ldaps', $text{'server_ldaps'} ],
+                                [ 'ldapi', $text{'server_ldapi'} ] ]),
                    ]);
                $i++;
                }
index bce9411..0050b3c 100644 (file)
@@ -29,6 +29,7 @@ server_uport=Port number
 server_uproto=Protocol
 server_ldap=Standard
 server_ldaps=SSL
+server_ldapi=Unix socket
 server_err=Failed to save LDAP server configuration
 server_ehost='$1' is not a valid hostname
 server_ehosts=No LDAP servers entered
index f603f83..1b55af9 100755 (executable)
@@ -21,6 +21,7 @@ if ($uri) {
                    $port =~ /^\d+$/ && $port > 0 && $port < 65536 ||
                    &error(&text('server_euport', $host));
                $uri = $proto."://".$host.($port ? ":$port" : "");
+               $uri .= "/" if ($proto eq "ldap" || $proto eq "ldaps");
                push(@uris, $uri);
                }
        @uris || &error($text{'server_euri'});
index 079e180..594a663 100644 (file)
@@ -21,6 +21,7 @@ index_users=LDAP Users
 index_groups=LDAP Groups
 
 conn_econn=Failed to connect to LDAP server $1 port $2
+conn_essl=Failed to start SSL for LDAP server $1 port $2 : $3
 conn_elogin=Failed to bind to LDAP server $1 as $2 : $3
 imap_econn=Failed to connect to IMAP server $1
 imap_elogin=Failed to login to IMAP server $1 as $2 : $3
index 1588209..069068c 100644 (file)
@@ -68,38 +68,72 @@ return \%nss_config_cache;
 sub ldap_connect
 {
 local $conf = &get_nss_config();
+
+# Work out LDAP hostnames, ports and SSL
 local (@hosts, $port);
 if ($conf) {
-       @hosts = split(/[ ,]+/, $conf->{'host'});
-       $port = $conf->{'port'};
+       # From ldap.conf file, using host and uri lines
+       my @hostnames = split(/[ ,]+/, $conf->{'host'});
+       my $port = $conf->{'port'};
+       my @uris = split(/[ ,]+/, $conf->{'uri'});
+       my $ssl = $conf->{'start_tls'};
+       foreach my $hname (@hostnames) {
+               push(@hosts, [ $hname, $port, $ssl eq 'start_tls' ]);
+               }
+       foreach my $u (@uris) {
+               if ($u =~ /^(ldap|ldaps|ldapi):\/\/([a-z0-9\_\-\.]+)(:(\d+))?/){
+                       my ($proto, $host, $port) = ($1, $2, $4);
+                       if (!$port && $proto eq "ldap") {
+                               $port = 389;
+                               }
+                       elsif (!$port && $proto eq "ldaps") {
+                               $port = 636;
+                               }
+                       push(@hosts, [ $host, $port, $proto eq 'ldaps' ]);
+                       }
+               }
        }
 else {
-       @hosts = split(/[ ,]+/, $config{'ldap_host'});
-       $port = $config{'ldap_port'};
+       # From config
+       foreach my $hname (split(/[ ,]+/, $config{'ldap_host'})) {
+               push(@hosts, [ $hname, $config{'ldap_port'},
+                              $config{'ldap_tls'} ]);
+               }
        }
-@hosts = ( "localhost" ) if (!@hosts);
-$port ||= 389;
+if (!@hosts) {
+       # Last-ditch fallback
+       push(@hosts, [ "localhost", 389, 0 ]);
+       }
+
+# Try each host in turn
 local ($ldap, $err);
-foreach $host (@hosts) {
-       $ldap = Net::LDAP->new($host, port => $port);
+foreach my $host (@hosts) {
+       $ldap = Net::LDAP->new($host->[0], port => $host->[1]);
        if (!$ldap) {
                $err = &text('conn_econn',
-                                  "<tt>$host</tt>","<tt>$port</tt>");
+                            "<tt>$host->[0]</tt>","<tt>$host->[1]</tt>");
+               next;
                }
-       else {
-               last;
+       # Connected .. but try SSL if needed
+       if ($host->[2]) {
+               my $mesg;
+               eval { $mesg = $ldap->start_tls(); };
+               if ($@ || !$mesg || $mesg->code) {
+                       # SSL failed
+                       $err = &text('conn_essl',
+                            "<tt>$host->[0]</tt>", "<tt>$host->[1]</tt>", $@);
+                       next;
+                       }
                }
+       # If we got here, it all worked!
+       $err = undef;
+       last;
        }
 if ($err) {
        if ($_[0]) { return $err; }
        else { &error($err); }
        }
 
-# Start TLS if configured
-if ($config{'ldap_tls'}) {
-       $ldap->start_tls;
-       }
-
 local ($dn, $password);
 if ($config{'login'}) {
        # Use the configured login