NT User Management

with commands and scripts


This page describes the use of commands and scripts for user management and Windows NT NTFS security, as outlined in the following pages :

Topics

  1. some batch program structures
  2. Batch files for Windows NT user management
  3. BONUS : program to create input files
  4. MORE ...

Creating users on a WIndows NT system is easy : fill in the dialog boxes and you're done. However, you may end up repeating the same thing over and over again to create 20 users for the software development department, 20 more for human resources, some 25 people in sales, and so on. Repeating the same thing over and over again ... that's what we have computers for, so there must be a way to let the computer do this.

This is an exercise in using DOS Batch files to create user accounts and manage file ACLs.

What we need is

  1. commands to
  2. a structure that will allow us to repeat these commands : FOR ... DO ...
  3. a technique that will allow us to supply a list of user names and / or group names (eg from a file) to these commands : pipes, redirects, or parsing

Type any of these commands with /? to see syntax, or look them up in Microsoft's TechNet Command Line Reference. The NET commands will show extensive help if you type net HELP users, net HELP groups, etc. Pipe through MORE to see output screen by screen (pipe : see further).
Note that there can be minor syntax differences between MS DOS commands, especially between MS-DOS 6 and MS-DOS 7 (MS-DOS 7 = Windows 95 and up). Commands on NT systems may also differ between different versions (Windows NT, Windows 2000, Windows XP, Windows 2003, ...) and with the DOS/Win9x family.

pipes and redirects

redirect operators

Commands and command line applications expect input and output from / to the console : input from the keyboard, output to the screen. However, it is possible to use input from other sources, and output to somewhere else. Typically, input and output can be redirected from and to text files. This is done with the redirect operators >, <, <<.

> and >> direct the output of a command to a file. > will create a new file, or overwrite an existing file. >> will append the output to the end of an existing file, or create a new file if it does not yet exist.

An easy exemple : dir c:\  >>  c:\temp\dirlist.txt will write the output of the dir c:\ command to a file named dirlist.txt located in the c:\temp\ directory.

Likewise, < will push te contents of a file towards a command, e.g a file named reply, containing 'Y <Enter>', can be used to automatically reply 'Y' to commands that require confirmation but don't have a /Y switch.

pipes

Pipes are similar to redirects, but in this case the output of one command is intercepted on its way to the screen, and used as input for an other command. The pipe operator is |

Typically, the output of a command will be piped through a so-called filter, such as more or sort. E.g. Type mytext.txt will put the contects of the file mytext.txt on the screen. Type mytext.txt | more will put the output through the 'more' command which will allow you to view the output screen by screen, which is usefull if the text does not fit in 1 screen. Type mylist.txt | sort would sort the output of the type command before taking it to the screen.

Pipes can also be applied to commands other than these filters. As in a previous exemple, ECHO Y | format ... will provide the format command with a confirmation (Y) when it asks 'are you sure [Y/N] ? ' : the output of the ECHO command is used as input to the FORMAT command.

Pipes can be very usefull to combine commands to get the desired result. In Unix-like operating systems, the pipe and filter approach is an essential feature of the operating system. In Dos and Windows, it's rather less developed, and not used all that much. The redirection operators allow you to create files which contain the output, the results from commands, or have commands read parameters from text files. Main problem there is that the text file will be read as a whole, so it may get difficult to read values one by one.

parsing

parsing means something like : a program reads a (text) file line by line, and does something with the text it has read : interprete it as commands, remember the words to use them as parameters, etc. This is a classic technique : html files are parsed by the web browser (read and interpreted to render a web page), batch files are parsed by the command interpreter (command.exe or cmd.exe) so that every command is execute 1 by 1, .ini files are read by applications until a keyword is found, than the value next to the keyword is used as a parameter, etc.

We'll see parsing later, in the FOR - command.

loop

The DOS batch language provides a control structure for loops : the "FOR ... DO ..." loop. Syntax :

	FOR{%Variable | %%Variable} in (Set) do Command [CommandLineOptions]
	
