1: #!/usr/bin/perl -w 2: # by Steve Haslam 3: 4: # description: 5: 6: # adds a user into an LDAP group- where "users" and "groups" are the 7: # objects seen by nss_ldap. 8: 9: # would be nice to be able to use pam-ldap here, but I've not got 10: # that to work yet. 11: 12: # notes: 13: # at least on my machine, Term::Readkey gives loads of "use of 14: # uninitialized value" errors. ymmv. 15: 16: # illustrates lots of things, and a resonably nice showcase for some 17: # techniques for working with Net::LDAP (e.g. the ldapassert() sub) 18: 19: require 5; 20: use strict; 21: use Net::LDAP; 22: use Net::LDAP::Util qw(ldap_error_text); 23: use Term::ReadKey; 24: use Getopt::Std; 25: use vars qw($hostname $basedn $ldap $sr $username $groupname $userdn $groupdn $entry $admindn $adminpw $verbose %opts); 26: 27: getopts('h:D:b:v', \%opts) && @ARGV == 2 or die "Syntax: $0 [-v] [-h hostname] [-D binddn] [-b basedn] username groupname"; 28: 29: ($username, $groupname) = (lc($ARGV[0]), lc($ARGV[1])); 30: 31: $verbose = 1 if ($opts{'v'}); 32: 33: # Print something if the -v switch was given 34: sub printv { 35: print(@_) if ($verbose); 36: } 37: 38: # Wrapper for a Net::LDAP call- assert the server message is a "success" 39: # code- die with a decoded error message if it isn't 40: sub ldapassert { 41: my $mesg = shift; 42: my $op = shift; 43: $mesg->code && die "LDAP error".($op?" during $op":"").": ".ldap_error_text($mesg->code)."\n"; 44: $mesg; 45: } 46: 47: # Extract a configuration option from the nss-ldap configuration file 48: # /etc/libnss-ldap.conf is the Debian conf file location 49: # /etc/ldap.conf is an alternative plausible location 50: sub confoption { 51: my $optname = lc(shift); 52: my $conffile; 53: 54: foreach $conffile (qw|/etc/libnss-ldap.conf /etc/ldap.conf|) { 55: if (-f $conffile) { 56: open(LDAPCONF, $conffile) or die "Unable to open nss-ldap configuration file $conffile: $!\n"; 57: while (<LDAPCONF>) { 58: s/\#.*//; 59: chomp; 60: my($keyword, $value) = split(/ +/, $_, 2); 61: next unless (defined($keyword) && defined($value)); 62: $keyword = lc($keyword); 63: if ($keyword eq $optname) { 64: close(LDAPCONF); 65: printv "[ldapconf $conffile] using \"$value\" for \"$optname\"\n"; 66: return $value; 67: } 68: } 69: return undef; 70: } 71: } 72: 73: printv "[ldapconf] no value for \"$optname\"\n"; 74: 75: return undef; 76: } 77: 78: $hostname = $opts{'h'} || confoption('host'); 79: $basedn = $opts{'b'} || confoption('base'); 80: 81: $ldap = Net::LDAP->new($hostname) or die "$@"; 82: 83: # Bind as administrator user 84: $admindn = $opts{'D'} || confoption('binddn'); 85: 86: # Get admin password iff a bind dn was specified 87: if ($admindn) { 88: print "LDAP password: "; 89: ReadMode('noecho'); 90: $adminpw = ReadLine; 91: chomp($adminpw); 92: ReadMode(0); 93: print "\n"; 94: } 95: 96: # Perform bind 97: # bind anonymously if no pw given 98: if ($adminpw) { 99: printv "Binding as $admindn\n"; 100: ldapassert($ldap->bind(dn => $admindn, password => $adminpw), "bind"); 101: } 102: else { 103: printv "Binding anonymously\n"; 104: ldapassert($ldap->bind, "anonymous bind"); 105: } 106: 107: # Find the user- get the user dn 108: $sr = ldapassert($ldap->search(base => "ou=People, $basedn", filter => "(&(objectClass=posixAccount)(uid=$username))"), "user search"); 109: 110: if ($sr->count == 0) { 111: die "Unknown user '$username'\n"; 112: } 113: elsif ($sr->count > 1) { 114: die "Ambiguous user '$username' (this is really bad)\n"; 115: } 116: 117: $entry = $sr->shift_entry; 118: $userdn = $entry->dn; 119: 120: # Find the group- get the group dn 121: $sr = ldapassert($ldap->search(base => "ou=Group, $basedn", filter => "(&(objectClass=posixGroup)(cn=$groupname))"), "group search"); 122: 123: if ($sr->count == 0) { 124: die "Unknown group '$groupname'\n"; 125: } 126: elsif ($sr->count > 1) { 127: die "Ambiguous group '$groupname' (this is really bad)\n"; 128: } 129: 130: $entry = $sr->shift_entry; 131: $groupdn = $entry->dn; 132: 133: # Is the user already in the group? 134: foreach (@{$entry->get('memberuid')}) { 135: if (lc($_) eq lc($username)) { 136: print "$username is already a member of $groupname\n"; 137: exit(0); 138: } 139: } 140: 141: # OK, now update the group entry 142: # $entry is the group entry 143: printv "Adding [$userdn] to [$groupdn]\n"; 144: 145: $entry->add(memberuid => $username); 146: 147: ldapassert($entry->update($ldap), "update"); # Write updated entry to directory server 148: 149: exit(0);
Back to
Craft