syncing examples
[ira/wip.git] / examples / LDAP / smbldap-tools / smbldap-usermod.pl
1 #!/usr/bin/perl 
2
3 #  This code was developped by IDEALX (http://IDEALX.org/) and
4 #  contributors (their names can be found in the CONTRIBUTORS file).
5 #
6 #                 Copyright (C) 2001-2002 IDEALX
7 #
8 #  This program is free software; you can redistribute it and/or
9 #  modify it under the terms of the GNU General Public License
10 #  as published by the Free Software Foundation; either version 2
11 #  of the License, or (at your option) any later version.
12 #
13 #  This program is distributed in the hope that it will be useful,
14 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #  GNU General Public License for more details.
17 #
18 #  You should have received a copy of the GNU General Public License
19 #  along with this program; if not, write to the Free Software
20 #  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 #  USA.
22
23 # Purpose of smbldap-usermod : user (posix,shadow,samba) modification
24
25 use strict;
26 use smbldap_tools;
27 use smbldap_conf;
28
29
30 #####################
31
32 use Getopt::Std;
33 my %Options;
34 my $nscd_status;
35
36 my $ok = getopts('A:B:C:D:E:F:H:IJxme:f:u:g:G:d:l:s:c:ok:?', \%Options);
37 if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
38         print "Usage: $0 [-awmugdsckxABCDEFGHI?] username\n";
39         print "  -c     gecos\n";
40         print "  -d     home directory\n";
41         #print "  -m    move home directory\n";
42         #print "  -e    expire date (YYYY-MM-DD)\n";
43         #print "  -f    inactive days\n";
44         print "  -u     uid\n";
45         print "  -o     uid can be non unique\n";
46         print "  -g     gid\n";
47         print "  -G     supplementary groups (comma separated)\n";
48         print "  -l     login name\n";
49         print "  -s     shell\n";
50         print "  -x     creates rid and primaryGroupID in hex instead of decimal (for Samba 2.2.2 unpatched only)\n";
51         print "  -A     can change password ? 0 if no, 1 if yes\n";
52         print "  -B     must change password ? 0 if no, 1 if yes\n";
53         print "  -C     sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n";
54         print "  -D     sambaHomeDrive (letter associated with home share, like 'H:')\n";
55         print "  -E     sambaLogonScript (DOS script to execute on login)\n";
56         print "  -F     sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n";
57         print "  -H     sambaAcctFlags (samba account control bits like '[NDHTUMWSLKI]')\n";
58         print "  -I     disable an user. Can't be used with -H or -J\n";
59         print "  -J     enable an user. Can't be used with -H or -I\n";
60         print "  -?     show this help message\n";
61         exit (1);
62 }
63
64 if ($< != 0) {
65     print "You must be root to modify an user\n";
66     exit (1);
67 }
68
69 # Read only first @ARGV
70 my $user = $ARGV[0];
71
72 # Read user datas
73 my $lines = read_user($user);
74 if (!defined($lines)) {
75     print "$0: user $user doesn't exist\n";
76     exit (1);
77 }
78
79 #print "$lines\n";
80 my $dn_line;
81 if ( $lines =~ /(^dn: .*)/ ) {
82     $dn_line = $1;
83 }
84
85 chomp($dn_line);
86
87 my $samba = 0;
88 if ($lines =~ m/objectClass: sambaAccount/) {
89     $samba = 1;
90 }
91
92 ############
93
94 my $tmp;
95 my $mods;
96
97 # Process options
98 my $changed_uid;
99 my $_userUidNumber;
100 my $_userRid;
101 if (defined($tmp = $Options{'u'})) {
102     if (defined($Options{'o'})) {
103         $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
104         
105         if ($nscd_status == 0) {
106             system "/etc/init.d/nscd stop > /dev/null 2>&1";
107         }
108
109         if (getpwuid($tmp)) {
110             if ($nscd_status == 0) {
111                 system "/etc/init.d/nscd start > /dev/null 2>&1";
112             }
113
114             print "$0: uid number $tmp exists\n";
115             exit (6);
116         }
117         if ($nscd_status == 0) {
118             system "/etc/init.d/nscd start > /dev/null 2>&1";
119         }
120
121     }
122     $_userUidNumber = $tmp;
123     # as rid we use 2 * uid + 1000
124     my $_userRid = 2 * $_userUidNumber + 1000;
125     if (defined($Options{'x'})) {
126         $_userRid= sprint("%x", $_userRid);
127     }
128     $mods .= "uidNumber: $_userUidNumber\n";
129     if ($samba) {
130         $mods .= "rid: $_userRid\n";
131     }
132     $changed_uid = 1;
133 }
134
135 my $changed_gid;
136 my $_userGidNumber;
137 my $_userGroupRid;
138 if (defined($tmp = $Options{'g'})) {
139     $_userGidNumber = parse_group($tmp);
140     if ($_userGidNumber < 0) {
141         print "$0: group $tmp doesn't exist\n";
142         exit (6);
143     }
144 # as grouprid we use 2 * gid + 1001
145     my $_userGroupRid = 2 * $_userGidNumber + 1001;
146     if (defined($Options{'x'})) {
147         $_userGroupRid = sprint("%x", $_userGroupRid);
148     }
149     $mods .= "gidNumber: $_userGidNumber\n";
150     if ($samba) {
151         $mods .= "primaryGroupID: $_userGroupRid\n";
152     }
153     $changed_gid = 1;
154 }
155
156 my $changed_shell;
157 my $_userLoginShell;
158 if (defined($tmp = $Options{'s'})) {
159     $_userLoginShell = $tmp;
160     $mods .= "loginShell: $_userLoginShell\n";
161     $changed_shell = 1;
162 }
163
164 my $changed_gecos;
165 my $_userGecos;
166 if (defined($tmp = $Options{'c'})) { 
167     $_userGecos = $tmp;
168     $mods .= "gecos: $_userGecos\n";
169     $changed_gecos = 1;
170 }
171
172 my $changed_homedir;
173 my $newhomedir;
174 if (defined($tmp = $Options{'d'})) {
175     $newhomedir = $tmp; 
176     $mods .= "homeDirectory: $newhomedir\n";
177     $changed_homedir = 1;
178 }
179
180
181 if (defined($tmp = $Options{'G'})) {
182
183     # remove user from old groups
184     my $groups = find_groups_of $user;
185     my @grplines = split(/\n/, $groups);
186
187     my $grp;
188     foreach $grp (@grplines) {
189         my $gname = "";
190         if ( $grp =~ /dn: cn=([^,]+),/) {
191             $gname = $1;
192             #print "xx $gname\n";
193         }
194         if ($gname ne "") {
195             group_remove_member($gname, $user);
196         }
197     }
198
199     # add user to new groups
200     add_grouplist_user($tmp, $user);
201 }
202
203 #
204 # A : sambaPwdCanChange
205 # B : sambaPwdMustChange
206 # C : sambaHomePath
207 # D : sambaHomeDrive
208 # E : sambaLogonScript
209 # F : sambaProfilePath
210 # H : sambaAcctFlags
211
212 my $attr;
213 my $winmagic = 2147483647;
214
215 if (defined($tmp = $Options{'A'})) {
216     $attr = "sambaPwdCanChange";
217     if ($tmp != 0) {
218         $mods .= "$attr: 0\n";
219     } else {
220         $mods .= "$attr: $winmagic\n";
221     }
222 }
223
224 if (defined($tmp = $Options{'B'})) {
225     $attr = "sambaPwdMustChange";
226     if ($tmp != 0) {
227         $mods .= "$attr: 0\n";
228     } else {
229         $mods .= "$attr: $winmagic\n";
230     }
231 }
232
233 if (defined($tmp = $Options{'C'})) {
234     $attr = "sambaHomePath";
235     #$tmp =~ s/\\/\\\\/g;
236     $mods .= "$attr: $tmp\n";
237 }
238
239 if (defined($tmp = $Options{'D'})) {
240     $attr = "sambaHomeDrive";
241     $tmp = $tmp.":" unless ($tmp =~ /:/);
242     $mods .= "$attr: $tmp\n";
243 }
244
245 if (defined($tmp = $Options{'E'})) {
246     $attr = "sambaLogonScript";
247     #$tmp =~ s/\\/\\\\/g;
248     $mods .= "$attr: $tmp\n";
249 }
250
251 if (defined($tmp = $Options{'F'})) {
252     $attr = "sambaProfilePath";
253     #$tmp =~ s/\\/\\\\/g;
254     $mods .= "$attr: $tmp\n";
255 }
256
257 if (defined($tmp = $Options{'H'})) {
258     $attr = "sambaAcctFlags";
259     #$tmp =~ s/\\/\\\\/g;
260     $mods .= "$attr: $tmp\n";
261 } elsif (defined($tmp = $Options{'I'})) {
262     my $flags;
263
264     if ( $lines =~ /^sambaAcctFlags: (.*)/m ) {
265         $flags = $1;
266     }
267
268     chomp($flags);
269
270     if ( !($flags =~ /D/) ) {
271         my $letters;
272         if ($flags =~ /(\w+)/) {
273             $letters = $1;
274         }
275         $mods .= "sambaAcctFlags: \[D$letters\]\n";
276     }
277 } elsif (defined($tmp = $Options{'J'})) {
278     my $flags;
279
280     if ( $lines =~ /^sambaAcctFlags: (.*)/m ) {
281         $flags = $1;
282     }
283
284     chomp($flags);
285
286     if ( $flags =~ /D/ ) {
287         my $letters;
288         if ($flags =~ /(\w+)/) {
289             $letters = $1;
290         }
291         $letters =~ s/D//;
292         $mods .= "sambaAcctFlags: \[$letters\]\n";
293     }
294 }
295
296 if ($mods ne '') {
297     #print "----\n$dn_line\n$mods\n----\n";
298
299     my $tmpldif =
300 "$dn_line
301 changetype: modify
302 $mods
303 ";
304
305     die "$0: error while modifying user $user\n"
306         unless (do_ldapmodify($tmpldif) == 0);
307
308     undef $tmpldif;
309 }
310
311 $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
312
313 if ($nscd_status == 0) {
314    system "/etc/init.d/nscd restart > /dev/null 2>&1";
315 }
316
317
318 ############################################################
319
320 =head1 NAME
321
322        smbldap-usermod.pl - Modify a user account
323
324 =head1 SYNOPSIS
325
326        smbldap-usermod.pl [-c comment] [-d home_dir]
327                [-g initial_group] [-G group[,...]]
328                [-l login_name] [-p passwd]
329                [-s shell] [-u uid [ -o]] [-x]
330                [-A canchange] [-B mustchange] [-C smbhome]
331                [-D homedrive] [-E scriptpath] [-F profilepath]
332                [-H acctflags] login
333
334 =head1 DESCRIPTION
335
336        The  smbldap-usermod.pl  command  modifies the system account files
337        to reflect the changes that are specified on the  command  line.
338        The  options  which apply to the usermod command are
339
340        -c comment
341               The new value of the user's comment field (gecos).
342
343        -d home_dir
344               The user's new login directory.
345
346        -g initial_group
347               The group name or number of the user's new initial login  group.
348               The  group  name  must  exist.   A group number must refer to an
349               already existing group.  The default group number is 1.
350
351        -G group,[...]
352               A list of supplementary groups which the user is also  a  member
353               of.   Each  group is separated from the next by a comma, with no
354               intervening whitespace.  The groups  are  subject  to  the  same
355               restrictions as the group given with the -g option.  If the user
356               is currently a member of a group which is not listed,  the  user
357               will be removed from the group
358
359        -l login_name
360               The  name  of the user will be changed from login to login_name.
361               Nothing else is changed.  In particular, the user's home  direcĀ­
362               tory  name  should  probably be changed to reflect the new login
363               name.
364
365        -s shell
366               The name of the user's new login shell.  Setting this  field  to
367               blank causes the system to select the default login shell.
368
369        -u uid The  numerical  value  of  the  user's  ID.   This value must be
370               unique, unless the -o option is used.  The value  must  be  non-
371               negative.  Any files which the user owns  and  which  are
372               located  in  the directory tree rooted at the user's home direcĀ­
373               tory will have the file user ID  changed  automatically.   Files
374               outside of the user's home directory must be altered manually.
375
376        -x     Creates rid and primaryGroupID in hex instead of decimal (for 
377               Samba 2.2.2 unpatched only - higher versions always use decimal)
378
379        -A     can change password ? 0 if no, 1 if yes
380
381        -B     must change password ? 0 if no, 1 if yes
382
383        -C     sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')
384
385        -D     sambaHomeDrive (letter associated with home share, like 'H:')
386
387        -E     sambaLogonScript, relative to the [netlogon] share (DOS script to execute on login, like 'foo.bat')
388
389        -F     sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
390
391        -H     sambaAcctFlags, spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]')
392
393        -I     disable user. Can't be used with -H or -J
394
395        -J     enable user. Can't be used with -H or -I
396
397 =head1 SEE ALSO
398
399        usermod(1)
400
401 =cut
402
403 #'