#!/usr/bin/perl # # ldap2nis - Update the GECOS fields for Unix accounts based on information in # an LDAP server. This script makes use of the FreeBSD pw(8) command, and the # Mozilla::LDAP CPAN modules. # # This script was created February, 2001 by Danny Howard, of Tellme Networks. # The author can be contacted by e-mailing dannyman@toldme.com. # # Tellme Open Source License # # Permission is hereby granted under the copyrights of Tellme, free of charge, # to any person obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to the # following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # Your LDAP server and base DN. my $ldap_serv = "ldap.your.com"; my $ldap_base = "dc=your,dc=com"; # The UID range you wish to sync against LDAP. my $nis_minid = 500; my $nis_maxid = 50000; # "Special" accounts that you do not wish to attempt to update against LDAP, # perhaps because they are not in LDAP, and you want to run this script out of # cron without seeing the same damn error message all the time. Ideally, you # filter out accounts with the $nis_minid and $nis_maxid, but who has an ideal # set-up? :) my @exclude = ( 'postfix', 'operator' ); # LDAP use Mozilla::LDAP::Conn; use Mozilla::LDAP::Utils; my $conn = new Mozilla::LDAP::Conn("$ldap_serv"); die "Couldn't connect to LDAP server $ldap_serv: $!\n" unless $conn; for (@exclude) { $excludes{$_}++; } # Array -> Hash makes it easy to # check for exclusions # Iterate through your Unix passwd database. while ( my @nis = getpwent() ) { if( $nis[2] >= $nis_minid && $nis[2] <= $nis_maxid &! $excludes{$nis[0]} ) { # Search ... my $ldap = $conn->search($ldap_base, "(ou=People)", "(uid=$nis[0])"); # Change warn to die if you want this error condition to be # fatal. if(! $ldap ) { warn "*** NIS user $nis[0] not found in LDAP!\n"; } # Aseemble the GECOS field, which is: # "name", "office", "office phone", "home phone" # We fill this in with these LDAP attributes: # "cn", (nothing), "telephonenumber", "homephone" # You will probably want to tweak this to match your schema. my $gecos = "$ldap->{cn}[0],,$ldap->{telephonenumber}[0],$ldap->{homephone}[0]"; $gecos =~ s/,://g; # Keep these out of your GECOS # Update only if there is a discrepancy. The only output this # script generates are errors and whether it has to actually # update anything. This makes it more cronnable. If you are # not running FreeBSD, you'll have to find a satisfactory way # to update your GECOS field. if( $nis[6] ne $gecos ) { print "$nis[0]: $nis[6] -> $gecos\n"; system("/usr/sbin/pw", "usermod", $nis[0], '-c', "$gecos"); } } }