Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Add a user to a group- when using nss-ldap, using Net::LDAP

by araqnid (Beadle)
on Sep 12, 2000 at 20:32 UTC ( #32126=perlcraft: print w/ replies, xml ) Need Help??

   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);

Comment on Add a user to a group- when using nss-ldap, using Net::LDAP
Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlcraft [id://32126]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (6)
As of 2015-07-03 23:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (57 votes), past polls