|< Windows Access Control Programming 15 | Main | Windows User Accounts & Groups Programming 2 >| Site Index | Download |


 

 

 

 

MODULE M

WINDOWS OS

.::USER ACCOUNTS AND GROUPS:  STORY & PROGRAM EXAMPLES::.

PART 1

 

 

 

 

What do we have in this Module?

  1. User Functions

  2. Groups

  3. Group Types

  4. Group Scope

  5. Local Group Functions

  6. Group Functions

  7. NetUserAdd() Program Example

 

My Training Period: xx hours. Before you begin, read some instruction here.

 

 

 

 

 

 

 

 

 

 

 

 

The expected abilities in this session:

User Functions

 

In MSDN documentation, the network management user functions control a user's account in the security database, which is the security accounts manager (SAM) database or, in the case of domain controllers, the Active Directory.  The user functions are listed in the following Table.

 

Function

Description

NetUserAdd()

Adds a user account and assigns a password and privilege level.

NetUserChangePassword()

Changes a user's password for a specified network server or domain.

NetUserDel()

Deletes a user account from the server.

NetUserEnum()

Lists all user accounts on a server.

NetUserGetGroups()

Returns a list of global group names to which a user belongs.

NetUserGetInfo()

Returns information about a particular user account on a server.

NetUserGetLocalGroups()

Returns a list of local group names to which a user belongs.

NetUserSetGroups()

Sets global group memberships for a specified user account.

NetUserSetInfo()

Sets the password and other elements of a user account.

 

Table 1

 

Each user or application that accesses network resources must have an account in the security database.  The directory services use this account to verify that the user or application has permission to connect to a resource. When a user or an application requests access to a resource, the Windows security system checks for an appropriate user account or group account to permit the access.  Once you remove a user account by calling the NetUserDel() function, the user can no longer access the server except by using the guest account.  Because a user's password is confidential, it is not returned by the NetUserEnum() function or the NetUserGetInfo() function.  The password is initially assigned when you call NetUserAdd().  User account information is available at the following levels.

 

Level

Description

USER_INFO_0

A structure contains a user account name.

USER_INFO_1

A structure contains information about a user account, including account name, password data, privilege level, and the path to the user's home directory.

USER_INFO_2

A structure contains information about a user account, including the account name, password data, privilege level, the path to the user's home directory, and other user-related network statistics.

USER_INFO_3

A structure contains information about a user account, including the account name, password data, privilege level, the path to the user's home directory, relative identifiers (RIDs), and other user-related network statistics.  It is recommended that you use the USER_INFO_4 structure instead.

USER_INFO_4

A structure contains information about a user account, including the account name, password data, privilege level, the path to the user's home directory, security identifier (SID), and other user-related network statistics.

Note that the USER_INFO_4 structure supersedes the USER_INFO_3 structure.  It is recommended that you use USER_INFO_4 instead of the USER_INFO_3 structure.

USER_INFO_10

A structure contains information about a user account, including the account name, comments associated with the account, and the user's full name.

USER_INFO_11

A structure contains information about a user account, including the account name, privilege level, the path to the user's home directory, and other user-related network statistics.

USER_INFO_20

A structure contains information about a user account, including the account name, the user's full name, a comment associated with the account, and the user's relative ID (RID).  It is recommended that you use the USER_INFO_23 structure instead.

USER_INFO_21

A structure contains a one-way encrypted LAN Manager 2.x-compatible password.

USER_INFO_22

A structure contains information about a user account, including the account name, privilege level, and the path to the user's home directory, a one-way encrypted LAN Manager 2.x-compatible password, and other user-related network statistics.

USER_INFO_23

A structure contains information about a user account, including the account name, the user's full name, a comment associated with the account, and the user's security identifier (SID). Note that the USER_INFO_23 structure supersedes the USER_INFO_20 structure.  It is recommended that you use USER_INFO_23 instead of the USER_INFO_20 structure.

 

Table 2

 

In addition, the following information levels are valid when you call the NetUserSetInfo() function:

 

Level

Description

USER_INFO_1003

A structure contains a user password.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1005

A structure contains a privilege level to assign to a user network account.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1006

A structure contains the user's home directory path.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1007

A structure contains a comment associated with a user network account.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1008

A structure contains a set of bit flags defining several user network account parameters.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1009

A structure contains the path for a user's logon script file.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1010

A structure contains a set of bit flags defining the operator privileges assigned to a user network account.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1011

A structure contains the full name of a network user.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1012

A structure contains a user comment.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1014

A structure contains the names of workstations from which the user can log on.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1017

A structure contains expiration information for network user accounts.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1020

A structure contains the times during which a user can log on to the network.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1024

A structure contains the country/region code for a network user's language of choice.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1051

