]> git.proxmox.com Git - pmg-api.git/blob - src/PMG/RuleDB/LDAPUser.pm
ldap: improve unicode support
[pmg-api.git] / src / PMG / RuleDB / LDAPUser.pm
1 package PMG::RuleDB::LDAPUser;
2
3 use strict;
4 use warnings;
5 use DBI;
6 use Digest::SHA;
7 use Encode qw(encode);
8
9 use PVE::INotify;
10
11 use PMG::Utils;
12 use PMG::RuleDB::Object;
13 use PMG::LDAPCache;
14 use PMG::LDAPConfig;
15 use PMG::LDAPSet;
16
17 use base qw(PMG::RuleDB::Object);
18
19 sub otype {
20 return 1006;
21 }
22
23 sub oclass {
24 return 'who';
25 }
26
27 sub otype_text {
28 return 'LDAP User';
29 }
30
31 sub new {
32 my ($type, $ldapuser, $profile, $ogroup) = @_;
33
34 my $class = ref($type) || $type;
35
36 my $self = $class->SUPER::new($class->otype(), $ogroup);
37
38 $self->{ldapuser} = $ldapuser // '';
39 $self->{profile} = $profile // '';
40
41 return $self;
42 }
43
44 sub load_attr {
45 my ($type, $ruledb, $id, $ogroup, $value) = @_;
46
47 my $class = ref($type) || $type;
48
49 defined($value) || die "undefined value: ERROR";
50
51 my $decoded = PMG::Utils::try_decode_utf8($value);
52
53 my $obj;
54 if ($decoded =~ m/^([^:]*):(.*)$/) {
55 $obj = $class->new($2, $1, $ogroup);
56 $obj->{digest} = Digest::SHA::sha1_hex($id, encode('UTF-8', $2), encode('UTF-8', $1), $ogroup);
57 } else {
58 $obj = $class->new($decoded, '', $ogroup);
59 $obj->{digest} = Digest::SHA::sha1_hex ($id, $value, '#', $ogroup);
60 }
61
62 $obj->{id} = $id;
63
64 return $obj;
65 }
66
67 sub save {
68 my ($self, $ruledb) = @_;
69
70 defined($self->{ogroup}) || die "undefined ogroup: ERROR";
71 defined($self->{ldapuser}) || die "undefined ldap user: ERROR";
72 defined($self->{profile}) || die "undefined ldap profile: ERROR";
73
74 my $user = $self->{ldapuser};
75 my $profile = $self->{profile};
76
77 my $confdata = encode('UTF-8', "$profile:$user");
78
79 if (defined($self->{id})) {
80 # update
81
82 $ruledb->{dbh}->do(
83 "UPDATE Object SET Value = ? WHERE ID = ?",
84 undef, $confdata, $self->{id});
85
86 } else {
87 # insert
88
89 # check if it exists first
90 if (my $id = PMG::Utils::get_existing_object_id(
91 $ruledb->{dbh},
92 $self->{ogroup},
93 $self->otype(),
94 $confdata
95 )) {
96 return $id;
97 }
98
99 my $sth = $ruledb->{dbh}->prepare(
100 "INSERT INTO Object (Objectgroup_ID, ObjectType, Value) " .
101 "VALUES (?, ?, ?);");
102
103 $sth->execute($self->{ogroup}, $self->otype, $confdata);
104
105 $self->{id} = PMG::Utils::lastid($ruledb->{dbh}, 'object_id_seq');
106 }
107
108 return $self->{id};
109 }
110
111 sub test_ldap {
112 my ($ldap, $addr, $user, $profile) = @_;
113
114 return $ldap->account_has_address($user, $addr, $profile);
115 }
116
117 sub who_match {
118 my ($self, $addr, $ip, $ldap) = @_;
119
120 return 0 if !$ldap;
121
122 return test_ldap($ldap, $addr, $self->{ldapuser}, $self->{profile});
123 }
124
125 sub short_desc {
126 my ($self) = @_;
127
128 my $user = $self->{ldapuser};
129 my $profile = $self->{profile};
130
131 my $desc;
132
133 if ($profile) {
134 $desc = "LDAP user '$user', profile '$profile'";
135 } else {
136 $desc = "LDAP user without profile - fail always";
137 }
138
139 return $desc;
140 }
141
142 sub properties {
143 my ($class) = @_;
144
145 return {
146 profile => {
147 description => "Profile ID.",
148 type => 'string', format => 'pve-configid',
149 },
150 account => {
151 description => "LDAP user account name.",
152 type => 'string',
153 maxLength => 1024,
154 minLength => 1,
155 },
156 };
157 }
158
159 sub get {
160 my ($self) = @_;
161
162 return {
163 account => $self->{ldapuser},
164 profile => $self->{profile},
165 };
166 }
167
168 sub update {
169 my ($self, $param) = @_;
170
171 my $profile = $param->{profile};
172 my $cfg = PVE::INotify::read_file("pmg-ldap.conf");
173 my $config = $cfg->{ids}->{$profile};
174 die "LDAP profile '$profile' does not exist\n" if !$config;
175
176 my $account = $param->{account};
177 my $ldapcache = PMG::LDAPCache->new(
178 id => $profile, syncmode => 1, %$config);
179
180 die "LDAP acoount '$account' does not exist\n"
181 if !$ldapcache->account_exists($account);
182
183 $self->{ldapuser} = $account;
184 $self->{profile} = $profile;
185 }
186
187 1;
188
189 __END__
190
191 =head1 PMG::RuleDB::LDAPUser
192
193 A WHO object to check LDAP users
194
195 =head2 Attributes
196
197 =head3 ldapuser
198
199 An LDAP user account (ignore case).
200
201 =head3 profile
202
203 The LDAP profile name
204
205 =head2 Examples
206
207 $obj = PMG::RuleDB::LDAPUser>new('username', 'profile_name');
208