source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ldap/objects.pm @ 1603

Last change on this file since 1603 was 1603, checked in by nanardon, 8 years ago

Upgrade entry user to sambaAccount to store NT encrypted password

Having password stored in NT windows forms will allow to use them for mschap(v2)
authentication

File size: 6.2 KB
Line 
1package LATMOS::Accounts::Bases::Ldap::objects;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use base qw(LATMOS::Accounts::Bases::Objects);
8use Net::LDAP;
9use Net::LDAP::Entry;
10use Net::LDAP::Control::Paged;
11use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED ); 
12use Net::LDAP::Util     qw( escape_filter_value );
13use LATMOS::Accounts::Log;
14
15our $VERSION = (q$Rev: 652 $ =~ /^Rev: (\d+) /)[0];
16
17=head1 NAME
18
19LATMOS::Ldap - Perl extension for blah blah blah
20
21=head1 SYNOPSIS
22
23  use LATMOS::Ldap;
24  blah blah blah
25
26=head1 DESCRIPTION
27
28Stub documentation for LATMOS::Ldap, created by h2xs. It looks like the
29author of the extension was negligent enough to leave the stub
30unedited.
31
32Blah blah blah.
33
34=head1 FUNCTIONS
35
36=cut
37
38sub _get_attr_schema {
39    my ($class, $base, $info) = @_;
40    $info ||= {};
41
42    foreach (qw(
43            createTimestamp
44            creatorsName
45            entryUUID
46            modifiersName
47            modifyTimestamp
48            entryCSN
49            )) {
50        $info->{$_} = { ro => 1 };
51    }
52
53    $info->{$class->_key_attribute($base)}{ro} = 1;
54    $info->{$class->_dn_attribute($base)}{ro} = 1;
55
56    return $info;
57}   
58
59sub _key_attribute {
60    my ($self, $base) = @_;
61    $base ||= $self->base;
62
63    $base->config($self->type . '_key_attribute') || $self->_key_attr || 'cn';
64}
65
66sub _dn_attribute {
67    my ($self, $base) = @_;
68    $base ||= $self->base;
69
70    $base->config($self->type . '_dn_attribute') || $self->_key_attr || 'cn';
71}
72
73sub list {
74    my ($class, $base) = @_;
75   
76    my @uids;
77    eval {
78    my $xx = $base->_unlimited_search(
79        attrs => [ $class->_key_attribute($base) ],
80        base => $base->object_base_dn($class->type),
81        filter => $class->_class_filter,
82        callback => sub {
83            my ($mesg, $entry) = @_;
84            #$mesg->code and die $mesg->error;
85            $entry or return;
86            ref $entry eq 'Net::LDAP::Entry' or return;
87            push(@uids, $entry->get_value( $class->_key_attribute($base) ));
88        },
89    );
90    };
91
92    return @uids;
93
94}
95
96sub new {
97    my ($class, $base, $uid) = @_;
98   
99    my $mesg = $base->ldap->search(
100        filter => sprintf(
101            '(&%s (%s=%s))',
102            $class->_class_filter,
103            $class->_key_attribute($base),
104            escape_filter_value($uid),
105        ),
106        base => $base->object_base_dn($class->type),
107        attrs => [ $class->_canonical_fields($base, 'r') ],
108    );
109
110    if ($mesg->code)  {
111        $base->log(LA_ERR, 'Cannot fetch %s/%s: %s', $class->type, $uid, $mesg->code);
112        return;
113    }
114
115    my ($entry, @others) = $mesg->entries;
116
117    if(@others) { # we cannot have multiple entries...
118        $base->la_log(LA_ERR, 'Multiple entry found forr %s/%s', $class->type, $uid);
119        return;
120    }
121    if (!$entry) {
122        $base->log(LA_DEBUG, 'Cannot fetch %s/%s: no entry returned', $class->type, $uid);
123        return;
124    }
125    bless({ entry => $entry, _base => $base, _id => $uid }, $class);
126}
127
128sub _delete {
129    my ($class, $base, $uid) = @_;
130    my $obj = $class->new($base, $uid) or return;
131
132    my $mesg = $base->ldap->delete($obj->{entry}->dn);
133
134    if ($mesg->code) {
135        $base->log(LA_ERR, "Cannot delete object %s: %s", $uid, $mesg->error);
136        return;
137    } else {
138        $base->log(LA_INFO, "Object (%s) %s delete", $class->type, $uid);
139        return 1
140    }
141}
142
143sub _rename {
144    my ($class, $base, $uid, $newuid) = @_;
145    my $obj = $class->new($base, $uid) or return;
146
147    my $mesg;
148    if ($class->_key_attribute($base) eq
149                $class->_dn_attribute($base)) {
150        $mesg = $base->ldap->moddn( $obj->{entry},
151            newrdn => $class->_dn_attribute($base) . '=' .  escape_filter_value($newuid),
152            deleteoldrdn => 1,)
153    } else {
154        $obj->{entry}->replace($class->_key_attribute($base), $newuid);
155        $mesg = $obj->{entry}->update($base->ldap);
156    }
157
158    if ($mesg->code) {
159        $base->log(LA_ERR, "Cannot rename object %s: %s", $uid, $mesg->error);
160        return;
161    } else {
162        return 1;
163    }
164}
165
166=head2 ldap
167
168A shortcut to return the L<Net::LDAP> object
169
170=cut
171
172sub ldap {
173    return $_[0]->base->{_ldap};
174}
175
176sub get_field {
177    my ($self, $field) = @_;
178
179    $field eq 'dn' and return $self->{entry}->dn;
180    my ($first, @others) = $self->{entry}->get_value($field);
181    return @others ? [ sort($first, @others) ] : $first;
182}
183
184sub _populate_entry {
185    my ($self, $entry, $field, $value, $base) = @_;
186    my $val = ref $self ? $self->get_field($field) : undef;
187    my $tr =  join(', ', map { $_ || '' } ($field, $val, $value));
188    if ($value) {
189        if ((!$val) || $val ne $value) {
190            $entry->replace($field, $value);
191        }
192    } elsif($val) {
193        $entry->delete($field);
194    }
195}
196
197sub set_fields {
198    my ($self, %fields) = @_;
199
200    {
201        my $oclass = join(',', sort $self->{entry}->get_value('objectClass'));
202        my $cclass = join(',', sort $self->_my_ldap_classes);
203        if ($oclass ne $cclass) {
204            $self->{entry}->replace(
205                'objectClass' => [ $self->_my_ldap_classes ]
206            );
207        }
208    }
209    foreach (keys %fields) {
210        my $attr = $self->attribute($_) or do {
211            $self->base->log(LA_ERR, "Unknow attribute %s (%s)",
212                $_, $self->type);
213            return;
214        };
215        $attr->ro and next;
216        $self->_populate_entry($self->{entry}, $_, $fields{$_});
217    }
218   
219    my $mesg = $self->{entry}->update($self->base->ldap);
220
221    if ($mesg->code && $mesg->code != 82) {
222        $self->base->log(LA_ERR, "Cannot set attributes: %s", $mesg->error);
223        return;
224    } else { return 1 }
225}
226
227sub _update_class {
228    my ($self, %attr) = @_;
229
230    $self->base->log(
231        LA_NOTICE,
232        "Updating ObjectClass for %s/%s: %s",
233        $self->type, $self->id, join(', ', $self->_my_ldap_classes)
234    );
235    $self->{entry}->replace(
236        'objectClass' => [ $self->_my_ldap_classes ],
237        %attr,
238    );
239}
240
2411;
242
243__END__
244
245=head1 SEE ALSO
246
247=head1 AUTHOR
248
249Olivier Thauvin, E<lt>olivier.thauvin@aerov.jussieu.frE<gt>
250
251=head1 COPYRIGHT AND LICENSE
252
253Copyright (C) 2008 CNRS SA/CETP/LATMOS
254
255This library is free software; you can redistribute it and/or modify
256it under the same terms as Perl itself, either Perl version 5.10.0 or,
257at your option, any later version of Perl 5 you may have available.
258
259
260=cut
Note: See TracBrowser for help on using the repository browser.