A structure contains the relative ID (RID) associated with the user account.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1052

A structure contains the path to a network user's profile.  This information level is valid only when you call the NetUserSetInfo() function.

USER_INFO_1053

A structure contains user information for network accounts.  This information level is valid only when you call the NetUserSetInfo() function.

 

Table 3

 

The following functions enable applications to check password compliance.

 

Function

Description

NetValidatePasswordPolicyFree()

Frees the memory allocated by the NetValidatePasswordPolicy() function.

NetValidatePasswordPolicy()

Verifies that passwords meet complexity, aging, minimum length, and history reuse requirements.

 

Table 4

 

If you are programming for Active Directory®, you may be able to call certain Active Directory Service Interface (ADSI) methods to achieve the same functionality you can achieve by calling the network management user functions.

 

Groups

 

A group is a collection of users, computers, contacts, and other groups.  Groups can be used as security or as e-mail distribution collections.  Distribution groups are used only for e-mail.  Security groups are used both to grant access to resources and as e-mail distribution lists.

 

Group Types

 

There are two types of groups defined by Active Directory, Security Groups and Distribution Groups.

A security group provides a logical grouping of objects and the group itself can be used as a security principal in an ACL.  When a security group is given access to an object, all members of the security group automatically receive the same access to the object.  Security groups with Universal scope can also be used as an e-mail entity.  Sending an e-mail message to a universal security group sends the message to all the members of the group.  A distribution group also provides a logical grouping of objects, but cannot provide any access privileges.  Distribution groups are not security enabled and cannot be used as a security principal in an ACL.  Distribution groups are only used for grouping purposes.  For example, distribution lists can be used with e-mail applications, such as Exchange, to send e-mail to a collection of users.

 

Group Scope

 

There are three group scopes that are defined by Active Directory, Universal, Global and Domain Local.  The scope of the group defines what types of object can belong to the group, what types of groups the group can be a member of and the scope of objects that security groups can be given access to.  When the domain functional level is set to Windows 2000 mixed mode, security groups with universal scope cannot be created.  The following table lists the three group scopes and more information about each scope for a security group.

 

Scope

Possible members

Scope conversion

Can grant permissions

Possible member of

Universal

Accounts from any domain in the same forest.

Global groups from any domain in the same forest.

Other universal groups from any domain in the same forest.

Can be converted to domain local scope.

Can be converted to global scope as long as the group does not contain any other universal groups.

On any domain in the same forest or trusting forests.

Other universal groups in the same forest.

Domain local groups in the same forest or trusting forests.

Local groups on machines in the same forest or trusting forests.

Global

Accounts from the same domain.

Other global groups from the same domain.

Can be converted to universal scope as long as the group is not a member of any other global group.

On any domain in the same forest or trusting domains or forests.

Universal groups from any domain in the same forest.

Other global groups from the same domain.

Domain local groups from any domain in the same forest or from any trusting domain.

Domain Local

Accounts from any domain or any trusted domain.

Global groups from any domain or any trusted domain.

Universal groups from any domain in the same forest.

Other domain local groups from the same domain.

Can be converted to universal scope as long as the group does not contain any other domain local groups.

Within the same domain.

Other domain local groups from the same domain.

Local groups on machines in the same domain, excluding built-in groups that have well-known SIDs.

 

Table 5

 

Local Group Functions

 

A local group can contain user accounts or global group accounts from one or more domains (Global groups can contain users from only one domain).  A local group shares common privileges and rights only within its own domain.

The network management local group functions control members of local groups in a way that the functions can only be called locally on the system on which the local group is defined.  On a Windows NT, Windows 2000, or Windows XP workstation, or on a server that is not a domain controller, you can use only a local group defined on that system.

On Windows NT 4.0, a local group is defined on the primary domain controller (PDC) and replicated to all other domain controllers in the domain.  Therefore, a local group is available on all domain controllers within the domain in which it was created.  In Active Directory domains that are in native mode, local groups are called domain local groups.  Domain local groups are available on all domain controllers, member servers, and workstations joined to the domain.  Active Directory mixed-mode domains behave like Windows NT 4.0 domains.  The local group functions create or delete local groups, and review or adjust the memberships of local groups.  These functions are listed in the following Table.

 

Function

Description

NetLocalGroupAdd()

Creates a local group.

NetLocalGroupAddMembers()

Adds one or more users or global groups to an existing local group.

NetLocalGroupDel()

Deletes a local group, removing all existing members from the group.

NetLocalGroupDelMembers()

Removes one or more members from an existing local group.

NetLocalGroupEnum()

Returns information about each local group account on a server.

NetLocalGroupGetInfo()

Returns information about a particular local group account on a server.

NetLocalGroupGetMembers()

Lists all members of a specified local group.

