#!/usr/bin/perl -w # # $Id: useradmin.pl,v 1.2 2006/06/01 04:26:12 jmates Exp $ # # Copyright (c) 2005, Alex Dioso. # All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ##################################################################### # # Manage users on windows # For Unix compatiblity, changes the CRLF during print to LF binmode STDOUT; use strict; use Win32; use Win32API::Net qw(:User :LocalGroup); use Getopt::Long; use constant OK => 0; use constant MISSING_USERNAME => 1; use constant TOO_MANY_USERNAMES => 2; use constant FAILED_USERADD => 3; use constant CONFLICTING_OPTIONS => 4; use constant FAILED_USERSETGROUPS => 5; use constant FAILED_USERDEL => 6; use constant FAILED_USERGETINFO => 7; use constant FAILED_USERENUM => 8; use constant MISSING_OPTIONS => 9; use constant USER_ALREADY_EXISTS => 10; use constant GROUP_DOESNT_EXIST => 11; use constant USER_DOESNT_EXIST => 12; if ( @ARGV == 0 ) { exit list_users(); } my %opts; GetOptions( \%opts, "a", "d", "c=s", "i" ); if ( exists $opts{'a'} and exists $opts{'d'} ) { usage(); exit CONFLICTING_OPTIONS; } unless ( exists $opts{'a'} or exists $opts{'d'} or exists $opts{'i'} ) { usage(); exit MISSING_OPTIONS; } if ( @ARGV == 0 ) { usage(); exit MISSING_USERNAME; } if ( @ARGV > 1 ) { usage(); exit TOO_MANY_USERNAMES; } $opts{'username'} = $ARGV[0]; if ( exists $opts{'a'} ) { exit add_user( \%opts ); } elsif ( exists $opts{'d'} ) { my %temp; unless ( UserGetInfo( "", $opts{'username'}, 0, \%temp ) ) { print STDERR "User $opts{'username'} doesn't exist.\n"; exit USER_DOESNT_EXIST; } unless ( UserDel( "", $opts{'username'} ) ) { print STDERR "UserDel() failed: " . Win32::GetLastError() . "\n"; exit FAILED_USERDEL; } } elsif ( exists $opts{'i'} ) { my %temp; unless ( UserGetInfo( "", $opts{'username'}, 2, \%temp ) ) { print STDERR "UserGetInfo() failed: " . Win32::GetLastError() . "\n"; exit FAILED_USERGETINFO; } foreach ( keys %temp ) { print "$_: $temp{$_}\n"; } exit OK; } exit OK; # Returns error code sub list_users { my @users; unless ( UserEnum( "", \@users ) ) { print STDERR "UserEnum() failed: " . Win32::GetLastError() . "\n"; return FAILED_USERENUM; } foreach (@users) { my %user_data; unless ( UserGetInfo( "", $_, 2, \%user_data ) ) { print STDERR "UserGetInfo() failed: " . Win32::GetLastError() . "\n"; return FAILED_USERGETINFO; } print "$_:x:::$user_data{'fullName'}::/bin/true\n"; } return OK; } # Returns error code sub add_user { my @s; my $fullname = ""; my $password = ""; my $error = ""; my $user_info = shift; my %temp; my @users = $user_info->{'username'}; my @logon_hours = ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); if ( UserGetInfo( "", $user_info->{'username'}, 0, \%temp ) ) { print STDERR "User $user_info->{'username'} already exists.\n"; return USER_ALREADY_EXISTS; } unless ( LocalGroupGetInfo( "", "Users", 1, \%temp ) ) { print STDERR "Group Users doesn't exist.\n"; return GROUP_DOESNT_EXIST; } if ( exists $user_info->{'c'} ) { $fullname = $user_info->{'c'}; } @s = grep { /[[:print:]]/ and /[^\s]/ } map { chr } 1 .. 128; for ( 1 .. ( int( rand 9 ) + 15 ) ) { $password .= $s[ rand @s ]; } my %user_data = ( 'name' => $user_info->{'username'}, 'password' => $password, 'passwordAge' => 0, 'priv' => USER_PRIV_USER, 'homeDir' => "", 'comment' => "", 'flags' => ( UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE | UF_SCRIPT ), 'scriptPath' => "", 'authFlags' => 0, 'fullName' => $fullname, 'usrComment' => "", 'parms' => "", 'workstations' => "", 'lastLogon' => 0, 'lastLogoff' => 0, 'acctExpires' => -1, 'maxStorage' => -1, 'unitsPerWeek' => 168, 'logonHours' => \@logon_hours, 'badPwCount' => 0, 'numLogons' => 0, 'logonServer' => "", 'countryCode' => 0, 'codePage' => 0 ); unless ( UserAdd( '', 2, \%user_data, \$error ) ) { print STDERR "UserAdd() failed: " . Win32::GetLastError() . "\n"; return FAILED_USERADD; } unless ( LocalGroupAddMembers( "", "Users", \@users ) ) { print STDERR "UserSetGroups() failed: " . Win32::GetLastError() . "\n"; return FAILED_USERSETGROUPS; } return OK; } sub usage { print "\nusage: $0 [(-a|-d) [-c \"REAL NAME\"] USER_NAME]\n"; }