1 package FS::part_export::ldap;
4 use FS::Record qw( dbh );
7 @ISA = qw(FS::part_export);
12 my($self, $svc_acct) = (shift, shift);
14 #false laziness w/shellcommands.pm
17 ${$_} = $svc_acct->getfield($_) foreach $svc_acct->fields;
18 ${$_} = $svc_acct->$_() foreach qw( domain );
19 my $cust_pkg = $svc_acct->cust_svc->cust_pkg;
21 my $cust_main = $cust_pkg->cust_main;
22 ${$_} = $cust_main->getfield($_) foreach qw(first last);
25 $crypt_password = ''; #surpress "used only once" warnings
26 $crypt_password = crypt( $svc_acct->_password,
27 $saltset[int(rand(64))].$saltset[int(rand(64))] );
30 my %attrib = map { /^\s*(\w+)\s+(.*\S)\s*$/; ( $1 => eval(qq("$2")) ); }
31 grep { /^\s*(\w+)\s+(.*\S)\s*$/ }
32 split("\n", $self->option('attributes'));
34 if ( $self->option('radius') ) {
35 foreach my $table (qw(reply check)) {
36 my $method = "radius_$table";
37 my %radius = $svc_acct->$method();
38 foreach my $radius ( keys %radius ) {
39 ( my $ldap = $radius ) =~ s/\-//g;
40 $attrib{$ldap} = $radius{$radius};
45 my $err_or_queue = $self->ldap_queue( $svc_acct->svcnum, 'insert',
48 return $err_or_queue unless ref($err_or_queue);
51 #my @groups = $svc_acct->radius_groups;
53 # my $err_or_queue = $self->ldap_queue(
54 # $svc_acct->svcnum, 'usergroup_insert',
55 # $svc_acct->username, @groups );
56 # return $err_or_queue unless ref($err_or_queue);
63 my( $self, $new, $old ) = (shift, shift, shift);
65 local $SIG{HUP} = 'IGNORE';
66 local $SIG{INT} = 'IGNORE';
67 local $SIG{QUIT} = 'IGNORE';
68 local $SIG{TERM} = 'IGNORE';
69 local $SIG{TSTP} = 'IGNORE';
70 local $SIG{PIPE} = 'IGNORE';
72 return "can't (yet?) change username with ldap"
73 if $old->username ne $new->username;
75 return "ldap replace unimplemented";
77 my $oldAutoCommit = $FS::UID::AutoCommit;
78 local $FS::UID::AutoCommit = 0;
82 #if ( $old->username ne $new->username ) {
83 # my $err_or_queue = $self->ldap_queue( $new->svcnum, 'rename',
84 # $new->username, $old->username );
85 # unless ( ref($err_or_queue) ) {
86 # $dbh->rollback if $oldAutoCommit;
87 # return $err_or_queue;
89 # $jobnum = $err_or_queue->jobnum;
92 foreach my $table (qw(reply check)) {
93 my $method = "radius_$table";
94 my %new = $new->$method();
95 my %old = $old->$method();
96 if ( grep { !exists $old{$_} #new attributes
97 || $new{$_} ne $old{$_} #changed
100 my $err_or_queue = $self->ldap_queue( $new->svcnum, 'insert',
101 $table, $new->username, %new );
102 unless ( ref($err_or_queue) ) {
103 $dbh->rollback if $oldAutoCommit;
104 return $err_or_queue;
107 my $error = $err_or_queue->depend_insert( $jobnum );
109 $dbh->rollback if $oldAutoCommit;
115 my @del = grep { !exists $new{$_} } keys %old;
117 my $err_or_queue = $self->ldap_queue( $new->svcnum, 'attrib_delete',
118 $table, $new->username, @del );
119 unless ( ref($err_or_queue) ) {
120 $dbh->rollback if $oldAutoCommit;
121 return $err_or_queue;
124 my $error = $err_or_queue->depend_insert( $jobnum );
126 $dbh->rollback if $oldAutoCommit;
133 # (sorta) false laziness with FS::svc_acct::replace
134 my @oldgroups = @{$old->usergroup}; #uuuh
135 my @newgroups = $new->radius_groups;
137 foreach my $oldgroup ( @oldgroups ) {
138 if ( grep { $oldgroup eq $_ } @newgroups ) {
139 @newgroups = grep { $oldgroup ne $_ } @newgroups;
142 push @delgroups, $oldgroup;
146 my $err_or_queue = $self->ldap_queue( $new->svcnum, 'usergroup_delete',
147 $new->username, @delgroups );
148 unless ( ref($err_or_queue) ) {
149 $dbh->rollback if $oldAutoCommit;
150 return $err_or_queue;
153 my $error = $err_or_queue->depend_insert( $jobnum );
155 $dbh->rollback if $oldAutoCommit;
162 my $err_or_queue = $self->ldap_queue( $new->svcnum, 'usergroup_insert',
163 $new->username, @newgroups );
164 unless ( ref($err_or_queue) ) {
165 $dbh->rollback if $oldAutoCommit;
166 return $err_or_queue;
169 my $error = $err_or_queue->depend_insert( $jobnum );
171 $dbh->rollback if $oldAutoCommit;
177 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
183 my( $self, $svc_acct ) = (shift, shift);
184 return "ldap delete unimplemented";
185 my $err_or_queue = $self->ldap_queue( $svc_acct->svcnum, 'delete',
186 $svc_acct->username );
187 ref($err_or_queue) ? '' : $err_or_queue;
191 my( $self, $svcnum, $method ) = (shift, shift, shift);
192 my $queue = new FS::queue {
194 'job' => "FS::part_export::ldap::ldap_$method",
199 $self->option('password'),
204 sub ldap_insert { #subroutine, not method
205 my $dn = ldap_connect(shift, shift, shift);
208 my $status = $ldap->add( $dn, attrs => [ %attrib ] );
209 die $status->error if $status->is_error;
214 #sub ldap_delete { #subroutine, not method
215 # my $dbh = ldap_connect(shift, shift, shift);
216 # my $username = shift;
218 # foreach my $table (qw( radcheck radreply usergroup )) {
219 # my $sth = $dbh->prepare( "DELETE FROM $table WHERE UserName = ?" );
220 # $sth->execute($username)
221 # or die "can't delete from $table table: ". $sth->errstr;
227 my( $machine, $dn, $password ) = @_;
229 $bind_options{password} = $password if length($password);
231 eval "use Net::LDAP";
234 my $ldap = Net::LDAP->new($machine) or die $@;
235 my $status = $ldap->bind( $dn, %bind_options );
236 die $status->error if $status->is_error;