• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/samba-3.0.13/examples/LDAP/smbldap-tools-0.8.7/
1#!/usr/bin/perl -w
2
3# $Id: smbldap-useradd,v 1.25 2005/01/29 15:00:54 jtournier Exp $
4#
5#  This code was developped by IDEALX (http://IDEALX.org/) and
6#  contributors (their names can be found in the CONTRIBUTORS file).
7#
8#                 Copyright (C) 2002 IDEALX
9#
10#  This program is free software; you can redistribute it and/or
11#  modify it under the terms of the GNU General Public License
12#  as published by the Free Software Foundation; either version 2
13#  of the License, or (at your option) any later version.
14#
15#  This program is distributed in the hope that it will be useful,
16#  but WITHOUT ANY WARRANTY; without even the implied warranty of
17#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18#  GNU General Public License for more details.
19#
20#  You should have received a copy of the GNU General Public License
21#  along with this program; if not, write to the Free Software
22#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23#  USA.
24
25# Purpose of smbldap-useradd : user (posix,shadow,samba) add
26
27use strict;
28
29use FindBin;
30use FindBin qw($RealBin);
31use lib "$RealBin/";
32use smbldap_tools;
33use Crypt::SmbHash;
34#####################
35
36
37use Getopt::Std;
38my %Options;
39
40my $ok = getopts('o:anmwiPG:u:g:d:s:c:k:A:B:C:D:E:F:H:M:N:S:T:?', \%Options);
41
42if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
43  print_banner;
44  print "Usage: $0 [-awmugdsckABCDEFGHMNPST?] username\n";
45  print "  -o	add the user in the organazional unit (relative to the user suffix)\n";
46  print "  -a	is a Windows User (otherwise, Posix stuff only)\n";
47  print "  -w	is a Windows Workstation (otherwise, Posix stuff only)\n";
48  print "  -i	is a trust account (Windows Workstation)\n";
49  print "  -u	uid\n";
50  print "  -g	gid\n";
51  print "  -G	supplementary comma-separated groups\n";
52  print "  -n	do not create a group\n";
53  print "  -d	home\n";
54  print "  -s	shell\n";
55  print "  -c	gecos\n";
56  print "  -m	creates home directory and copies /etc/skel\n";
57  print "  -k	skeleton dir (with -m)\n";
58  print "  -P	ends by invoking smbldap-passwd\n";
59  print "  -A	can change password ? 0 if no, 1 if yes\n";
60  print "  -B	must change password ? 0 if no, 1 if yes\n";
61  print "  -C	sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n";
62  print "  -D	sambaHomeDrive (letter associated with home share, like 'H:')\n";
63  print "  -E	sambaLogonScript (DOS script to execute on login)\n";
64  print "  -F	sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n";
65  print "  -H	sambaAcctFlags (samba account control bits like '[NDHTUMWSLKI]')\n";
66  print "  -N	canonical name\n";
67  print "  -S	surname\n";
68  print "  -M	local mailAddress (comma seperated)\n";
69  print "  -T	mailToAddress (forward address) (comma seperated)\n";
70  print "  -?	show this help message\n";
71  exit (1);
72}
73
74my $ldap_master=connect_ldap_master();
75
76
77# cause problems when dealing with getpwuid because of the
78# negative ttl and ldap modification
79my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
80
81if ($nscd_status == 0) {
82  system "/etc/init.d/nscd stop > /dev/null 2>&1";
83}
84
85
86# Read only first @ARGV
87my $userName = $ARGV[0];
88
89# For computers account, add a trailing dollar if missing
90if (defined($Options{'w'})) {
91  if ($userName =~ /[^\$]$/s) {
92    $userName .= "\$";
93  }
94}
95
96# untaint $userName (can finish with one or two $)
97if ($userName =~ /^([\w -.]+\$?)$/) {
98  $userName = $1;
99} else {
100  print "$0: illegal username\n";
101  exit (1);
102}
103
104# user must not exist in LDAP (should it be nss-wide ?)
105my ($rc, $dn) = get_user_dn2($userName);
106if ($rc and defined($dn)) {
107  print "$0: user $userName exists\n";
108  exit (9);
109} elsif (!$rc) {
110  print "$0: error in get_user_dn2\n";
111  exit(10);
112}
113
114# Read options
115# we create the user in the specified ou (relative to the users suffix)
116my $user_ou=$Options{'o'};
117if (defined $user_ou) {
118  $config{usersdn}="$user_ou,$config{usersdn}";
119}
120
121my $userUidNumber = $Options{'u'};
122if (!defined($userUidNumber)) { 
123  $userUidNumber=get_next_id($config{usersdn},"uidNumber");
124} elsif (getpwuid($userUidNumber)) {
125  die "Uid already exists.\n";
126}
127
128if ($nscd_status == 0) {
129  system "/etc/init.d/nscd start > /dev/null 2>&1";
130}
131
132my $createGroup = 0;
133my $userGidNumber = $Options{'g'};
134# gid not specified ? 
135if (!defined($userGidNumber)) {
136  # windows machine => $config{defaultComputerGid}
137  if (defined($Options{'w'})) {
138    $userGidNumber = $config{defaultComputerGid};
139    #    } elsif (!defined($Options{'n'})) {
140    # create new group (redhat style)
141    # find first unused gid starting from $config{GID_START}
142    #	while (defined(getgrgid($config{GID_START}))) {
143    #		$config{GID_START}++;
144    #	}
145    #	$userGidNumber = $config{GID_START};
146
147    #	$createGroup = 1;
148
149  } else {
150    # user will have gid = $config{defaultUserGid}
151    $userGidNumber = $config{defaultUserGid};
152  }
153} else {
154  my $gid;
155  if (($gid = parse_group($userGidNumber)) < 0) {
156    print "$0: unknown group $userGidNumber\n";
157    exit (6);
158  }
159  $userGidNumber = $gid;
160}
161
162my $group_entry;
163my $userGroupSID;
164my $userRid;
165my $user_sid;
166if (defined $Options{'a'} or defined $Options{'i'}) {
167  # as grouprid we use the value of the sambaSID attribute for
168  # group of gidNumber=$userGidNumber
169  $group_entry = read_group_entry_gid($userGidNumber);
170  $userGroupSID = $group_entry->get_value('sambaSID');
171  unless ($userGroupSID) {
172    print "Error: SID not set for unix group $userGidNumber\n";
173    print "check if your unix group is mapped to an NT group\n";
174    exit (7);
175  }
176
177  # as rid we use 2 * uid + 1000
178  $userRid = 2 * $userUidNumber + 1000;
179  # let's test if this SID already exist
180  $user_sid="$config{SID}-$userRid";
181  my $test_exist_sid=does_sid_exist($user_sid,$config{usersdn});
182  if ($test_exist_sid->count == 1) {
183    print "User SID already owned by\n";
184    # there should not exist more than one entry, but ...
185    foreach my $entry ($test_exist_sid->all_entries) {
186      my $dn= $entry->dn;
187      chomp($dn);
188      print "$dn\n";
189    }
190    exit(7);
191  }
192}
193
194my $userHomeDirectory;
195my ($userCN, $userSN);
196my @userMailLocal;
197my @userMailTo;
198my $tmp;
199if (!defined($userHomeDirectory = $Options{'d'})) {
200  $userHomeDirectory = &subst_user($config{userHome}, $userName);
201}
202$userHomeDirectory=~s/\/\//\//;
203$config{userLoginShell} = $tmp if (defined($tmp = $Options{'s'}));
204$config{userGecos} = $tmp if (defined($tmp = $Options{'c'}));
205$config{skeletonDir} = $tmp if (defined($tmp = $Options{'k'}));
206$userCN = ($Options{'c'} || $userName);
207$userCN = $tmp if (defined($tmp = $Options{'N'}));
208$userSN = $userName;
209$userSN = $tmp if (defined($tmp = $Options{'S'}));
210@userMailLocal = &split_arg_comma($Options{'M'});
211@userMailTo = &split_arg_comma($Options{'T'});
212
213########################
214
215# MACHINE ACCOUNT
216if (defined($Options{'w'}) or defined($Options{'i'})) {
217   
218  #print "About to create machine $userName:\n";
219
220  if (!add_posix_machine ($userName, $userUidNumber, $userGidNumber)) {
221    die "$0: error while adding posix account\n";
222  }
223
224  if (defined($Options{'i'})) {
225    # For machine trust account
226    # Objectclass sambaSAMAccount must be added now !
227    my $pass;
228    my $pass2;
229
230    system "stty -echo";
231    print "New password : ";
232    chomp($pass=<STDIN>); 
233    print "\n";
234    system "stty echo";
235
236    system "stty -echo";
237    print "Retype new password : ";
238    chomp($pass2=<STDIN>);
239    print "\n";
240    system "stty echo";
241
242    if ($pass ne $pass2) {
243      print "New passwords don't match!\n";
244      exit (10);
245    }
246    my ($lmpassword,$ntpassword) = ntlmgen $pass;
247    my $date=time;
248    my $modify = $ldap_master->modify ( "uid=$userName,$config{computersdn}",
249					changes => [
250						    replace => [objectClass => ['inetOrgPerson', 'posixAccount', 'sambaSAMAccount']],
251						    add => [sambaLogonTime => '0'],
252						    add => [sambaLogoffTime => '2147483647'],
253						    add => [sambaKickoffTime => '2147483647'],
254						    add => [sambaPwdCanChange => '0'],
255						    add => [sambaPwdMustChange => '2147483647'],
256						    add => [sambaPwdLastSet => "$date"],
257						    add => [sambaAcctFlags => '[I          ]'],
258						    add => [sambaLMPassword => "$lmpassword"],
259						    add => [sambaNTPassword => "$ntpassword"],
260						    add => [sambaSID => "$user_sid"],
261						    add => [sambaPrimaryGroupSID => "$config{SID}-515"]
262						   ]
263				      );
264
265    $modify->code && die "failed to add entry: ", $modify->error ;
266  }
267
268  $ldap_master->unbind;
269  exit 0;
270}
271
272# USER ACCOUNT
273# add posix account first
274
275my $add = $ldap_master->add ("uid=$userName,$config{usersdn}",
276			     attr => [
277				      'objectclass' => ['top','inetOrgPerson','posixAccount','shadowAccount'],
278				      'cn'   => "$userCN",
279				      'sn'   => "$userSN",
280				      'uid'   => "$userName",
281				      'uidNumber'   => "$userUidNumber",
282				      'gidNumber'   => "$userGidNumber",
283				      'homeDirectory'   => "$userHomeDirectory",
284				      'loginShell'   => "$config{userLoginShell}",
285				      'gecos'   => "$config{userGecos}",
286				      'description'   => "$config{userGecos}",
287				      'userPassword'   => "{crypt}x"
288				     ]
289			    );
290
291$add->code && warn "failed to add entry: ", $add->error ;
292
293
294#if ($createGroup) {
295#    group_add($userName, $userGidNumber);
296#}
297
298group_add_user($userGidNumber, $userName);
299
300my $grouplist;
301# adds to supplementary groups
302if (defined($grouplist = $Options{'G'})) {
303  add_grouplist_user($grouplist, $userName);
304}
305
306# If user was created successfully then we should create his/her home dir
307if (defined($tmp = $Options{'m'})) {
308  unless ( $userName =~ /\$$/ ) {
309    if ( !(-e $userHomeDirectory) ) {
310      system "mkdir $userHomeDirectory 2>/dev/null";
311      system "cp -a $config{skeletonDir}/.[a-z,A-Z]* $config{skeletonDir}/* $userHomeDirectory 2>/dev/null";
312      system "chown -R $userUidNumber:$userGidNumber $userHomeDirectory 2>/dev/null";
313      system "chmod 700 $userHomeDirectory 2>/dev/null"; 
314    }
315  }
316}
317
318# we start to defined mail adresses if option M or T is given in option
319my @adds;
320if (@userMailLocal) {
321  my @mail;
322  foreach my $m (@userMailLocal) {
323    my $domain = $config{mailDomain};
324    if ($m =~ /^(.+)@/) {
325      push (@mail, $m);
326      # mailLocalAddress contains only the first part
327      $m= $1;
328    } else {
329      push(@mail, $m.($domain ? '@'.$domain : ''));
330    }
331  }
332  push(@adds, 'mailLocalAddress' => [ @userMailLocal ]);
333  push(@adds, 'mail' => [ @mail ]);
334}
335if (@userMailTo) {
336  push(@adds, 'mailRoutingAddress' => [ @userMailTo ]);
337}
338if (@userMailLocal || @userMailTo) {
339  push(@adds, 'objectClass' => 'inetLocalMailRecipient');
340}
341
342# Add Samba user infos
343if (defined($Options{'a'})) {
344  if (!$config{with_smbpasswd}) {
345
346    my $winmagic = 2147483647;
347    my $valpwdcanchange = 0;
348    my $valpwdmustchange = $winmagic;
349    my $valpwdlastset = 0;
350    my $valacctflags = "[UX]";
351
352    if (defined($tmp = $Options{'A'})) {
353      if ($tmp != 0) {
354	$valpwdcanchange = "0";
355      } else {
356	$valpwdcanchange = "$winmagic";
357      }
358    }
359
360    if (defined($tmp = $Options{'B'})) {
361      if ($tmp != 0) {
362	$valpwdmustchange = "0";
363	# To force a user to change his password:
364	# . the attribut sambaPwdLastSet must be != 0
365	# . the attribut sambaAcctFlags must not match the 'X' flag
366	$valpwdlastset=$winmagic;
367	$valacctflags = "[U]";
368      } else {
369	$valpwdmustchange = "$winmagic";
370      }
371    }
372
373    if (defined($tmp = $Options{'H'})) {
374      $valacctflags = "$tmp";
375    }
376
377
378    my $modify = $ldap_master->modify ( "uid=$userName,$config{usersdn}",
379					changes => [
380						    add => [objectClass => 'sambaSAMAccount'],
381						    add => [sambaPwdLastSet => "$valpwdlastset"],
382						    add => [sambaLogonTime => '0'],
383						    add => [sambaLogoffTime => '2147483647'],
384						    add => [sambaKickoffTime => '2147483647'],
385						    add => [sambaPwdCanChange => "$valpwdcanchange"],
386						    add => [sambaPwdMustChange => "$valpwdmustchange"],
387						    add => [displayName => "$config{userGecos}"],
388						    add => [sambaAcctFlags => "$valacctflags"],
389						    add => [sambaSID => "$config{SID}-$userRid"]
390						   ]
391				      );
392	
393    $modify->code && die "failed to add entry: ", $modify->error ;
394
395  } else {
396    my $FILE="|smbpasswd -s -a $userName >/dev/null" ;
397    open (FILE, $FILE) || die "$!\n";
398    print FILE <<EOF;
399x
400x
401EOF
402    ;
403    close FILE;
404    if ($?) {
405      print "$0: error adding samba account\n";
406      exit (10);
407    }
408  }				# with_smbpasswd
409
410  $tmp = defined($Options{'E'}) ? $Options{'E'} : $config{userScript};
411  my $valscriptpath = &subst_user($tmp, $userName);
412
413  $tmp = defined($Options{'C'}) ? $Options{'C'} : $config{userSmbHome};
414  my $valsmbhome = &subst_user($tmp, $userName);
415
416  my $valhomedrive = defined($Options{'D'}) ? $Options{'D'} : $config{userHomeDrive};
417  # if the letter is given without the ":" symbol, we add it
418  $valhomedrive .= ':' if ($valhomedrive && $valhomedrive !~ /:$/);
419
420  $tmp = defined($Options{'F'}) ? $Options{'F'} : $config{userProfile};
421  my $valprofilepath = &subst_user($tmp, $userName);
422
423  if ($valhomedrive) {
424    push(@adds, 'sambaHomeDrive' => $valhomedrive);
425  }
426  if ($valsmbhome) {
427    push(@adds, 'sambaHomePath' => $valsmbhome);
428  }
429
430  if ($valprofilepath) {
431    push(@adds, 'sambaProfilePath' => $valprofilepath);
432  }
433  if ($valscriptpath) {
434    push(@adds, 'sambaLogonScript' => $valscriptpath);
435  }
436  push(@adds, 'sambaPrimaryGroupSID' => $userGroupSID);
437  push(@adds, 'sambaLMPassword' => "XXX");
438  push(@adds, 'sambaNTPassword' => "XXX");
439  my $modify = $ldap_master->modify ( "uid=$userName,$config{usersdn}",
440				    add => {
441					    @adds
442					   }
443				  );
444
445  $modify->code && die "failed to add entry: ", $modify->error ;
446}
447
448$ldap_master->unbind;		# take down session
449
450
451if (defined($Options{'P'})) {
452  exec "$RealBin/smbldap-passwd $userName"
453}
454
455exit 0;
456
457########################################
458
459=head1 NAME
460
461smbldap-useradd - Create a new user
462
463=head1 SYNOPSIS
464
465smbldap-useradd [-o user_ou] [-c comment] [-d home_dir] [-g initial_group] [-G group[,...]] [-m [-k skeleton_dir]] [-s shell] [-u uid [ -o]] [-P] [-A canchange] [-B mustchange] [-C smbhome] [-D homedrive] [-E scriptpath] [-F profilepath] [-H acctflags] login
466
467=head1 DESCRIPTION
468
469Creating New Users
470  The smbldap-useradd command creates a new user account using  the values specified on the  command  line  and  the default  values from the system and from the configuration files (in  /etc/smbldap-tools directory).
471
472For Samba users, rid is '2*uidNumber+1000', and sambaPrimaryGroupSID  is '$SID-2*gidNumber+1001', where $SID is the domain SID.  Thus you may want to use :
473  $ smbldap-useradd -a -g "Domain Admins" -u 500 Administrator
474 to create an domain administrator account (admin rid is 0x1F4 = 500 and grouprid is 0x200 = 512).
475
476Without any option, the account created will be an Unix (Posix)  account. The following options may be used to add information:
477
478-o
479The user's account will be created in the specified organazional unit. It is relative to the user suffix dn ($usersdn) defined in the configuration file.
480
481-a
482The user will have a Samba account (and Unix).
483
484-w
485 Creates an account for a Samba machine (Workstation), so that it can join a sambaDomainName.
486
487-i
488 Creates an interdomain trust account (machine Workstation). A password will be asked for the trust account.
489
490-c "comment"
491 The new user's comment field (gecos).
492
493-d home_dir
494 The new user will be created using home_dir as the value for the user's login directory.  The default is to append the login name      to userHomePrefix (defined in the configuration file) and use that      as the login directory name.
495
496-g initial_group
497  The group name or number of the user's initial login group. The  group  name must exist.  A group number must refer to an already  existing group.  The default group number is defined in the  configuration file (defaultUserGid="513").
498
499-G group,[...]
500 A list of supplementary groups which the user is also  a  member of. Each  group is separated to the next by a comma, with no intervening whitespace.  The groups  are  subject  to  the  same restrictions as the group given with the -g option.  The default is for the user to belong only to the initial group.
501
502-m
503The user's home directory will be created if it does not  exist. The  files  contained in skeletonDir will be copied to the home directory if the -k option is used,  otherwise  the  files  contained  in /etc/skel will be used instead.  Any directories contained in skeletonDir or  /etc/skel  will  be  created  in  the user's  home  directory as well.  The -k option is only valid in conjunction with the -m option.  The default is  to  not  create the directory and to not copy any files.
504
505-s shell
506 The name of the user's login shell.  The  default  is  to  leave this  field blank, which causes the system to select the default login shell.
507
508-u uid
509  The numerical value of  the  user's  ID.   This  value  must  be unique,  unless  the  -o option is used.  The value must be nonnegative.  The default is to use the smallest ID  value  greater than 1000 and greater than every other user.
510
511-P
512 ends by invoking smbldap-passwd
513
514-A
515 can change password ? 0 if no, 1 if yes
516
517-B
518 must change password ? 0 if no, 1 if yes
519
520-C sambaHomePath
521 SMB home share, like '\\\\PDC-SRV\\homes'
522
523-D sambaHomeDrive
524 letter associated with home share, like 'H:'
525
526-E sambaLogonScript
527 relative to the [netlogon] share (DOS script to execute on login, like 'foo.bat'
528
529-F sambaProfilePath
530 profile directory, like '\\\\PDC-SRV\\profiles\\foo'
531
532-H  sambaAcctFlags
533  spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]'
534
535-M  local mail aliases (multiple addresses are seperated by spaces)
536
537-N  canonical name
538 defaults to gecos or username, if gecos not set
539
540-S  surname
541 defaults to username
542
543-T  mailToAddress (forward address) (multiple addresses are seperated by spaces)
544
545-n  do not print banner message
546
547=head1 SEE ALSO
548
549       useradd(1)
550
551=cut
552
553#'
554