1#!/usr/bin/perl
2# chfn implementation for LDAP
3# Copyright (C) 2000 Tom Lear <tom@trap.mtview.ca.us>
4
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18#
19
20# read login.defs
21open(CONF,"/etc/login.defs") or die "$!\n";
22while(<CONF>) {
23  next if(m/^\s*($|#)/);
24  $CHFN_RESTRICT=$1 if(m/^\s*CHFN_RESTRICT\s+(.*?)\s*$/);
25}
26close(CONF);
27$CHFN_RESTRICT='rwh' if($CHFN_RESTRICT eq 'yes');
28$CHFN_RESTRICT='frwh' if($CHFN_RESTRICT eq 'no');
29
30$CHFN_RESTRICT='frwho' if($<==0);
31
32while($ARGV[0]=~m/^-([frwho])$/) {
33  shift;
34  my $let=$1;
35  $new{$let}=shift;
36  die "You can't change that field.\n" if($CHFN_RESTRICT!~m/$let/);
37}
38
39$user=$ARGV[0];
40if($user eq '') {
41  $user=(getpwuid($<))[0];
42} else {
43  die "You can't change that user.\n" if($< and $<!=getpwnam($user));
44}
45
46# use pam_ldap's config file since this script is ldap specific and
47# is a work around for a deficiency in pam
48$CONF{'pam_login_attribute'}='uid';
49open(CONF,"/etc/ldap.conf") or die "$!\n";
50while(<CONF>) {
51  next if(m/^\s*($|#)/);
52  m/^\s*(\S+)\s+(.*?)\s*$/;
53  $CONF{$1}=$2;
54}
55close(CONF);
56open(CONF,"/etc/ldap.secret") and chomp($CONF{'rootbindpw'}=<CONF>);
57close(CONF);
58
59%FIELDS=(
60  'f' =>        'Full Name',
61  'r' =>        'Room Number',
62  'w' =>        'Work Phone',
63  'h' =>        'Home Phone',
64  'o' =>        'Other',
65);
66
67use Net::LDAP;
68
69$ldap=Net::LDAP->new($CONF{'host'});
70
71if($< or $CONF{'rootbinddn'} eq '') {
72  $ENV{'PATH'}='';
73  system "/bin/stty -echo";
74  print 'Password:';
75  chomp($password = <STDIN>);
76  print "\n";
77  system "/bin/stty echo";
78  %bindargs=('dn'         => "$CONF{pam_login_attribute}=$user,ou=People,$CONF{base}",
79             'password'   => $password,
80  );
81} else {
82  %bindargs=('dn'         => $CONF{'rootbinddn'},
83             'password'   => $CONF{'rootbindpw'},
84  );
85}
86$bindargs{'version'}=$CONF{'ldap_version'}?$CONF{'ldap_version'}:2;
87
88$ldap->bind(%bindargs) or die "unable to bind to ldap server: $@";
89
90# get the current values
91@gecos=split(',',(getpwnam($user))[6]);
92
93# get the new entries if neccesary
94if(!defined %new) {
95  print "Enter the new value, or press return for the default\n";
96  @fields=('f','r','w','h');
97  push(@fields, 'o') if($<==0);
98  foreach(@fields) {
99    if($CHFN_RESTRICT=~m/$_/) {
100      print "\t$FIELDS{$_} [$gecos[$i]]: ";
101      chomp($new{$_}=<STDIN>);
102      $new{$_}=$gecos[$i] if($new{$_} eq '');
103    } else {
104      print "\t$FIELDS{$_}: $gecos[$i]\n";
105    }
106    $i++;
107  }
108}
109
110# check the entries validity
111$i=0;
112foreach('f','r','w','h','o') {
113  die "invalid entry: \"$new{$_}\"\n" if($new{$_}!~m/^[ -~]*$/ or $new{$_}=~m/[:,=]/);
114  $gecos[$i]=$new{$_} if(defined $new{$_});
115  $i++;
116}
117
118# change the gecos field
119$gecos[3].='';
120$ret=$ldap->modify("$CONF{pam_login_attribute}=$user,ou=People,$CONF{base}",
121        replace => {'gecos' => join(',',@gecos)});
122if($ret->code) {
123  printf STDERR ("failed: %s\n",$ret->error);
124}
125
126