1#!/usr/bin/perl -w 2 3# Created by P.Wieleba@iem.pw.edu.pl in 2004 4 5use strict; 6use Getopt::Std; 7use FindBin; 8use FindBin qw($RealBin); 9use lib "$RealBin/"; 10use smbldap_tools; 11 12# function declaration 13sub exist_in_tab; 14 15my %Options; 16 17my $ok = getopts('f:r:w:h:o:s:?v', \%Options); 18if ( (!$ok) || ($Options{'?'}) ) { 19 print "Usage: $0 [-frwhosh?] username\n"; 20 print " -?|-h show this help message\n"; 21 print " -f full_name\n"; 22 print " -r room_no\n"; 23 print " -w work_ph\n"; 24 print " -h home_ph\n"; 25 print " -o other\n"; 26 print " -s shell\n"; 27 print " -v show modified user record\n"; 28 exit (1); 29} 30 31 32my $user; 33my $pass; 34if ( $< != 0 ) { 35 my $current_user = getpwuid($<); 36 if ($current_user and $ARGV[0] and $current_user ne $ARGV[0] ) { 37 die "Only root can change other users inormation\n"; 38 } 39} else { 40 if ( $ARGV[0] ) { 41 $user = $ARGV[0]; 42 } 43 $pass = 1; 44} 45 46if (!defined($user)) { 47 $user = getpwuid($<); 48} 49 50my ($dn,$ldap_master); 51# First, connecting to the directory 52if ($< != 0) { 53 # non-root user 54 if (!defined($pass)) { 55 # prompt for password 56 print "UNIX password: "; 57 system "stty -echo" if (-t STDIN); 58 chomp($pass=<STDIN>); 59 system "stty echo" if (-t STDIN); 60 print "\n"; 61 62 $config{masterDN}="uid=$user,$config{usersdn}"; 63 $config{masterPw}="$pass"; 64 $ldap_master=connect_ldap_master(); 65 $dn=$config{masterDN}; 66 if (!is_user_valid($user, $dn, $pass)) { 67 print "Authentication failure\n"; 68 exit (10); 69 } 70 } 71} else { 72 # root user 73 $ldap_master=connect_ldap_master(); 74 # test existence of user in LDAP 75 my $dn_line; 76 if (!defined($dn_line = get_user_dn($user))) { 77 print "$0: user $user doesn't exist\n"; 78 exit (10); 79 } 80 $dn = get_dn_from_line($dn_line); 81} 82 83my %eng = ( 84 'shell' => 'User Shell', 85 'name' => 'Full Name', 86 'office' => 'Room Number', 87 'wphone' => 'Work Phone', 88 'hphone' => 'Home Phone', 89 'other' => 'Other' 90 ); 91 92# obtain old values 93my $entry = read_user_entry($user); 94my $gecos = $entry->get_value('gecos'); 95my %old; 96( $old{'name'}, 97 $old{'office'}, 98 $old{'wphone'}, 99 $old{'hphone'}, 100 $old{'other'} 101) = split(/,/,$gecos); 102$old{'shell'} = $entry->get_value('LoginShell'); 103# unbind from LDAP 104$ldap_master->unbind(); 105 106foreach my $key (keys %old) { 107 !defined($old{$key}) and $old{$key}=""; 108} 109 110# read new values 111my %new; 112if ($Options{'f'}) { 113 $new{'name'} = $Options{'f'}; 114} 115if ($Options{'r'}) { 116 $new{'office'} = $Options{'r'}; 117} 118if ($Options{'w'}) { 119 $new{'wphone'} = $Options{'w'}; 120} 121if ($Options{'h'}) { 122 $new{'hphone'} = $Options{'h'}; 123} 124if ($Options{'o'}) { 125 $new{'other'} = $Options{'o'}; 126} 127if ($Options{'s'}) { 128 $new{'shell'} = $Options{'s'}; 129} 130if ( keys(%Options) < 1 or keys(%Options) == 1 and $Options{'v'} ) { 131 print "Changing the user information for $user\n"; 132 print "Enter the new value, or press ENTER for the default\n"; 133 134 print " $eng{'shell'} [$old{'shell'}]:"; 135 $new{'shell'} = readline(*STDIN); 136 print " $eng{'name'} [$old{'name'}]:"; 137 $new{'name'} = readline(*STDIN); 138 print " $eng{'office'} [$old{'office'}]:"; 139 $new{'office'} = readline(*STDIN); 140 print " $eng{'wphone'} [$old{'wphone'}]:"; 141 $new{'wphone'} = readline(*STDIN); 142 print " $eng{'hphone'} [$old{'hphone'}]:"; 143 $new{'hphone'} = readline(*STDIN); 144 print " $eng{'other'} [$old{'other'}]:"; 145 $new{'other'} = readline(*STDIN); 146} 147 148 149foreach my $key (keys %old) { 150 if (!$new{$key}) { 151 $new{$key} = $old{$key}; 152 } 153} 154 155# simple check of new values 156foreach my $key (keys %new) { 157 chop($new{$key}) if ( $new{$key}=~/\n$/ ); 158 if ($new{$key} =~ /^\s+$/ and $key ne 'shell') { 159 $new{$key} = ""; 160 } elsif ($new{$key} =~ /^$/) { 161 $new{$key} = $old{$key}; 162 } elsif ($key ne 'other' and $new{$key} =~ /.*,.*/) { 163 print "Comma cannot be used with $key.\n"; 164 exit(6); 165 } 166 # $new{$key} eq "" 167} 168 169# [TODO] check if shell really exists 170if ( $new{'shell'} and !($new{'shell'}=~/^\/.+\/.+/) 171 and ($old{'shell'}=~/^\/.+\/.+/) 172 ) { 173 $new{'shell'} = $old{'shell'}; 174} elsif ( $new{'shell'} and !($new{'shell'}=~/^\/.+\/.+/) 175 or !$new{'shell'} and !$old{'shell'} 176 ) { 177 $new{'shell'} = '/bin/sh'; 178} 179 180if ( !$new{'name'} ) { 181 $new{'name'} = $user; 182} 183 184# prepare gecos field 185$gecos = join(',', 186 ( $new{'name'}, 187 $new{'office'}, 188 $new{'wphone'}, 189 $new{'hphone'}, 190 $new{'other'} 191 ) 192 ); 193 194my @tmp = split(/\s+/,$new{'name'}); 195my $sn = $tmp[$#tmp]; 196pop(@tmp); 197my $givenName = join(' ',@tmp); 198 199$entry->replace( 'gecos' => $gecos ); 200$entry->replace( 'cn' => $new{'name'} ); 201 202if ( exist_in_tab( [$entry->get_value('objectClass')],'inetOrgPerson') ) { 203 if ( $sn ) { 204 $entry->replace('sn' => $sn); 205 } else { 206 $entry->replace('sn' => $user); 207 } 208 if ( $givenName ) { 209 $entry->replace('givenName' => $givenName); 210 } else { 211 $entry->get_value('givenName') and $entry->delete('givenName'); 212 } 213 if ( $new{'office'} ) { 214 $entry->replace('roomNumber' => $new{'office'}); 215 } else { 216 $entry->get_value('roomNumber') and $entry->delete('roomNumber'); 217 } 218 if ( $new{'wphone'} ) { 219 $entry->replace('telephoneNumber' => $new{'wphone'}); 220 } else { 221 $entry->get_value('telephoneNumber') and $entry->delete('telephoneNumber'); 222 } 223 if ( $new{'hphone'} ) { 224 $entry->replace('homePhone' => $new{'hphone'}); 225 } else { 226 $entry->get_value('homePhone') and $entry->delete('homePhone'); 227 } 228} #end of inetOrgPerson 229if ( $new{'shell'} ) { 230 $entry->replace('loginShell' => $new{'shell'}); 231} else { 232 $entry->get_value('loginShell') and $entry->delete('loginShell'); 233} 234 235if ($Options{'v'}) { 236 $entry->dump(); 237} 238# bind to LDAP and update entry 239$ldap_master = connect_ldap_master(); 240my $mesg = $entry->update($ldap_master); 241if ($mesg->is_error()) { 242 print "Error: " . $mesg->error() . "\n"; 243} else { 244 print "LDAP updated\n"; 245} 246$ldap_master and $ldap_master->unbind; 247 248# Check if a $text element exists in @table 249# eg. exist_in_tab(\@table,$text); 250sub exist_in_tab 251 { 252 my($ref_tab,$text) = @_; 253 my @tab = @$ref_tab; 254 255 foreach my $elem (@tab) { 256 if ( lc($elem) eq lc($text) ) { 257 return 1; 258 } 259 } 260 return 0; 261 } 262 263######################################## 264 265=head1 NAME 266 267smbldap-chfn - change user real name, information and shell 268 269=head1 SYNOPSIS 270 271smbldap-chfn [-f full_name] [-r room_no] [-w work_ph] [-h home_ph] 272[-o other] [-s login_shell] [-?] [-v] 273 274=head1 DESCRIPTION 275 276This command changes user gecos fields and login shell. 277The normal user can change only the fields for his own account, 278the super user may change the fiels for any account. 279 280If none of the options are selected, the command is run 281in an interactive mode for the current user account. User is 282asked for all fields. To accept a default value you should 283just press <ENTER>, otherwise write text and press <ENTER>. 284 285posixAccount objectClasses has to be present in the modified 286entry. If inetOrgPerson objectClass is also present additional 287attributes will be changed (givenName,sn,roomNumber,telephoneNumber, 288homePhone) 289 290-f full_name 291 affected attributes: 'gecos', 'cn' (and 'givenName', 'sn' 292 if inetOrgPerson is present) 293 294-r room_number 295 affected attributes: 'gecos' (and 'roomNumber' 296 if inetOrgPerson is present) 297 298-w work_phone 299 affected attributes: 'gecos' (and 'telephoneNumber' 300 if inetOrgPerson is present) 301 302-h home_phone 303 affected attributes: 'gecos' (and 'homePhone' 304 if inetOrgPerson is present) 305 306-o other 307 affected attributes: 'gecos' 308 309-s login_shell 310 affected attributes: 'loginShell' 311 312-? show the help message 313 314-v verbose - show modified user entry 315 316=cut 317 318#' 319 320# The End 321 322