3dbc has asked for the wisdom of the Perl Monks concerning the following question:


So what I would like to modify on this win32 script is the   -USER LOGON NAME for the Account entry in the Active Directory.

The Script currently updates the   -USER LOGON NAME (pre-Windows 2000) field.   It leaves the USER LOGON NAME field empty for any users inserted with this script.   I also would like to populate the first name and last name fields however; currently the script only modifies the full name field.

Furthermore when using Win32::Lanman::NetUserAdd( "itstw2k1", \%Account ); it adds the users to the users directory within the active directory - I would like to add users to specific OU's (organizational units) that we have created within the Active Directory. Actually these OU's are often nested within other OU's enabling strict usage of Group policy which is slightly off topic.

Thanks Monks, your advice is quintessential for an evolving PERL hacker.

my $dbh1 = DBI->connect("DBI:CSV:") or die "Cannot connect: " . $DBI::errstr; $dbh1->{'csv_tables'}->{'stokes_studs'} = { 'file' => 'stokes_studs.cs +v'}; my $href = $dbh1->selectall_hashref("SELECT * FROM stokes_studs", "key +"); $num_records = keys %{$href}; print "$num_records\n"; foreach (keys %{$href}) { $href->{$_}{id} = sprintf ("%00005d",$href->{$_}{id}); #print "$href->{$_}{last_name} = $href->{$_}{id}\n"; &addUser($href->{$_}{last_name}, #$href->{$_}{first_name}, $href-> +{$_}{id}, $href->{$_}{dob}, $href->{$_}{year}); } sub makeHomefolder { #create the user directory and set the security on it my($id,$homeServer,$domain,$pdc) = @_; if ($pdc eq ''){$domain = '';} #if ($id =~ /\w/) { $id =~ s/\(\w+\)//g; $id =~ s/ / /g; $id =~ s/ /_/g; $id = sprintf ("%.20s",$id); #} $userRoot = "$homeServer\\$id"; print "Creating Users Home Folder $userRoot\n"; system ("mkdir $userRoot"); } sub addUser { my($lastname,$firstname,$id,$bday,$comment) = @_; my ($passwordAge, $privilege, $login_name, $homeDir, $fullname, $flags, $scriptPath); $login_name = "$firstname $lastname $bday"; $login_name = sprintf "%.1s%.1s%02d%02d", lcfirst $firstname, lcfi +rst $lastname, split /\//, $bday; #chop $login_name; #chop $login_name; print "login_name = $login_name"; $fullName = "$firstname $lastname"; $domain = "itelem1"; $homeServer = "E:\\Stokes_students\\$comment"; $pdc = Win32::AdminMisc::GetPDC($domain); $passwordAge = 1; #never expire $privilege = USER_PRIV_USER; $homeDir = ""; $flags = UF_NORMAL_ACCOUNT | UF_SCRIPT; $scriptPath = 'login.bat'; $location = ''; %Account = ( name => "$login_name", password => "$id", home_dir => "\\\\maxst2\\$login_name", comment => "$comment", usr_comment => "usr_comment", flags => UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE, params => '', script_path => 'login.bat', full_name => "$fullName", workstations => "", profile => "\\\\maxst2\\$login_name", acct_expires => -1, #logon_hours => pack( "b168", "11111111" x 21 ), home_dir_drive => "H:", password_expired => 1, ); if (Win32::NetAdmin::UsersExist("itstw2k1", $login_name)) { #### C +RT print "duplicate username found = $login_name"; } else { print "\nadding user $login_name\n"; print "firstname = $firstname\n"; print "lastname = $lastname\n"; Win32::Lanman::NetUserAdd( "itstw2k1", \%Account ); makeHomefolder($fullName,$homeServer,$domain,$pdc); makePermissions($login_name,$fullName,$comment); #system "cusrmgr -u $login_name -f $fullName"; #die; } } sub makePermissions { my($username,$full_name,$description) = @_; $stop=1; $full_name =~ s/\(\w+\)//g; $full_name =~ s/ / /g; $full_name =~ s/ /_/g; $full_name = sprintf ("%.20s",$full_name); #opendir DIR, "E:\\Stokes_students\\$description\\$full_name" or & +ERROR(); sub ERROR { $stop=0; } print "\nuserRoot = $userRoot\n"; if($stop==1) { #closedir DIR; print "\nModifying Security on Users Home Folder\n"; print "\nusername = $username\n"; $Dir = new Win32::Perms( "$userRoot") || die; $Dir->Remove(-1); $Dir->Allow(Administrators,Win32::Perms::FULL_CONTROL_DIR,Win3 +2::Perms::DIR); $Dir->Allow(Administrators,Win32::Perms::FULL_CONTROL_FILE,Win +32::Perms::FILE); $Dir->Set(); $Dir->Allow("$username",Win32::Perms::FULL_CONTROL_DIR,Win32:: +Perms::DIR); $Dir->Allow("$username",Win32::Perms::FULL_CONTROL_FILE,Win32: +:Perms::FILE); $Dir->Set(); $Dir->Allow(System,Win32::Perms::FULL_CONTROL_DIR,Win32::Perms +::DIR); $Dir->Allow(System,Win32::Perms::FULL_CONTROL_FILE,Win32::Perm +s::FILE); $Dir->Set(); print "\n\nCreating Share on user's Home Directory\n"; print "$username\n"; print "$full_name\n"; print "$description\n\n"; if(!Win32::Lanman::NetShareAdd("\\\\MAXST2", {'netname' => "$username", # share name type => Win32::Lanman::STYPE_ +DISKTREE, # share type remark => 'user share', # remark permissions => Win32::Lanman: +:ACCESS_ALL, # only used for share level security max_uses => 3, # number of users can connect current_uses => 0, # unused path => "$userRoot", # physical share path passwd => 'password', # password #security_descriptor => $secd +esc })) # sec. descriptor if you need security { print "Sorry, something went wrong; error: "; # get the error code print Win32::Lanman::GetLastError(); exit 1; } print "\nModifying Security on User Share\n"; $path = "\\\\MAXST2\\$username"; $Dir = new Win32::Perms("share:".$path ) || warn "Can not create perm for $path \n"; $Dir->Remove(-1); $Dir->Allow(Administrators,Win32::Perms::FULL_CONTROL_DIR,Win3 +2::Perms::DIR); $Dir->Allow(Administrators,Win32::Perms::FULL_CONTROL_FILE,Win +32::Perms::FILE); $Dir->Set(); $Dir->Allow("$username",Win32::Perms::FULL_CONTROL_DIR,Win32:: +Perms::DIR); $Dir->Allow("$username",Win32::Perms::FULL_CONTROL_FILE,Win32: +:Perms::FILE); $Dir->Set(); $Dir->Allow(System,Win32::Perms::FULL_CONTROL_DIR,Win32::Perms +::DIR); $Dir->Allow(System,Win32::Perms::FULL_CONTROL_FILE,Win32::Perm +s::FILE); $Dir->Set(); } }

janitored by ybiC: Balanced <readmore> tags around code as per Monastery convention, minor format cleanup for legibility

Replies are listed 'Best First'.
Re: Win32::Lanman::NetUserAdd
by SquireJames (Monk) on Dec 11, 2003 at 01:24 UTC
    You really can't do much with Win32::Lanman and AD, as you are only really using NT funtion to achieve what you want, so there's no control over anything purely Win2K/AD related. You really need to use Win32::OLE to do what you're trying to. Here are a couple of user modification sibroutintes that I use;
    sub ad_modify { # To change a single value in AD use Win32::OLE; my $dn = $_[0]; # The object DN my $attrib = $_[1]; # The attribute to change my $value = $_[2]; # The attributes new value my ($object); $object = Win32::OLE->GetObject("$dn"); $object->{$attrib} = "$value"; $object->SetInfo; # Don't forget to set the values } sub ad_get_attrib { # For returning Attribute Values.... use Win32::OLE; my $dn = $_[0]; # The object DN my $attrib = $_[1]; # The attribute in question my ($object,$result); $object = Win32::OLE->GetObject("$dn"); if ($object->{$attrib}) { # If this Attribute actually exists.... $result = $object->Get("$attrib"); } return $result; } sub ad_search { # To search AD and return a pre-determined value use Win32::OLE; my $search_base = $_[0]; # This is the base for our searches my $filter = $_[1]; # This is the valid LDAP filter that we will be ap +plying my $attribute = $_[2]; # This is the attribute that we will be returni +ng my $search_scope = $_[3]; # This is the scope for our search to follow my ($conn, $res, @result, $succ_search); # Variables that we are using + as we go $conn = Win32::OLE->new('ADODB.Connection'); # New connection $conn->{Provider} = "ADsDSOObject"; # OLE provider $conn->Open; $res = $conn->Execute($search_base . $filter . $attribute . $search_sc +ope); # This is our search if ($res->EOF) { # If we have found 0 records that match our search $succ_search = 0; # Set our no records found item and return it } else { $succ_search = 1; # So our records found item $res->MoveFirst; # Go to the first record while (not $res->EOF) { # Whie we still have records push (@result, $res->Fields(0)->Value); # Push them to our arr +ay $res->MoveNext; # Go to the next one } } return ($succ_search, @result); # Return our success and our array of +results }
    You could use a mix of Win32::OLE and Win32::Lanman::NewUser to achieve that you want (Win32::OLE will also allow you to move objects to new containers), but I'd suggest doing a bit of research and using Win32::OLE to do the whole lot.