{%Variable | %%Variable}
Required. Represents a replaceable parameter. Use %Variable to carry out for from the command prompt. Use %%Variable to carry out the for command within a batch file. Variables are case-sensitive and must be represented with an alphabetical value, such as %A, %B, or %C.
(Set)
Required. Specifies one or more files, directories, range of values, or text strings that you want to process with the specified command. The parentheses are required. Wildcards are allowed. e.g. (*.*) means : all files in current directory; (list.txt) means : list.txt file in curtrent directory
Command
Required. Specifies the command that you want to carry out on each file, directory, range of values, or text string included in the specified (Set).
CommandLineOptions
Specifies any command-line options that you want to use with the specified command.
/?
Displays help at the command prompt.

Try some exemples to see how FOR works (see Technet : Command Line Reference). The most simple example (works on Windows 9x as well) is

		for %f in (*.doc *.txt) do type %f 

	

This takes every file with extension .doc or .txt in the current directory, feeds them into the %f variable one by one, then for each file (%f), the command type %f is executed. The result : the contents of every .doc or .txt file is shown on the screen.

FOR has options to work with directories, subdirectories, values from a list or from a file, etc. We'll come to that later.

SHIFT

When a batch file is called with parameters, these parameters are passed to the batch file where they are known by symbols like %1 (first parameter), %2 (second parameter), %3 etc up to %9. It is thus possible to submit 9 variable parameters to a batch file.

In fact, it is possible to supply more than 9 parameters, but the batch language can only name the first 9. To have access to parameter 10 and up, you SHIFT the value of 'parameter 10' to %9, the value of %9 goes into %8, the value of %8 to %7, and so on, until %1 gets the value of %2, and the original value of %1 is discarded.

This is often used in a loop. You start a batch file with a number of parameters,

C:> batch1.bat 1 A 2 B 3 C 4 D 5 E 6 F 7 G 8 H

and in the batch file, a GOTO and SHIFT contraption create a loop in wich %1 takes the next parameter value for evey iteration.


		@ echo off

		:begin
		
		rem show 2 parameters
		echo %1 - %2

		rem SHIFT twice to get values of parameter 3 and 4 in to %1 and %2
		SHIFT
		SHIFT

		rem loop by returning to begin
		GOTO begin

	

Of course, this would be an infinite loop, so the last statement should test whether there's another value, and only loop if there is : IF NOT "%1"=="" goto begin
There's no 'while' loop in the batch language, and the FOR loop is actually a FOR EACH structure, so this IF <condition> GOTO <label or line number that indicates what to repeat>... contraption is a typical workaround in DOS batch files.

Parsing with FOR /F

FOR with option /F lets you parse a file. This lets you read values from a file, 1 line at the time, and feed these values into the FOR loop. Each line can contain one or more then one value. If it's more than one, they have to be delimited. You can specify the delimiter in the FOR /F command. Say you have a plain text file - list.txt - with a bunch of user names and corresponding passwords, 1 set on each line, with a space between the user name and the password.

	FOR /F "tokens=1,2" %i in (list.txt) do @echo user %i has password %j
	

Compare this with the basic FOR command shown earlier. The /F "tokens=1,2" part means : parse (/F) and read 2 values from each line (token=1,2), values are delimited by a space (delimes= ; note the space after the '='). The values are then passed to the echo command; the %i variable is declared in the FOR statement and takes the value of token1 (1st value on the line), %j variable is implicitily declared to hold the second token (2nd value rerad from the line). If more tokens are declared, more values per line can be read and stored in variables. The whole mechanism is repeated for each username - password combination, read one by one (line by line) from the list.txt file.

We can now replace the echo command by a command to create users or create groups, or add users to groups, etc. All we need then are lists of users, or lists of groups, or a directory with a text file for each group, each file containing names and paswords of the members of that group, and we have all the tools we need to write a batch file (or a number of batch files) to implement our user management.

Granted, you still need to create the lists. But it's just lists, you don't need to write a command with options and parameters for each user : once you get the syntax right with all the switches and options correct, you can automatically have it done for every user. And you can reuse these lists for several groups, and to read parameters from for the CACLS command as well. So it is an improvement, I'd say.

One mayor disadvantage is that you have plain text files with the namles and passwords of all your user accounts. That's a highly insecure situation. By no means should you keep that file on the computer after the user accounts etc have been created. Delete it, or if you want to keep it in case you need to restore your user accounts from scratch, then encrypt it, and move it to a diskette or CD-ROM for save keeping.

