Page 1 of 1 1
Topic Options
#191051 - 2008-12-12 06:41 AM bunch of Local User Managment functions
lukeod Offline
Getting the hang of it

Registered: 2008-01-11
Posts: 70
Loc: Australia
Hey All,

I was hard pressed to find how to perform local user managment via Kix. There are examples on how to do some of it remotley as well as for Active Directory but tracking down ones that can be run against the local machine's users was harder to find. I'm suprised there isnt already UDF's for much of the below.

These scripts can be used during shutdown or startup, thereby negating the need for administrative priviliges as well as issues around the scripts containing plain text passwords.

Most of the below code is recycled code from many sources. Appologies for lack of acknowlegment to the original coders.

They could use work along the lines of error handling.

 Code:
Function ModifyPassword($strUserName, $strPassword)
	;DESCRIPTION: Modify the password of a user account
		
	;Declate Variables
	Dim $objUser
		
	;Create Object
	$objUser = GetObject("WinNT://" + @WKSTA + "/" + $strUserName + "") 
		
	;Set the Password
	$objUser.SetPassword($strPassword)
		
	;If it failed, return an error
	$ModifyPassword =  IIf(@ERROR, 'Failed ' + @SERROR , 'Successful') + '  '
EndFunction 


 Code:
 Function GetLocalUsers()
	;DESCRIPTION :  Returns an array containing all local user accounts
		
	;Declare Variables
	Dim $strHost, $String
		
	;Initilise Variables
	$strHost = @WKSTA
	$String = ""
		
	;Get a ';' delimited string containing all the local user accounts
	For Each $Object in GetObject("WinNT://" + $strHost) 
		If $Object.Class = "User"
			$String = $String + $Object.name + ";"
		EndIf
	Next
		
	;Check if the string is empty, if not, create an array
	If Len($String) = 0
		;No Members in the Group
		$GetLocalUsers = "ERROR!!! " + @SERROR
		Exit 2
	Else
		;Create an array from the string
		$GetLocalUsers = Split($String, ";")
	EndIf
EndFunction


 Code:
 Function GetLocalGroupMembers($strGroupName)
	;DESCRIPTION : Returns an array containing the members of the group passed to the Function
		
	;Declare Variables
	Dim $strHost, $String, $Object
	
	;Initilise Variables
	$strHost = @WKSTA
	$String = ""
		
	For Each $Object in GetObject("WinNT://" + $strHost) 
		If $Object.Class = "Group"
			If $Object.Name = $strGroupName
				For Each $Member in $Object.members 
					$String = $String + $Member.name + ";"
				Next 
			EndIf
		EndIf
	Next
	If Len($String) = 0
		;No Members in the Group
		@SERROR = "No members in the Group Specified (" + $strGroupName + ")"
		$GetLocalGroupMembers = "No members in the Group Specified (" + $GroupName + ")"
		Exit 2
	Else
		$GetLocalGroupMembers = Split($String, ";")
	EndIf
EndFunction



 Code:
 
Function AddLocalAdmin($strUserAccount)
	;DESCRIPTION: Attempts to add the account to the local administrators group
	
	Dim $strComputer, $objComputer, $objUser, $objGroup
	$strComputer = @WKSTA
	
	;Create Objects
	$objGroup = GetObject("WinNT://" + $strComputer + "/Administrators,group")	
	$objUser = GetObject("WinNT://" + $strComputer + "/" + $strUserAccount + ",user")
		
	;Create the User Account
	$objGroup.Add($objUser.ADsPath)
EndFunction


 Code:
Function CreateLocalUser($strName, $strPassword, $Description)
	;DESCRIPTION : Attempts to create a local user account
	
	Dim $strComputer, $objComputer, $objUser  
	;Set Variables
	$strComputer = @WKSTA
	;Create Object
	$objComputer = GetObject("WinNT://" + $strComputer)
	;Create object of class user on the computer.  
	$objUser = $objComputer.Create("user", $strName)  
	$objUser.Put("description", $Description)
	;Save changes.  
	$objUser.SetInfo
	;set password.  
	$objUser.SetPassword($strPassword)
	$objUser.SetInfo  
EndFunction 


 Code:
