account.pm
branchfoerste
changeset 41 a0ed03bc2e1d
parent 23 72ba031fec20
child 42 b90dc89e8c66
equal deleted inserted replaced
40:cc9a80eb647c 41:a0ed03bc2e1d
     6 use strict;
     6 use strict;
     7 use warnings;
     7 use warnings;
     8 use Net::LDAP;
     8 use Net::LDAP;
     9 use Net::LDAP::Constant qw(LDAP_ALREADY_EXISTS LDAP_NO_SUCH_OBJECT LDAP_TYPE_OR_VALUE_EXISTS);
     9 use Net::LDAP::Constant qw(LDAP_ALREADY_EXISTS LDAP_NO_SUCH_OBJECT LDAP_TYPE_OR_VALUE_EXISTS);
    10 use Net::LDAP::Entry;
    10 use Net::LDAP::Entry;
    11 use Cyrus::IMAP::Admin;
    11 use Mail::IMAPTalk;
    12 use Text::Wrap;
    12 use Text::Wrap;
    13 use password;
    13 use password;
    14 
    14 
    15 
    15 
    16 my $Cf;
    16 my $Cf;
    17 my ($ldap, $ubase, $abase);
    17 my ($ldap, $ubase, $abase);
    18 my ($imap);
    18 my ($imap, $imap_password);
    19 END { $imap and $imap = undef; };
    19 END { $imap and $imap = undef; };
    20 
    20 
    21 
    21 
    22 sub _add();
    22 sub _add();
    23 sub _list();
    23 sub _list();
    31 sub AT_PRIMARYADDRESS();
    31 sub AT_PRIMARYADDRESS();
    32 sub OC_RECIPIENT();
    32 sub OC_RECIPIENT();
    33 sub AT_ADDRESS();
    33 sub AT_ADDRESS();
    34 sub AT_GROUP();
    34 sub AT_GROUP();
    35 sub AT_FORWARDINGADDRESS();
    35 sub AT_FORWARDINGADDRESS();
       
    36 sub AT_QUOTA();
    36 
    37 
    37 sub import(@) {
    38 sub import(@) {
    38     $Cf = shift;
    39     $Cf = shift;
    39 
    40 
    40     require constant;
    41     require constant;
    43     import constant OC_RECIPIENT => $Cf->ldap_oc_recipient;
    44     import constant OC_RECIPIENT => $Cf->ldap_oc_recipient;
    44     import constant AT_PRIMARYADDRESS => $Cf->ldap_at_primaryaddress;
    45     import constant AT_PRIMARYADDRESS => $Cf->ldap_at_primaryaddress;
    45     import constant AT_ADDRESS => $Cf->ldap_at_address;
    46     import constant AT_ADDRESS => $Cf->ldap_at_address;
    46     import constant AT_GROUP => $Cf->ldap_at_group;
    47     import constant AT_GROUP => $Cf->ldap_at_group;
    47     import constant AT_FORWARDINGADDRESS => $Cf->ldap_at_forwardingaddress;
    48     import constant AT_FORWARDINGADDRESS => $Cf->ldap_at_forwardingaddress;
       
    49     import constant AT_QUOTA => $Cf->ldap_at_quota;
    48 
    50 
    49     $ubase = OU_ACCOUNTS . "," . $Cf->ldap_base;
    51     $ubase = OU_ACCOUNTS . "," . $Cf->ldap_base;
    50     $abase = OU_ALIASES . "," . $Cf->ldap_base;
    52     $abase = OU_ALIASES . "," . $Cf->ldap_base;
    51 }
    53 }
    52 
    54 
    55     $ldap = new Net::LDAP $Cf->ldap_server or die;
    57     $ldap = new Net::LDAP $Cf->ldap_server or die;
    56     my $r = $ldap->bind($Cf->ldap_bind_dn,
    58     my $r = $ldap->bind($Cf->ldap_bind_dn,
    57 	password => $Cf->ldap_password || $ENV{LDAP_PASS} || password::ask("LDAP (". $Cf->ldap_bind_dn .") password: "));
    59 	password => $Cf->ldap_password || $ENV{LDAP_PASS} || password::ask("LDAP (". $Cf->ldap_bind_dn .") password: "));
    58     die $r->error, "\n" if $r->code;
    60     die $r->error, "\n" if $r->code;
    59 
    61 
    60     $imap = new Cyrus::IMAP::Admin or die $@;
    62     $imap = Mail::IMAPTalk->new(Server => $Cf->imap_server, Port => $Cf->imap_port)
    61     $imap->authenticate(-server => $Cf->imap_server, -user => $Cf->imap_admin, 
    63         or die "Can't connect to IMAP Server '", $Cf->imap_server, "', Port '", $Cf->imap_port, "': ", $@;
    62 	-password => $Cf->imap_password || $ENV{IMAP_PASS} || password::ask("IMAP (". $Cf->imap_admin .") password: "))
    64     $imap_password = $Cf->imap_password || $ENV{IMAP_PASS} || password::ask("IMAP (". $Cf->imap_admin .") password: ");
    63     or die $@;
       
    64 
       
    65 
    65 
    66     if ($Cf->list) { _list() }
    66     if ($Cf->list) { _list() }
    67     elsif ($Cf->add) { _add() }
    67     elsif ($Cf->add) { _add() }
    68     elsif ($Cf->delete) { _delete() }
    68     elsif ($Cf->delete) { _delete() }
    69     elsif ($Cf->modify) { _modify() }
    69     elsif ($Cf->modify) { _modify() }
    86     my $user = shift @ARGV;
    86     my $user = shift @ARGV;
    87     my $mailPrimaryAddress = $Cf->primary || $user;	    # evtl. mit !
    87     my $mailPrimaryAddress = $Cf->primary || $user;	    # evtl. mit !
    88     my $mailAddress = [$user, split /,/, $Cf->other || ""]; # ditto
    88     my $mailAddress = [$user, split /,/, $Cf->other || ""]; # ditto
    89 
    89 
    90     $user =~ s/!$//;					    # jetzt können wir ! nicht mehr brauchn
    90     $user =~ s/!$//;					    # jetzt können wir ! nicht mehr brauchn
    91     my $mbox = "user/$user";
       
    92     my $cn = $Cf->fullname || $user;
    91     my $cn = $Cf->fullname || $user;
    93     my $sn = (reverse split " ", $cn)[0];
    92     my $sn = (reverse split " ", $cn)[0];
    94     my $mailGroup = [split /,/, $Cf->group || ""];
    93     my $mailGroup = [split /,/, $Cf->group || ""];
    95     my $mailForwardingAddress = [split /,/, $Cf->forward || ""];
    94     my $mailForwardingAddress = [split /,/, $Cf->forward || ""];
    96     my $pw = _mkpw($Cf->password || "{pwgen}");
    95     my $pw = _mkpw($Cf->password || "{pwgen}");
       
    96     # assuming usernames of the form localpart@domain
       
    97     $user =~ /@(.+)$/;
       
    98     my $escapes;
       
    99     die "Invalid username '$user'" unless $escapes->{'%u'} = $user
       
   100         and $escapes->{'%1'} = substr $user, 0, 1
       
   101         and $escapes->{'%d'} = $1;
       
   102     my $mbox = $Cf->imap_mail_location;
       
   103     $mbox =~ s/$_/$escapes->{$_}/ for keys %{$escapes};
    97 
   104 
    98     if ($mailPrimaryAddress !~ /@/) {
   105     if ($mailPrimaryAddress !~ /@/) {
    99 	$mailPrimaryAddress .= "@" . $Cf->default_domain;
   106 	$mailPrimaryAddress .= "@" . $Cf->default_domain;
   100     }
   107     }
   101 
   108 
   137 	$e->replace(objectClass => [uniq $e->get("objectClass"), qw/uidObject person/, OC_RECIPIENT]);
   144 	$e->replace(objectClass => [uniq $e->get("objectClass"), qw/uidObject person/, OC_RECIPIENT]);
   138 	$e->replace(uid => [uniq $e->get("uid"), $user]);
   145 	$e->replace(uid => [uniq $e->get("uid"), $user]);
   139 
   146 
   140 	$e->add((AT_ADDRESS) => $mailAddress);
   147 	$e->add((AT_ADDRESS) => $mailAddress);
   141 	$e->add((AT_PRIMARYADDRESS) => $mailPrimaryAddress);
   148 	$e->add((AT_PRIMARYADDRESS) => $mailPrimaryAddress);
   142 	$e->add(userPassword => $pw);
   149 	$e->add(userPassword => "{plain}$pw");
   143 	$e->add((AT_GROUP) => $mailGroup) if @$mailGroup;
   150 	$e->add((AT_GROUP) => $mailGroup) if @$mailGroup;
   144 	$e->add((AT_FORWARDINGADDRESS) => $mailForwardingAddress) if @$mailForwardingAddress;
   151 	$e->add((AT_FORWARDINGADDRESS) => $mailForwardingAddress) if @$mailForwardingAddress;
       
   152 	$e->add((AT_QUOTA) => $Cf->imap_quota);
   145 
   153 
   146 	# $e->add(iusRestrictedMail => $Cf->internal) if $Cf->internal ne ":";
   154 	# $e->add(iusRestrictedMail => $Cf->internal) if $Cf->internal ne ":";
   147 
   155 
   148 	$e->exists("sn") or $e->add(sn => $sn);
   156 	$e->exists("sn") or $e->add(sn => $sn);
   149 	$e->exists("cn") or $e->add(cn => $cn);
   157 	$e->exists("cn") or $e->add(cn => $cn);
   150 
   158 
   151 
   159 
   152 	$r = $e->update($ldap);
   160 	$r = $e->update($ldap);
   153 	die $r->error if $r->code;
   161 	die $r->error if $r->code;
   154 
   162 
   155 	verbose("ok");
   163 	verbose('ok');
   156 	verbose(" Password: $pw") if not $Cf->password or $Cf->password eq "{pwgen}";
   164 	verbose(" Password: $pw") if not $Cf->password or $Cf->password eq "{pwgen}";
   157     }
   165     }
   158 
   166 
   159     if($Cf->mbox) {
   167     if($Cf->mbox) {
   160 	verbose("\n\t$mbox...");
   168 	verbose("\n\t$mbox...");
   161 
   169 
   162 	if ($imap->list($mbox)) { verbose("exists") }
   170 	if (-d $mbox) { verbose('exists') }
   163 	else {
   171 	else {
   164 	    $imap->create($mbox) and verbose("ok") or die $@;
   172 
   165 	    $imap->setacl($mbox, $Cf->imap_admin => "lrswipcda") or die $@;
   173             $imap->login($user, $pw) or die $@;
   166 	    $imap->setquota($mbox, STORAGE => 1024 * $Cf->imap_quota) or die $@;
   174             # 'list' seems to trigger acl file (and thus the maildir) creation with dovecot
   167 	}
   175             $imap->list('', '*') or die $@;
   168     }
   176             verbose('ok');
   169 
   177 	}
       
   178 
       
   179     }
   170 
   180 
   171     verbose("\n");
   181     verbose("\n");
   172 }
   182 }
   173 
   183 
   174 sub _modify() {
   184 sub _modify() {
   185     while (my $e = $r->shift_entry) {
   195     while (my $e = $r->shift_entry) {
   186 	my $r;
   196 	my $r;
   187 
   197 
   188 	my $user = $e->get_value("uid");
   198 	my $user = $e->get_value("uid");
   189 	my $dn = $e->dn;
   199 	my $dn = $e->dn;
   190 	my $mbox = "user/$user";
       
   191 
   200 
   192 	my $modified = 0;
   201 	my $modified = 0;
   193 	verbose "$user:";
   202 	verbose "$user:";
   194 
   203 
   195 	verbose "\n\t$dn...";
   204 	verbose "\n\t$dn...";
   294 	    die $r->error.$r->code if $r->code;
   303 	    die $r->error.$r->code if $r->code;
   295 	}
   304 	}
   296 
   305 
   297 	# FIXME: Wenn keine Mailbox existiert, gibt es hier ein Problem
   306 	# FIXME: Wenn keine Mailbox existiert, gibt es hier ein Problem
   298 	if (defined $Cf->imap_quota) {
   307 	if (defined $Cf->imap_quota) {
   299 	    $imap->setquota($mbox, STORAGE => $Cf->imap_quota * 1024)
   308 #	    $imap->setquota($mbox, STORAGE => $Cf->imap_quota * 1024)
   300 	    or die $@;
   309 #	    or die $@;
   301 	}
   310 	}
   302 
   311 
   303 	verbose "ok\n";
   312 	verbose "ok\n";
   304 
   313 
   305 	print "\n";
   314 	print "\n";
   320 
   329 
   321 
   330 
   322     foreach (@ARGV) {
   331     foreach (@ARGV) {
   323 	my $user = $_;
   332 	my $user = $_;
   324 	my $dn = "uid=$user,$ubase";
   333 	my $dn = "uid=$user,$ubase";
   325 	my $mbox = "user/$user";
       
   326 
   334 
   327 	verbose("$user:\n");
   335 	verbose("$user:\n");
   328 
   336 
   329 	# Nachsehen, ob es noch aliase gibt, in denen dieser Nutzer steht:
   337 	# Nachsehen, ob es noch aliase gibt, in denen dieser Nutzer steht:
   330 	my $r = $ldap->search(base => $abase,
   338 	my $r = $ldap->search(base => $abase,
   350 	    die $r->error;
   358 	    die $r->error;
   351 	}
   359 	}
   352 	verbose("\n");
   360 	verbose("\n");
   353 	
   361 	
   354 	if ($Cf->mbox) {
   362 	if ($Cf->mbox) {
   355 	    verbose("\tdeleting mbox $mbox...");
   363             verbose("\tdeleting mbox for $user...");
   356 	    $imap->delete($mbox) and verbose("ok")
   364             my $m = user_dovecot( 'LOGIN' )->{'home'};
   357 	    or verbose($imap->error);
   365             if (not (defined $m and $m)) { verbose("can't determine mbox location - not deleting it"); }
       
   366             elsif (not unlink $m) { verbose("Can't unlink $m: $!"); }
       
   367             else { verbose('ok'); }
   358 	}
   368 	}
   359 
   369 
   360 	verbose("\n");
   370 	verbose("\n");
   361 
   371 
   362     }
   372     }
   382 	my $cn = join(", ", $e->get_value("cn"));
   392 	my $cn = join(", ", $e->get_value("cn"));
   383 	my $mr = $e->get_value(AT_PRIMARYADDRESS) || "";	# ??
   393 	my $mr = $e->get_value(AT_PRIMARYADDRESS) || "";	# ??
   384 	my $ml = join(", ", $e->get_value(AT_ADDRESS)) || "";	# ??
   394 	my $ml = join(", ", $e->get_value(AT_ADDRESS)) || "";	# ??
   385 	my $mg = join(", ", $e->get_value(AT_GROUP)) || "";	# ??
   395 	my $mg = join(", ", $e->get_value(AT_GROUP)) || "";	# ??
   386 	my $forw = join (", ", $e->get_value(AT_FORWARDINGADDRESS)) || "";
   396 	my $forw = join (", ", $e->get_value(AT_FORWARDINGADDRESS)) || "";
   387 	my $mbox = "user/$uid";
       
   388 
   397 
   389 	print "$uid: $cn <$mr>";
   398 	print "$uid: $cn <$mr>";
   390 
   399 
   391 	#if (($e->get_value("iusRestrictedMail")||"") eq "TRUE") {
   400 	#if (($e->get_value("iusRestrictedMail")||"") eq "TRUE") {
   392 	    #print " INTERNAL";
   401 	    #print " INTERNAL";
   393 	#}
   402 	#}
   394 
   403 
       
   404         $imap->login("$uid*" . $Cf->imap_admin, $imap_password ) or die $@;
       
   405 
   395 	MBOX: {
   406 	MBOX: {
   396 	    if (!$imap->list($mbox)) {
   407 	    if (!$imap->list()) {
   397 		print ", no mbox";
   408 		print ", no mbox";
   398 		last MBOX;
   409 		last MBOX;
   399 	    }
   410 	    }
   400 	    print ", mbox";
   411 	    print ", mbox";
   401 	    my %q = $imap->listquota($mbox);
   412 	    my %q = $imap->listquota();
   402 	    my ($used, $max) = map { int($_ / 1024) } @{$q{STORAGE}};
   413 	    my ($used, $max) = map { int($_ / 1024) } @{$q{STORAGE}};
   403 
   414 
   404 	    if (!$max) {
   415 	    if (!$max) {
   405 		print ", no quota";
   416 		print ", no quota";
   406 		last MBOX;
   417 		last MBOX;