In the NET USER command, you can put * in stead of the password. You can do that either in the textfile with usernames, or in the script : FOR ... IN ... DO NET USER %1 * /ADD. The * will cause NET USER to prompt for a password, so that they don't have to be in the text file. Still, uou'd have to type them all, and your list will still contain half of the crucial account information, the username

Batch files

Here are some exemples of batch files that could be used to create users, groups, and modify ACLs, using some of the batch script techniques mentioned. I'm trying to stay as close as possible to the case study of the Silly Software Company, but for reasons of clarity, there may be minor differences between the exemples here and the case of the Silly Software Company.

create groups with NET GROUPS and input from a text file

List the groups you want to create in a text file (groups.txt) :


		GeneralDirectors
		ICT
		Programmers
		MarketingTeam
		FinanceTeam
		HRteam 
		TeamLeaders

		

Then create a batch file that will run the NET GROUPS /ADD command with every one of these groups. The groups are Global Groups, meant to group users.

		
		ECHO creating groups
		ECHO.
		
		FOR /F %%i in (groups.txt) DO NET GROUPS %%i /ADD

		REM show groups
		NET GROUPS |MORE

		

The file groups.txt is expected in the current directory. You can specify a different location by using a full pathname, eg. FOR ... IN (A:\usermgt\groups.txt) DO ... )

Create local groups

NET LOCALGROUPS groupname /ADD [/DOMAIN] creates local groups. Syntax is identical to NET GROUPS. Global groups (and users) can be added to localgroups with NET LOCALGROUPS groupname name /ADD, where groupname is the name of the local group, name is the name of the global group or user to be added to the local group.

Create users and add them to groups - using 1 input file

As we'll use 1 input file, this file need to contain the group name, user name and password for each user. If you want to add options such as the user's full name, activate or disactivate the account, comments, logon hours, etc (in fact, all the User Manager check boxes), they'll need to be listed as well.

		GeneralDirectors	mob	pw01

		ICT			ned	pw02 

		Programmers		ssf	pw03 
		Programmers		cpp	pw04 
		Programmers		ssk	pw05 

		Marketing		mark	pw06 
		Marketing		mich 	pw07 
		Marketing		moni 	pw08 

		Finance 		buck 	pw09 
		Finance 		bibi 	pw10 

		TeamLeaders 		mob 	pw01 
		TeamLeaders 		ned 	pw02 
		TeamLeaders  		ssf 	pw03 
		TeamLeaders 		mark 	pw06 
		TeamLeaders 		buck 	pw09 

		