Function SetNeverExpire($strUserAccount)
	;DESCRIPTION: Sets the account's password to never expire
	;Original code by  Chris S, just function'ised it (that even a word? :P)

	;Variables
	Dim $ADS_UF_DONT_EXPIRE_PASSWD, $strComputer, $objUser 
	$ADS_UF_DONT_EXPIRE_PASSWD = &10000
	$strComputer = @WKSTA
	
	;Create Objects
	$objUser = GetObject("WinNT://" + $strComputer + "/" + $strUserAccount + ",user")			
	$objUserFlags = $objUser.Get("UserFlags")
	
	If ($objUserFlags & $ADS_UF_DONT_EXPIRE_PASSWD) = 0
		$objPasswordExpirationFlag = $objUserFlags + $ADS_UF_DONT_EXPIRE_PASSWD
		$objUser.Put("userFlags", $objPasswordExpirationFlag)
		$objUser.SetInfo
		@SERROR ?
	Else
		"Account already has the Password Never Expires Flag." ?
	EndIf	
EndFunction 




Edited by lukeod (2008-12-12 06:50 AM)

Top
#191065 - 2008-12-12 04:03 PM Re: bunch of Local User Managment functions [Re: lukeod]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
Two quick comments regarding cleanup..

1 - You can't set the @ERROR or @SERROR macros.. they are read only.
2 - Most UDFs should be silent. If you want to return status, you should return a code or string in the function's private variable (ie: $FuncName)

As for standards, make sure all vars are declared to avoid "accidental globals" from messing with your code. For public functions, I like to declare each var on its own line and add a short comment to define what the var (or set of vars) is used for.

Since these functions are inter-related, you could create a function library with a single standard header, and separate syntax statements for each function.

Also, for enhanced flexibility, I'd consider passing the group name as an additional arg, and changing AddLocalAdmin(AccountID) to JoinLocalGroup(AccountID, GroupID).

Needs just a bit of polish, but there's a gem of a library waiting to come out of this!

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#191072 - 2008-12-12 08:19 PM Re: bunch of Local User Managment functions [Re: Glenn Barnas]
NTDOC Administrator Offline
Administrator
*****

Registered: 2000-07-28
Posts: 11634
Loc: CA
And just how does a Startup script hide a password change? A user with knowledge can come along and look where it comes from and what was passed to it, not very secure. Though I'm sure you understand, but for others that come along and read this you would want to have other code that prevents most of these routines from running every time the computer starts.
Top
#191172 - 2008-12-15 01:06 AM Re: bunch of Local User Managment functions [Re: NTDOC]
lukeod Offline
Getting the hang of it

Registered: 2008-01-11
Posts: 70
Loc: Australia
A startup script gets run (from a Domain Controllers point of view) using the 'Domain Computers' Security Group. You can then put the script on a share / a folder and lock it down using NTFS so only domain computers have read only access to this share/folder. Then, if a user knew the path to the script (not hard to get via RSOP.msc) they wouldnt have NTFS permssions to view anything in the folder.

Edited by lukeod (2008-12-15 01:07 AM)

Top
#191173 - 2008-12-15 01:09 AM Re: bunch of Local User Managment functions [Re: Glenn Barnas]
lukeod Offline
Getting the hang of it

Registered: 2008-01-11
Posts: 70
Loc: Australia
Ahh okay thanks Glenn. I'm pretty sure you have to set the @ERROR using 'EXIT x', how do you set the @SERROR? i'll have to wander through the documentation.
Top
#191174 - 2008-12-15 01:11 AM Re: bunch of Local User Managment functions [Re: Glenn Barnas]
lukeod Offline
Getting the hang of it

Registered: 2008-01-11
Posts: 70
Loc: Australia
 Originally Posted By: Glenn Barnas

Also, for enhanced flexibility, I'd consider passing the group name as an additional arg, and changing AddLocalAdmin(AccountID) to JoinLocalGroup(AccountID, GroupID).

Glenn


I was thinking someone would mention somthing along those lines :P. If i get some time i'll have to try and implement all you mentioned, could be a good kix-learning experience \:\)

Cheers

Top
#191175 - 2008-12-15 02:43 AM Re: bunch of Local User Managment functions [Re: lukeod]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
If you use a function with just an "Exit 0" in it to clear the @ERROR, the @SERROR is reset automatically to "The command completed successfully". You can't "clear" it but you can reset both values to a success.

It's rarely (if ever) needed, as just about every function sets the exit status and the corresponding error macros. UDFs without explicit exit values (generally a bad practice) will default to success values.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#191176 - 2008-12-15 04:02 AM Re: bunch of Local User Managment functions [Re: Glenn Barnas]
lukeod Offline
Getting the hang of it