NetLocalGroupSetInfo()

Sets general information about a local group.

NetLocalGroupSetMembers()

Assigns members to a local group.

 

Table 6

 

You can add a member to a local group by specifying the security identifier (SID) of the member.  To translate a member account name to a SID, call the LookupAccountName() function.  When you create a local group by calling the NetLocalGroupAdd() function, you must supply a local group name.  Initially, the local group has no members.  Local group account information is available at the following levels (defined in the respective structure):

 

Level

Description

LOCALGROUP_INFO_0

A structure contains a local group name.

LOCALGROUP_INFO_1

A structure contains a local group name and a comment describing the local group.

LOCALGROUP_INFO_1002

A structure contains a comment describing a local group.

 

Table 7

 

Local group membership information is available at the following information levels:

 

Level

Description

LOCALGROUP_MEMBERS_INFO_0

A structure contains the security identifier (SID) associated with a local group member. The member can be a user account or a global group account.

LOCALGROUP_MEMBERS_INFO_1

A structure contains the security identifier (SID) and account information associated with the member of a local group.

LOCALGROUP_MEMBERS_INFO_2

A structure contains the security identifier (SID) and account information associated with a local group member.

LOCALGROUP_MEMBERS_INFO_3

A structure contains the account name and domain name associated with a local group member.

 

Table 8

 

You can retrieve the names of the local groups to which a user belongs by calling the NetUserGetLocalGroups() function, specifying the following information level:

LOCALGROUP_USERS_INFO_0 - A structure contains local group member information.

If you are programming for Active Directory®, you may be able to call certain Active Directory Service Interface (ADSI) methods to achieve the same functionality you can achieve by calling the network management local group functions.

 

Group Functions

 

A global group contains user accounts from one domain that are grouped together under one group account name.  A global group can contain only members (users) from the domain where the global group is created; it cannot contain local groups.  A global group is available within its own domain and within any trusting domain.  The network management group functions control global groups.  The group functions are listed following.

 

Function

Description

NetGroupAdd()

Creates a global group.

NetGroupAddUser()

Adds one user to an existing global group.

NetGroupDel()

Removes a global group whether or not the group has any members.

NetGroupDelUser()

Removes one user name from a global group.

NetGroupEnum()

Lists all global groups on a server.

NetGroupGetInfo()

Returns information about a particular global group.

NetGroupGetUsers()

Lists all members of a particular global group.

NetGroupSetInfo()

Sets general information about a global group.

NetGroupSetUsers()

Assigns members to a new global group; replaces the members of an existing group.

 

Table 9

 

When you call the NetGroupAdd() function to create a global group, you must supply a group name. Initially, a new group has no members.  User accounts automatically belong to the special global group Domain Users.  Membership in this group is indirectly controlled by the NetUserAdd(), NetUserDel() and NetUserSetInfo() functions.  Global group account information is available at the following levels:

 

Level

Description

GROUP_INFO_0

A structure contains the name of a global group in the security database, which is the security accounts manager (SAM) database or, in the case of domain controllers, the Active Directory.

GROUP_INFO_1

A structure contains a global group name and a comment to associate with the group.

GROUP_INFO_2

A structure contains information about a global group, including name, identifier, and resource attributes.  It is recommended that you use the GROUP_INFO_3 structure instead.

GROUP_INFO_3

A structure contains information about a global group, including name, security identifier (SID), and resource attributes.

GROUP_INFO_1002

A structure contains a comment to associate with a global group.

GROUP_INFO_1005

A structure contains the resource attributes associated with a global group.

 

Table 10

 

The 1002 and 1005 levels are valid only for the NetGroupSetInfo() function.  Global group member information is available at the following information level:

GROUP_USERS_INFO_0 - A structure contains global group member information.

If you are programming for Active Directory®, you may be able to call certain Active Directory Service Interface (ADSI) methods to achieve the same functionality you can achieve by calling the network management group functions.

 

NetUserAdd() Program Example

 

The following code sample demonstrates how to add a user account and assign a privilege level using a call to the NetUserAdd() function.  The code sample fills in the members of the USER_INFO_1 structure and calls NetUserAdd(), specifying information level 1. Before you can compile and link the program, for default Visual Studio .Net 2003 installation, you have to add netapi32.lib library for NetUserAdd() function family.  Follow the steps below.

 

Project menu your_project_name Properties... sub menu.  In the Configuration Properties window (as shown below), expand the Linker folder select the Input subfolder.  For the Additional Dependencies setting, add manually the netapi32.lib.  Click Apply and/or OK button.

 

