source: LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ad/User.pm @ 189

Last change on this file since 189 was 189, checked in by nanardon, 15 years ago
  • add set_password() to AD
  • Property svn:keywords set to Id Rev
File size: 5.7 KB
Line 
1package LATMOS::Accounts::Bases::Ad::User;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use base qw(LATMOS::Accounts::Bases::Ad::objects);
8use Net::LDAP;
9use Net::LDAPS;
10use Net::LDAP::Entry;
11use Net::LDAP::Control::Paged;
12use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED ); 
13use Net::LDAP::Util     qw( escape_filter_value );
14
15our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0];
16
17=head1 NAME
18
19LATMOS::Ad - Perl extension for blah blah blah
20
21=head1 SYNOPSIS
22
23  use LATMOS::Ad;
24  blah blah blah
25
26=head1 DESCRIPTION
27
28Stub documentation for LATMOS::Ad, 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 _class_filter { '(&(ObjectClass=user) (!(ObjectClass=computer)))' }
39
40sub _key_attr { 'cn' } 
41
42sub _delayed_fields {
43    my ($self)= @_;
44    return qw(memberOf);
45}
46
47sub _canonical_fields {
48    my ($self, $base, $mode) = @_;
49    (
50        qw(
51        sn name givenName
52        sAMAccountName uid gecos
53        homeDirectory loginShell
54        uidNumber gidNumber gecos
55        userPassword
56        shadowLastChange shadowMin shadowMax
57        shadowWarning shadowInactive shadowExpire
58        shadowFlag
59        description
60        mail
61        ipPhone otherTelephone department
62        title modbile homePhone
63        memberOf
64        accountExpires
65        streetAddress postalCode postOfficeBox l
66        physicalDeliveryOfficeName
67        company st
68        displayName
69        initials
70        manager
71        userAccountControl
72        locked
73        dSHeuristics
74        ),
75        ($mode !~ /w/
76            ? qw(cn dn uSNCreated uSNChanged directReports)
77            : ()
78        )
79    )
80}
81
82sub _create {
83    my ($class, $base, $id, %data) = @_;
84
85    my $entry = Net::LDAP::Entry->new();
86
87    $entry->dn(join(',',
88        sprintf('cn=%s', escape_filter_value($id)),
89        $base->object_base_dn($class->type),
90    ));
91    $entry->replace('sAMAccountName', $id);
92    $entry->replace(objectClass => [ qw(top person organizationalPerson user)],);
93    $entry->replace(userAccountControl => 66112);
94    $entry->replace(sAMAccountType => 0x30000000);
95    $entry->replace(accountExpires => '9223372036854775807'); # TODO hardcoded, burk
96    $entry->replace(userPrincipalName => "$id\@" . $base->ad_domain);
97    foreach (keys %data) {
98        $class->_populate_entry($entry, $_, $data{$_});
99    }
100    my $msg = $base->ldap->add($entry);
101    return $msg->code ? 0 : 1;
102}
103
104sub get_field {
105    my ($self, $field) = @_;
106
107    $field eq 'memberOf' and do {
108        my @res;
109        $self->base->_unlimited_search(
110            base => $self->base->object_base_dn('group'),
111            filter => sprintf(
112                '(&(objectClass=group)(member=%s))',
113                escape_filter_value($self->{entry}->dn),
114            ),
115            callback => sub {
116                my ($mesg, $entry) = @_;
117                ref $entry eq 'Net::LDAP::Entry' or return;
118                push(@res, $entry->get_value('cn'));
119            },
120        );
121        return [ sort(@res) ];
122    };
123    $field eq 'directReports' and do {
124        my $res = $self->SUPER::get_field($field);
125        return;
126        #return [ map { $self->base->get_value('cn') } @{ ref $res ? $res : [ $res ] } ];
127    };
128    $field eq 'manager' and do {
129        #my $entry = $self->SUPER::get_field($field) or return;
130        #return $entry->get_value('cn');
131    };
132    $self->SUPER::get_field($field);
133}
134
135sub set_fields {
136    my ($self, %data) = @_;
137    my %ndata;
138    while (my ($f, $val) = each(%data)) {
139        $f eq 'memberOf' and do {
140            my %users;
141            $users{$_}{e} = 1 foreach (@{ $self->get_field('memberOf') || []});
142            $users{$_}{n} = 1 foreach (@{ $val || []});
143            foreach (keys %users) {
144                $users{$_}{e} && $users{$_}{n} and next;
145                my $user = $self->base->get_object('group', $_) or next;
146                if ($users{$_}{e}) {
147                    $self->{entry}->del(memberOf => $user->get_field('dn'));
148                } elsif ($users{$_}{n}) {
149                    $self->{entry}->add(memberOf => $user->get_field('dn'));
150                } # else {} # can't happen
151                my $mesg = $self->{entry}->update($self->base->ldap);
152            }
153            next;
154        };
155        $f eq 'manager' && $val and do {
156            my $user = $self->base->get_object('user', $val) or next;
157            $ndata{$f} = $user->get_field('dn');
158            next;
159        };
160        $f eq 'locked' and do {
161            my $uac = $self->get_field('userAccountControl');
162            if ($val) {
163                $uac |= 0x00000002;
164            } else {
165                $uac &= (0xFFFFFFFF ^ 0x00000002);
166            }
167            $ndata{userAccountControl} = "$uac";
168            next;
169        };
170        $ndata{$f} = $val;
171    }
172    $self->SUPER::set_fields(%ndata);
173}
174
175sub set_password {
176    my ($self, $clear_pass) = @_;
177    my $charmap = Unicode::Map8->new('latin1')  or  die;
178    my $newUniPW = $charmap->tou('"'.$clear_pass.'"')->byteswap()->utf16();
179    my $mesg = $self->base->ldap->modify(
180        $self->get_c_field('dn'),
181        changes => [
182        #replace => [ userPassword => $clear_pass ],
183        replace => [ unicodePwd => $newUniPW ],
184
185        ]
186    );
187    if ($mesg->code && $mesg->code != 82) {
188        warn $mesg->error;
189        return;
190    } else { return 1 }
191}
192
1931;
194
195__END__
196
197=head1 SEE ALSO
198
199=head1 AUTHOR
200
201Olivier Thauvin, E<lt>olivier.thauvin@aerov.jussieu.frE<gt>
202
203=head1 COPYRIGHT AND LICENSE
204
205Copyright (C) 2008 CNRS SA/CETP/LATMOS
206
207This library is free software; you can redistribute it and/or modify
208it under the same terms as Perl itself, either Perl version 5.10.0 or,
209at your option, any later version of Perl 5 you may have available.
210
211
212=cut
Note: See TracBrowser for help on using the repository browser.