Registered: 2008-01-11
Posts: 70
Loc: Australia
They could probably still use more error catching - for example to return a different error code depending on the particular error (for the more common errors), but i've made some improvements (i think)

 Code:
;Function:
; fnModifyPassword()
;Action:
; Sets the password for the specified user
;Syntax:
; fnModifyPassword(USERNAME, PASSWORD)
;
;Parameters:
; USERNAME : Required Parameter. The Name of the local User you wish to change the password for.
; PASSWORD : Required Parameter. The Password you wish to change to.
;Returns:
; 0 for successful, 1 for failed
;Example:
; $ = fnModifyPassword('testuser','123password456')
; If $ = 0
;    'Successful' ?
; Else
;	  'Failed' ?
; EndIf
Function fnModifyPassword($strUserName, $strPassword)

	Dim $objUser 	;ADSI object for the specified user
			
	;Create Object
	$objUser = GetObject('WinNT://' + @WKSTA + '/' + $strUserName + '') 
			
	;Set the Password
	$objUser.SetPassword($strPassword)
			
	;If it failed, return an error
	If @ERROR
		$ModifyPassword = 1
		Exit 1
	Else
		$fnModifyPassword = 0
		Exit 0
	EndIf
EndFunction  



 Code:
 ;Function:
; fnGetLocalUsers()
;Action:
; Returns an array containing the username of local user accounts
;Syntax:
; fnGetLocalUsers()
;Returns:
; (If successful) - An array containing the username of local user accounts
; (If failed) 		- An empty array (Ubound = -1)
;Example:
;	$arrLocalUsers = fnGetLocalUsers()
;	For Each $User in $arrLocalUsers
;		'User >' + $User ?
;	Next

Function fnGetLocalUsers()
	;Declare Variables
	Dim $arrUsers[] ;Array containing local users
	Dim $intCounter ;Counter
			
	;Initilise Variables
		
	$intCounter = 0
		
	;Get a ';' delimited string containing all the local user accounts
	For Each $Object in GetObject('WinNT://' + @WKSTA) 
		If $Object.Class = 'User'
			ReDim Preserve $arrUsers[$intCounter]
			$arrUsers[$intCounter] = $Object.name
			$intCounter = $intCounter + 1
		EndIf
	Next
				
	;Check if the Array is empty. If it is, return an error
	If UBound($arrUsers) = -1 ;An Empty Array
		$fnGetLocalUsers = $arrUsers
		Exit 1
	Else 	;Array contains at least one element
		;Set the exit variable to contain the users as an array
		$fnGetLocalUsers = $arrUsers
		Exit 0
	EndIf
EndFunction


 Code:
;Function:
; fnGetLocalGroupMembers()
;Action:
; Returns an Array containing the usernames of members of the specified group
;Syntax:
; fnGetLocalUsers(GroupName)
;Parameters:
; GroupName: Required Parameter. The Name of the local Group you wish to find the members of.
;Returns:
; (If successful) - An array containing the usernames of the members of the specified group.
; (If failed - or no members)	- An empty array (Ubound = -1)
;Example:
;	$arrGroupMembers = fnGetLocalGroupMembers('Administrators')
;	For Each $User in $arrGroupMembers
;		'Member' + $User ?
;	Next

Function fnGetLocalGroupMembers($strGroupName)
	;DESCRIPTION : Returns an array containing the members of the group passed to the Function
			
	;Declare Variables
	Dim $arrUsers[] ;Array containing users which are a member of the specified group
	Dim $intCounter ;Counter
	Dim $objObject  ;Contains adsi objects of various classes (users, groups etc)		
		
	;Initilise Variables
	
	$intCounter = 0
		
	;Determine the users in the group
	For Each $objObject in GetObject('WinNT://' + @WKSTA) 
		If $objObject.Class = 'Group'
			If $objObject.Name = $strGroupName
				For Each $Member in $objObject.members 
					ReDim Preserve $arrUsers[$intCounter]
					$arrUsers[$intCounter] = $Member.name
					$intCounter = $intCounter + 1
				Next 
			EndIf
		EndIf
	Next
	If UBound($arrUsers) = -1
		;No Members in the Group
		$fnGetLocalGroupMembers = $arrUsers
		Exit 1
	Else
		;Members in the Group
		$fnGetLocalGroupMembers = $arrUsers
		Exit 0
	EndIf
EndFunction 


 Code:
 ;Function:
; fnAddLocalGroupMember()
;Action:
; Adds the specified user to the group specified
;Syntax:
; fnAddLocalGroupMember(GROUP, USER)
;Parameters:
; GROUP: Required Parameter. The Name of the local Group you wish to add a user to.
; USER:  Required Parameter. The Name of the local User you wish to add to the Group.
;Example:
;	fnAddLocalGroupMember('Administrators', 'TestUser')

		
		Function fnAddLocalGroupMember($strGroup, $strUser)
					
			Dim $strComputer  ;String containing the name of the machine the script is being run on
			Dim $objGroup 		;Object containing the Group specified
			Dim $objUser  		;Object containing the User specified
				
			;Initilise Variables
			$strComputer = @WKSTA
					
			;Create Objects
			$objGroup = GetObject('WinNT://' + $strComputer + '/' + $strGroup + ',group')	
			$objUser = GetObject('WinNT://' + $strComputer + '/' + $strUser + ',user')
						
			;Create the User Account
			$objGroup.Add($objUser.ADsPath)
				
			If @ERROR Exit 1 EndIf
EndFunction


 Code:
 ;Function:
; fnCreateLocalUser()
;Action:
; Creates a local User account
;Syntax:
; fnCreateLocalUser(USERNAME, PASSWORD, DESCRIPTION)
;Parameters:
; USERNAME: Required Parameter. The Name of the local user you wish to create
; PASSWORD: Required Parameter. The Password of the local User you wish create
; DESCRIPTION: Optional Parameter. The description for the local user
;Example:
;	fnCreateLocalUser('TestUser', '123Password456', 'A Test Account')

Function fnCreateLocalUser($strName, $strPassword, Optional $strDescription)
		
	Dim $objComputer	;Adsi root Object
	Dim $objUser		;Adsi User Object
		
	If $strDescription = ''	$strDescription = 'Local User'	EndIf	
	
	;Create Object
	$objComputer = GetObject("WinNT://" + @WKSTA)
	
	;Create object of class user on the computer  
	$objUser = $objComputer.Create("user", $strName)  
	$objUser.Put("description", $strDescription)
	
	;Save changes  
	$objUser.SetInfo
	
	;Set password
	$objUser.SetPassword($strPassword)
	$objUser.SetInfo 
		
	If @ERROR Exit 1 EndIf
EndFunction 


 Code:
;Function:
; fnSetNeverExpire()
;Original code by  Chris S
;Action:
; Sets the password for the specified user to not expire
;Syntax:
; fnSetNeverExpire(USERNAME)
;Parameters:
; USERNAME: Required Parameter. The Name of the local user you wish to set the PASSWORD to not expire
;Example:
;	fnSetNeverExpire('TestUser')


Function fnSetNeverExpire($strUser)
	;DESCRIPTION: Sets the account's password to never expire
	;Original code by  Chris S, just function'ised it (that even a word? :P)
		
	Dim $ADS_UF_DONT_EXPIRE_PASSWD ;Contains the 'never expire' flag
	Dim $objUser						 ;Adsi object for the specified user
	Dim $objUserFlags					 ;Object containing the flags for the specified user
	Dim $strNewFlags					 ;String containing the new flags
	
	;Initilise Variables
	$ADS_UF_DONT_EXPIRE_PASSWD = &10000
		
	;Create Objects
	$objUser = GetObject('WinNT://' + @WKSTA + '/' + $strUser + ',user')			
	$objUserFlags = $objUser.Get('UserFlags')
		
	If ($objUserFlags & $ADS_UF_DONT_EXPIRE_PASSWD) = 0	;Currently password will expire.
		$strNewFlags = $objUserFlags + $ADS_UF_DONT_EXPIRE_PASSWD
		$objUser.Put("userFlags", $strNewFlags)
		$objUser.SetInfo
		If @ERROR
			Exit 1 
		Else 
			Exit 0 
		EndIf
	Else
		;Already does not expire
		Exit 0
	EndIf	
EndFunction  

Top
Page 1 of 1 1


Moderator:  Glenn Barnas, NTDOC, Arend_, Jochen, Radimus, Allen, ShaneEP, Ruud van Velsen, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 661 anonymous users online.
Newest Members
Viginette, ManuvdWielNL, Sir_Barrington, batdk82, StuTheCoder
17888 Registered Users

Generated in 0.057 seconds in which 0.024 seconds were spent on a total of 13 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org