Initial import
[samba] / examples / LDAP / smbldap-tools-0.9.1 / smbldap-userinfo
1 #!/usr/bin/perl -w
2
3 # Created by P.Wieleba@iem.pw.edu.pl in 2004
4
5 use strict;
6 use Getopt::Std;
7 use FindBin;
8 use FindBin qw($RealBin);
9 use lib "$RealBin/";
10 use smbldap_tools;
11
12 # function declaration
13 sub exist_in_tab;
14
15 my %Options;
16
17 my $ok = getopts('f:r:w:h:o:s:?v', \%Options);
18 if ( (!$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
32 my $user;
33 my $pass;
34 if ( $< != 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
46 if (!defined($user)) {
47   $user = getpwuid($<);
48 }
49
50 my ($dn,$ldap_master);
51 # First, connecting to the directory
52 if ($< != 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
83 my %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
93 my $entry = read_user_entry($user);
94 my $gecos = $entry->get_value('gecos');
95 my %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
106 foreach my $key (keys %old) {
107   !defined($old{$key}) and $old{$key}="";
108 }
109
110 # read new values
111 my %new;
112 if ($Options{'f'}) {
113   $new{'name'} = $Options{'f'};
114 }
115 if ($Options{'r'}) {
116   $new{'office'} = $Options{'r'};
117 }
118 if ($Options{'w'}) {
119   $new{'wphone'} = $Options{'w'};
120 }
121 if ($Options{'h'}) {
122   $new{'hphone'} = $Options{'h'};
123 }
124 if ($Options{'o'}) {
125   $new{'other'} = $Options{'o'};
126 }
127 if ($Options{'s'}) {
128   $new{'shell'} = $Options{'s'};
129 }
130 if ( 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
149 foreach my $key (keys %old) {
150   if (!$new{$key}) {
151     $new{$key} = $old{$key};
152   }
153 }
154
155 # simple check of new values
156 foreach 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
170 if ( $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
180 if ( !$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
194 my @tmp = split(/\s+/,$new{'name'});
195 my $sn = $tmp[$#tmp];
196 pop(@tmp);
197 my $givenName = join(' ',@tmp);
198
199 $entry->replace( 'gecos' => $gecos );
200 $entry->replace( 'cn'    => $new{'name'} );
201
202 if ( 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
229 if ( $new{'shell'} ) {
230   $entry->replace('loginShell' => $new{'shell'});
231 } else {
232   $entry->get_value('loginShell') and $entry->delete('loginShell');
233 }
234
235 if ($Options{'v'}) {
236   $entry->dump();
237 }
238 # bind to LDAP and update entry
239 $ldap_master = connect_ldap_master();
240 my $mesg = $entry->update($ldap_master);
241 if ($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);
250 sub 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
267 smbldap-chfn - change user real name, information and shell
268
269 =head1 SYNOPSIS
270
271 smbldap-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
276 This command changes user gecos fields and login shell.
277 The normal user can change only the fields for his own account,
278 the super user may change the fiels for any account.
279
280 If none of the options are selected, the command is run
281 in an interactive mode for the current user account. User is
282 asked for all fields. To accept a default value you should 
283 just press <ENTER>, otherwise write text and press <ENTER>.
284
285 posixAccount objectClasses has to be present in the modified
286 entry. If inetOrgPerson objectClass is also present additional
287 attributes will be changed (givenName,sn,roomNumber,telephoneNumber,
288 homePhone)
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