The order in the file is : Groupname UserName Password. A space or tab is used as default delimiter in the FOR /F command. Similar to the group creation batch file, you simply run a 'create user' command and an 'add to group' command for each of these user/group combinations.


	@echo off
	echo create users
	echo.

	FOR /F "tokens=2,3" %%i IN (groups.txt>  DO NET USER %%i %%j /ADD

	echo finished creating users.
	echo adding users to groups.
	echo.

	FOR /F "tokens=1,3" %%i IN (groups.txt>  DO NET GROUP %%i %%j /ADD
		
	

In the first FOR loop, token 2,3 refer to user name and password, which are passed to the NET USER < name > (%%i) < password > (%%j) command,
In the second FOR loop, token 1,2 refer to user name and group name, passed to the NET GROUP <groupname >(%%i) < username> (%%j) command. Because some users are member of more than 1 group, this batch will attemt to create the same user twice. This is not a problem. The NET USER (or NET GROUPS) command will just return 'User Account already exists", and the batch will go on with the next entry in the file.

alternatively :
Create groups and add users in 1 batch operation - with 1 input file

As the group names are mentioned in the list, this list can be used both for creating groups, for creating user accounts, and for adding users to the group


	@echo off
		
	REM create users
	FOR /F "tokens=2,3" %%i IN (groups.txt>  DO NET USER %%i %%j /ADD

	REM create groups : 
	FOR /F "tokens=1" %%i IN (groups.txt>  DO NET GROUPS %%i /ADD
		
	REM Add users to groups
	FOR /F "tokens=1,2" %%i IN (groups.txt>  DO NET GROUP %%i %%j /ADD
		
	echo done.


		

alternatively :
Create users and add them to groups - using a separate input file for each group

When the number of users and groups increases, and you want to add more info to the user accounts, just 1 list may get a bit too long, or a bit messy. You could also use a separate list for each group.

For clarity, let's consider 2 groups only:
Progammers in A:\usermgt\prog.txt :

		ssf pw03 Silly Softie
		cpp pw04 Celia Pointer
		ssk pw05 Silly Skript Kiddie

		

TeamLeaders in A:\usermgt\tmldr.txt :


		mob pw01 Mean Old Bastard
		ned pw02 Ned
		ssf pw03 Silly Softie
		mark pw06 Mark
		buck pw09 Big Buck

		

Note that the full name has been added to the list, it will become 'token 3' in the FOR /F command. This is done by adding * to the "tokens=" part of the command, meaning : the rest of the line. If this is not suitable, you can choose another delimiter and edit your list accordingly, eg "delims=," for a list like mob,pw01,Mean Old Bastard .

Now, for the loops : we need 1 loop that will check every list, and 1 loop that will - in every list - check every line for names and passwords. So we need a loop inside a loop : a nested loop. Although, in general, statements can not span across lines (end of line = end of statement), you can sometimes use parentheses to span a statement over multiple lines:


		echo Adding users to groups, using group lists in a:\usermgt\ directory
		echo.

		FOR %%F in (A:\usermgt\*.*) DO (
			FOR /F "tokens=1,2,*" %%U in (%%F) DO ( 
				NET USER %%U %%V /fullname:"%%W" /ADD
				)
			)

		

Somehow, you'de expect a statement such as

FOR /F "tokens=1,2,*" %%U in (A:\usermgt\*.*) DO NET USER ...

to work ass well, because the *.* would mean 'every file in this directory' - you wouldn't have to read them with a seperate FOR statement. But for some reasing (the file parsing ?) this does not work in this situation.

The nested loop takes care of creating all the user accounts. Remains the problem of creating the groups and adding the users to their respective groups.

One solution is to use a second .bat file : The first batch file would loop through the files, and call a second batch file. The second batch file would contain the 2nd loop, the 'create user from evey item in the list' code . A group name can be supplied as a parameter that will be accessible in the creatUser.bat as %1 (batch parameter 1).

Since these text files where values are taken from, don't really need extensions, you can use the filename as group name : the file Programmers contains members of the group Programmers, the file teamleaders contains members of teamleaders, etc.

So that would be

		[group.bat :] FOR %%F in (A:\usermgt\*.*) DO call adduser.bat %%F

		

in adduser.bat, the parameter %%F is copied into %1 :

		
		[adduser.bat :] FOR %%i in (%1) DO NET GROUP %1 %%i /ADD

		

Or you could try it in one statement, like

		FOR %%f in (*.txt) DO (FOR /F %%i in (%%f.txt) DO NET GROUPS %%f %%i /ADD)
		

Yet an other solution could be to call a batch file to add users, and provide groupname and corresponding file as parameters.

Assuming that prog.txt contains a list of users to be added to the group Programmers, you'd call a batch file from the command prompt :

 
		C:> adduser programmers prog.txt
		

Inside the batch file adduser.bat, the parameters will be known as %1 and %2 respectively. The batch file might look like this :

		FOR /F "token=1,2" %%i in (%%2) DO NET GROUP %1 %%i /ADD
		

Downside here is that you'd have to repeat it for every group, but you could create a batch that refreshes every group :


			echo refresh groups
			echo.

			addusers programmers prog.txt
			addusers teamleders tmldr.txt
			addusers marketing marketing.txt
			addusers finance fin.txt
			addusers HRteam hr.txt
			addusers ICT ict.txt

		

Use your imagination : depending on the situation, you can combine these batch processes or choose from the different approaches to create a sollution that best matches your needs. (If you want to be a hacker, just copying scripts is not your style, is it ?)

Modify access control lists for files and directories
- using input from 'group' text file

The CACLS command lets you replace or edit (/E) the ACL of files and directories. Type CACLS /? for a list of options and switches to grant, revoke and deny access rights, including subdirectories (/T), etc.

You will be asked 'Are you sure [Y/N], so to avoid having to reply, you can already pipe the reply to the command :


		ECHO Y | CACLS D:\ /P Administrator:F localgrProgrammers:C localgrStaff:R /T
		

This would give Administrator Full controll, the localgroupProgrammers Write access, and the local group Staff Read access to D:\ and subdirectories of D.

To implement access rights to files and directories, you'd need to know what group has which rights to each and any file and directory. A simple policy pays off here. If you only need to set access rights for a few groups to a few top level directories and let files and subdirectories inherit these rights, your live (or at least : your job) becomes a lot easier.

Assume we'll give Write / Change Access to the following groups, for the directories mentioned. Apart from that, all staff will just have Read access to the D:\Data directory and all subdirectories.


		D:\Data\Management	GeneralDirectors 
		D:\Data\ICT		ICT		
		D:\Data\Development	Programmers	
		D:\Data\Marketing	MarketingTeam	
		D:\Data\Finance		FinanceTeam	
		D:\Data\Personel	HRteam 		
		D:\Data\Teams		TeamLeaders	

		

First, we give Administrator and SYSTEM Full control on all partitions, directories, subdirectories etc. As we replace the existing ACL's, former settings such as Everyone:Full Control, will be removed in the same action.


	@echo off
	echo setting full control for administrator and system
	echo on all partitions, directories and files

	For %%d in (C D E F G H I J K) DO @ECHO Y| CACLS %%d: /P administrator:F SYSTEM:F

		

Then we give the local group Users Read access to the D:\Data directory and all subdirectories (/T). We do not replace the ACL but edit it (/E) so that previous settings (Administrator, System) are not removed. The local group Users is a built-in local group which by default contains the global group DomainUsers, and thus all user accounts.


	echo setting read access for all users to D (data) partition
	ECHO Y | CACLS d:\data /T /E /P Users:R

	

Used like this, the CACLS command sets ACL's for files and directories both, in one go.

Next, we use a FOR statement to go through the modified groups.txt file which will now match a group to the directory. Because of the order that the variables appear in the CALCS command (directory then group), the items in the file that is parsed need to be in the same order, or the FOR /F "tokens" statement will fail.

	
	FOR /F "tokens=1-2" %%F in (groups.txt) DO echo Y | CACLS %%F /T /E /P %G:C


	

Lastly, we could review all ACL's to see if it looks OK. Any left-over odds and ends can be modified manually or by adding an appropriate statement to this script.


	echo check ACL's
	echo.
	pause

  	For %%d in (C D E F G H ) DO (CACLS %%d: /T | more) & pause
	
	

Create network shares

NET SHARE lets you share directories, and set some properties such as maximum number of concurrent users. Note that you can not set permissions to these shares (using command line programs). They get 'Everyone Full Control' by default. But in any case, the NTFS security (ACL's) overrules (the lack of) share permissions, so that's not too bad.

Other commands

Another useful command is NET ACCOUNTS that can be used to modify all user accounts, for settings such as minimum password length, force unique passwords when forcing a password change, etc.

with NET HELP | MORE you get an overview of all NET commands.

A lot of these NET commands have a switch /DOMAIN to force the operation to be executed on the primary domain controller, when run from an NT workstation. Without /DOMAIN, the operation is executed on the local machine.

Resource Kit

Microsoft supplies Resource Kits to its operating systems. They contain upgraded versions of commands and tools (command line tools and others) for network administration and server administration, which are often more powerful than the standard commands. You need to register with Microsoft Technet to have access to these resource kits. Registration with TechNet is NOT free. (What did you expect ?). You can, however, download free subsets (smaller, less complete sets) of the resource kits from Microsoft Technet


BONUS : creating text files (for lists of users and groups)

Of course you can just use a text editor (edit.com, notepad.exe) to create or modify the text files you'll use as input for these scripts, or edit them from the command line with echo >> and type >> and so on.

If you're not comfortable with text files, or need large lists with added functionality (sorting, lookup, ...) you can create the lists in a spreadsheet (ms Excel), and copy the contents into a text file.


More where this came from ...

(Update June 4, 2005:) I've elaborated on the use of command line tools, batch files and scripts for (Windows) Network and System Administration in Automatic Network and System Administration in the Small Office, where you'll find exemples of scripts for user and computer management, Active Directory Organizational Units, Software Deployment and Management, Unattended Operating System Setups, and much more.


Koen Noens
15 august 2003