These steps also applied to other libraries that required by your programs.  The error message something like "Cannot resolve symbols... ", normally generated if the linker cannot find the appropriate library to resolve the symbols in the functions through the header files used in your programs.  All the program examples run by Restricted User (normal user) who is a member of Administrators group (Debugger Users group should be included by default for the user that installs the Visual Studio .Net 2003) except whenever mentioned.  What additional library needed to be included depends on the function used (header file) and can be known by checking the documentation for that function.

 

Adding library/dependencies to Visual C++ .Net project

 

Figure 1: Project property pages, adding additional dependencies.

 

Just type the library file name and click the OK button.  Actually this library file resides under the default path of the Visual C++ .Net.

 

Manually add library to Visual C++ .Net project

 

Figure 2:  Adding additional library.

 

The following example adds a user account to the system.

 

//********* myadduser.cpp **********

// For WinXp

#define _WIN32_WINNT 0x0501

// Wide character/Unicode based program

#ifndef UNICODE

#define UNICODE

#endif

 

#include <windows.h>

#include <stdio.h>

#include <lm.h>

 

// This program accept 3 arguments: servername, user account and password.

// It is run on local WinXp machine so the servername is the

// local WinXp machine name or you can use NULL for the 1st parameter

// of the NetUserAdd() and arguments, should be without the servername.

int wmain(int argc, wchar_t *argv[ ])

{

   USER_INFO_1 ui;

   DWORD dwLevel = 1;

   DWORD dwError = 0;

   NET_API_STATUS nStatus;

 

   if(argc != 4)

   {

      fwprintf(stderr, L"Usage: %s ServerName UserName Password.\n", argv[0]);

      // or use fwprintf(stderr, L"Usage: %s UserName Password.\n", argv[0]);

      // for local machine and adjust other array element appropriately.

      exit(1);

   }

   // Set up the USER_INFO_1 structure.

   // USER_PRIV_USER: name identifies an normal user

   // UF_SCRIPT: required for LAN Manager 2.0 and Windows NT and later.

   ui.usri1_name = argv[2];                      // Username entered through command line

   ui.usri1_password = argv[4];              // Password

   ui.usri1_priv = USER_PRIV_USER; // As a normal/restricted user

   ui.usri1_home_dir = NULL;                // No home directory

   ui.usri1_comment = L"This is a test normal user account using NetUserAdd";  // Comment

   ui.usri1_flags = UF_SCRIPT;            // Must be UF_SCRIPT

   ui.usri1_script_path = NULL;            // No script path

   // Call the NetUserAdd() function, specifying level 1.

   nStatus = NetUserAdd(argv[1],

                        dwLevel,

                        (LPBYTE)&ui,

                        &dwError);

   // If the call succeeds, inform the user.

   if(nStatus == NERR_Success)

   {

     fwprintf(stderr, L"%s user has been successfully added on %s machine.\n", argv[2], argv[1]);

     fwprintf(stderr, L"Username: %s password: %s.\n", argv[2], argv[3]);

   }

   // Otherwise, print the system error.

   else

      fprintf(stderr, "A system error has occurred: %d\n", nStatus);

 

   return 0;

}

 

A sample output:

E:\myproject\win32prog\Debug>myadduser

Usage: myadduser ServerName UserName Password.

 

E:\myproject\win32prog\Debug> myadduser mypersonal

Usage: myadduser ServerName UserName Password.

 

E:\myproject\win32prog\Debug> myadduser mypersonal myuser#1 12345678

myuser#1 user has been successfully added on mypersonal machine.

Username: myuser#1 password: 12345678.

 

E:\myproject\win32prog\Debug>

 

Then use the Computer Management snap in (Start Program Administrator Tools Computer Management) to verify the user account creation.

 

Add user account to a system

 

Figure 3: myuser#1 user account has been created.

 

Verify myuser#1 properties.  Other settings are default and set by system.

 

Add user verification

 

Figure 4: Default setting for myuser#1 user.

 

More verification

 

Figure 5: myuser#1 user not a member of any group.

 

It seems that this user account is still not usable because it is not a Users group’s member.  You can verify this by logging off and there shouldn’t be myuser#1 user at the login screen.  We will correct this and other properties of this user account later on.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

 

  1. Check the best selling C, C++ and Windows books at Amazon.com.

  2. Microsoft Visual C++, online MSDN.

  3. MSDN library.

  4. For Multibytes, Unicode characters and Localization please refer to Locale, wide characters & Unicode (Story) and Windows users & groups programming tutorials (Implementation).

  5. Structure, enum, union and typedef story can be found C/C++ struct, enum, union & typedef.

  6. Notation used in MSDN is Hungarian Notation instead of CamelCase and is discussed Windows programming notations.

  7. Windows data type information is in Windows data types used in Win32 programming.

 

 

 

 

 

 

|< Windows Access Control Programming 15 | Main | Windows User Accounts & Groups Programming 2 >| Site Index | Download |