1 package PVE
::Auth
::LDAP
;
10 use base
qw(PVE::Auth::Plugin);
19 description
=> "LDAP base domain name",
21 pattern
=> '\w+=[^,]+(,\s*\w+=[^,]+)*',
26 description
=> "LDAP user attribute name",
33 description
=> "LDAP bind domain name",
35 pattern
=> '\w+=[^,]+(,\s*\w+=[^,]+)*',
40 description
=> "Verify the server's SSL certificate",
46 description
=> "Path to the CA certificate store",
49 default => '/etc/ssl/certs',
52 description
=> "Path to the client certificate",
57 description
=> "Path to the client certificate key",
67 server2
=> { optional
=> 1 },
69 bind_dn
=> { optional
=> 1 },
71 port
=> { optional
=> 1 },
72 secure
=> { optional
=> 1 },
73 sslversion
=> { optional
=> 1 },
74 default => { optional
=> 1 },
75 comment
=> { optional
=> 1 },
76 tfa
=> { optional
=> 1 },
77 verify
=> { optional
=> 1 },
78 capath
=> { optional
=> 1 },
79 cert
=> { optional
=> 1 },
80 certkey
=> { optional
=> 1 },
84 my $authenticate_user_ldap = sub {
85 my ($config, $server, $username, $password, $realm) = @_;
87 my $default_port = $config->{secure
} ?
636: 389;
88 my $port = $config->{port
} ?
$config->{port
} : $default_port;
89 my $scheme = $config->{secure
} ?
'ldaps' : 'ldap';
90 $server = "[$server]" if Net
::IP
::ip_is_ipv6
($server);
91 my $conn_string = "$scheme://${server}:$port";
94 if ($config->{verify
}) {
95 $ldap_args{verify
} = 'require';
96 if (defined(my $cert = $config->{cert
})) {
97 $ldap_args{clientcert
} = $cert;
99 if (defined(my $key = $config->{certkey
})) {
100 $ldap_args{clientkey
} = $key;
102 if (defined(my $capath = $config->{capath
})) {
104 $ldap_args{capath
} = $capath;
106 $ldap_args{cafile
} = $capath;
110 $ldap_args{verify
} = 'none';
113 if ($config->{secure
}) {
114 $ldap_args{sslversion
} = $config->{sslversion
} ?
$config->{sslversion
} : 'tlsv1_2';
117 my $ldap = Net
::LDAP-
>new($conn_string, %ldap_args) || die "$@\n";
119 if (my $bind_dn = $config->{bind_dn
}) {
120 my $bind_pass = PVE
::Tools
::file_read_firstline
("/etc/pve/priv/ldap/${realm}.pw");
121 die "missing password for realm $realm\n" if !defined($bind_pass);
122 my $res = $ldap->bind($bind_dn, password
=> $bind_pass);
123 my $code = $res->code();
124 my $err = $res->error;
125 die "failed to authenticate to ldap service: $err\n" if ($code);
128 my $search = $config->{user_attr
} . "=" . $username;
129 my $result = $ldap->search( base
=> "$config->{base_dn}",
134 die "no entries returned\n" if !$result->entries;
135 my @entries = $result->entries;
136 my $res = $ldap->bind($entries[0]->dn, password
=> $password);
138 my $code = $res->code();
139 my $err = $res->error;
143 die "$err\n" if ($code);
146 sub authenticate_user
{
147 my ($class, $config, $realm, $username, $password) = @_;
149 eval { &$authenticate_user_ldap($config, $config->{server1
}, $username, $password, $realm); };
152 die $err if !$config->{server2
};
153 &$authenticate_user_ldap($config, $config->{server2
}, $username, $password, $realm);