]>
Commit | Line | Data |
---|---|---|
c712d3a2 DM |
1 | package PMG::RuleDB::LDAPUser; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use DBI; | |
6 | use Digest::SHA; | |
ff1a61ff | 7 | use Encode qw(encode); |
c712d3a2 | 8 | |
aba41750 DM |
9 | use PVE::INotify; |
10 | ||
c712d3a2 DM |
11 | use PMG::Utils; |
12 | use PMG::RuleDB::Object; | |
13 | use PMG::LDAPCache; | |
aba41750 | 14 | use PMG::LDAPConfig; |
c712d3a2 DM |
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 | ||
c712d3a2 DM |
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"; | |
ff1a61ff DC |
50 | |
51 | my $decoded = PMG::Utils::try_decode_utf8($value); | |
52 | ||
c712d3a2 | 53 | my $obj; |
ff1a61ff | 54 | if ($decoded =~ m/^([^:]*):(.*)$/) { |
c712d3a2 | 55 | $obj = $class->new($2, $1, $ogroup); |
ff1a61ff | 56 | $obj->{digest} = Digest::SHA::sha1_hex($id, encode('UTF-8', $2), encode('UTF-8', $1), $ogroup); |
c712d3a2 | 57 | } else { |
ff1a61ff | 58 | $obj = $class->new($decoded, '', $ogroup); |
c712d3a2 DM |
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 | ||
ff1a61ff | 77 | my $confdata = encode('UTF-8', "$profile:$user"); |
c712d3a2 DM |
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 | ||
736b986f DC |
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 | ||
c712d3a2 DM |
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 | ||
d4d73d95 DM |
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) { | |
f76f331a | 134 | $desc = "LDAP user '$user', profile '$profile'"; |
d4d73d95 DM |
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 | ||
c712d3a2 DM |
187 | 1; |
188 | ||
189 | __END__ | |
190 | ||
191 | =head1 PMG::RuleDB::LDAPUser | |
192 | ||
193 | A WHO object to check LDAP users | |
194 | ||
1359baef | 195 | =head2 Attributes |
c712d3a2 DM |
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 |