]> git.proxmox.com Git - pve-access-control.git/blame - PVE/Auth/LDAP.pm
ldap auth: add sslversion option
[pve-access-control.git] / PVE / Auth / LDAP.pm
CommitLineData
5bb4e06a
DM
1package PVE::Auth::LDAP;
2
3use strict;
7c410d63
DM
4use warnings;
5
b5040b42 6use PVE::Tools;
5bb4e06a
DM
7use PVE::Auth::Plugin;
8use Net::LDAP;
8b600c4d 9use Net::IP;
5bb4e06a
DM
10use base qw(PVE::Auth::Plugin);
11
12sub type {
13 return 'ldap';
14}
15
16sub properties {
17 return {
18 base_dn => {
19 description => "LDAP base domain name",
20 type => 'string',
21 pattern => '\w+=[^,]+(,\s*\w+=[^,]+)*',
22 optional => 1,
23 maxLength => 256,
24 },
25 user_attr => {
26 description => "LDAP user attribute name",
27 type => 'string',
28 pattern => '\S{2,}',
29 optional => 1,
30 maxLength => 256,
31 },
b5040b42
WB
32 bind_dn => {
33 description => "LDAP bind domain name",
34 type => 'string',
35 pattern => '\w+=[^,]+(,\s*\w+=[^,]+)*',
36 optional => 1,
37 maxLength => 256,
38 },
e03c2aef
WB
39 verify => {
40 description => "Verify the server's SSL certificate",
41 type => 'boolean',
42 optional => 1,
43 default => 0,
44 },
45 capath => {
46 description => "Path to the CA certificate store",
47 type => 'string',
48 optional => 1,
49 default => '/etc/ssl/certs',
50 },
51 cert => {
52 description => "Path to the client certificate",
53 type => 'string',
54 optional => 1,
55 },
56 certkey => {
57 description => "Path to the client certificate key",
58 type => 'string',
59 optional => 1,
60 },
5bb4e06a
DM
61 };
62}
63
64sub options {
65 return {
66 server1 => {},
67 server2 => { optional => 1 },
68 base_dn => {},
b5040b42 69 bind_dn => { optional => 1 },
5bb4e06a
DM
70 user_attr => {},
71 port => { optional => 1 },
72 secure => { optional => 1 },
07dd90d7 73 sslversion => { optional => 1 },
5bb4e06a
DM
74 default => { optional => 1 },
75 comment => { optional => 1 },
96f8ebd6 76 tfa => { optional => 1 },
e03c2aef
WB
77 verify => { optional => 1 },
78 capath => { optional => 1 },
79 cert => { optional => 1 },
80 certkey => { optional => 1 },
5bb4e06a
DM
81 };
82}
83
84my $authenticate_user_ldap = sub {
b5040b42 85 my ($config, $server, $username, $password, $realm) = @_;
5bb4e06a
DM
86
87 my $default_port = $config->{secure} ? 636: 389;
88 my $port = $config->{port} ? $config->{port} : $default_port;
89 my $scheme = $config->{secure} ? 'ldaps' : 'ldap';
8b600c4d 90 $server = "[$server]" if Net::IP::ip_is_ipv6($server);
5bb4e06a
DM
91 my $conn_string = "$scheme://${server}:$port";
92
e03c2aef
WB
93 my %ldap_args;
94 if ($config->{verify}) {
95 $ldap_args{verify} = 'require';
96 if (defined(my $cert = $config->{cert})) {
97 $ldap_args{clientcert} = $cert;
98 }
99 if (defined(my $key = $config->{certkey})) {
100 $ldap_args{clientkey} = $key;
101 }
102 if (defined(my $capath = $config->{capath})) {
103 if (-d $capath) {
104 $ldap_args{capath} = $capath;
105 } else {
106 $ldap_args{cafile} = $capath;
107 }
108 }
109 } else {
110 $ldap_args{verify} = 'none';
111 }
112
07dd90d7
AD
113 if ($config->{secure}) {
114 $ldap_args{sslversion} = $config->{sslversion} ? $config->{sslversion} : 'tlsv1_2';
115 }
116
e03c2aef 117 my $ldap = Net::LDAP->new($conn_string, %ldap_args) || die "$@\n";
b5040b42
WB
118
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);
126 }
127
5bb4e06a
DM
128 my $search = $config->{user_attr} . "=" . $username;
129 my $result = $ldap->search( base => "$config->{base_dn}",
130 scope => "sub",
131 filter => "$search",
132 attrs => ['dn']
133 );
134 die "no entries returned\n" if !$result->entries;
135 my @entries = $result->entries;
136 my $res = $ldap->bind($entries[0]->dn, password => $password);
137
138 my $code = $res->code();
139 my $err = $res->error;
140
141 $ldap->unbind();
142
143 die "$err\n" if ($code);
144};
145
146sub authenticate_user {
147 my ($class, $config, $realm, $username, $password) = @_;
148
b5040b42 149 eval { &$authenticate_user_ldap($config, $config->{server1}, $username, $password, $realm); };
5bb4e06a
DM
150 my $err = $@;
151 return 1 if !$err;
152 die $err if !$config->{server2};
f4e7fc7b 153 &$authenticate_user_ldap($config, $config->{server2}, $username, $password, $realm);
5bb4e06a
DM
154}
155
1561;