Locally logged-on users can easily change their password through the Windows interface. When you're using Integrated Windows, Windows NT Challenge/Response, or Digest authentication, a user must log on to a system that supports Microsoft Internet Explorer (IE) and the authentication method. The user can use standard Windows utilities to change a password directly through the Windows interface during the current logon session. Users who are disconnected from the network part of the time can change their passwords during their next logon session.
However, when you're using Basic authentication or you need to implement a Web-browser-based change-password interface for users of an OS authentication method, you have no easy way for users to change their password. In these situations, Microsoft Active Directory Service Interfaces (ADSI) and some straightforward code let you give users an interface for password change.
Before you tackle password changes, you need to understand the authentication methods that Windows 2000 and NT 4.0 use and select the one that is appropriate for your situation. NT 4.0 can use Anonymous access, which lets anyone use a Web application or Web site. Microsoft IIS automatically uses the IUSR_MachineName account to log an Anonymous user on to the server. If you turn off Anonymous access, NT 4.0 can use Basic authentication, which prompts the user for a username and password when the user first visits a site or application. Then the OS verifies the username and password against the local user account or domain database.
Win2K and NT 4.0 can use another authentication option, which goes by a different name in each system: Integrated Windows security in Win2K and NT Challenge/Response in NT 4.0. Both mechanisms operate similarly to Basic authentication, but instead of forcing the user to enter a username and password, Integrated Windows security and NT Challenge/Response take the username and password from the OS. Then, IE uses the Web server's security database (e.g., the SAM, Active Directory—AD) to verify the username and password.
Win2K supports Digest authentication, which works only with Win2K domain controllers (DCs). Digest authentication takes the username and password from the credentials that the user supplied to the browser and verifies them against the user account database that the Web server uses.
You can also authenticate users against a database table, effectively creating your own authentication system. However, if you use this method, you lose Win2K or NT 4.0 security features that are available if the OS authenticates users. For example, you can't use ACLs or other OS security features that require authenticated users.
Choose an authentication method that fits your security goals. If you need file security, use Basic authentication, Integrated Windows security, NT Challenge/ Response, or—in Win2K—Digest authentication. If you just need application security, create an authentication system.
Using the IADsUser Interface
ADSI gives you a set of directory service interfaces for managing network resources, and you can use the ADSI IADsUser interface and script to change a user's password. I created two Active Server Pages (ASP) pages that demonstrate this procedure. Figure 1 shows the first page, ChangePasswordEntry.asp, and Listing 1 shows the script for the page.
ChangePasswordEntry.asp is an HTML file that gathers three crucial pieces of information for changing a user's password: username, existing password, and new password. After a user enters the information and clicks Submit, the script passes control to Change Password1.asp. This file contains the code, which Listing 2 shows, that actually changes the user's password.
The code in Listing 2 works in Win2K and NT 4.0 for usernames that are stored locally and aren't part of a domain or AD. Callout A in Listing 2 dimensions (i.e., creates) several variables that Change Password1.asp uses. Dimensioning makes code more readable for developers. You must use Option Explicit in code to force the dimensioning of all variables.
The code in Listing 2's callout B uses Xname and password values from ChangePasswordEntry.asp and place these values in the corresponding variables that callout A created. The If statement at callout B checks whether the sUser variable is blank. If it's blank, the code sends control back to ChangePasswordEntry.asp.
The code at callout C starts Change Password1.asp's real work. When you use ADSI, you must communicate with an ADSI provider that manages the resource you're connecting to. ChangePassword1 .asp uses the WinNT provider, which also works with Win2K when the Web server is using local user accounts. Callout C's first line builds the connection string and stores it in the sConnectString variable to begin the process of connecting to the WinNT provider. The connection string consists of the provider name (WinNT), separators (://), the computer name (bigboat), and a closing separator (/). Then callout C appends the username and ",user" to the string. The username represents the user object of the WinNT provider. The user object represents a user account.
After callout C's sConnectString statement builds the connection string, the Response.Write statement displays the string by sending it to the HTTP stream. Response.Write statements are great for debugging. After you've tested the code, you can precede them with one quotation mark (') so that they won't be executed. The Set oUser statement at callout C binds the oUser variable to an instance of the user object that represents the user specified in the connection string.
The two Response.Write statements that follow callout C help you debug the sample code because they let you inspect the username and password that Basic authentication provided to the server. They use the ServerVariables collection of the ASP Request object. The first line uses the LOGON_USER variable, which represents the currently logged-on user. You could also use the REMOTE_USER variable to return the user account. The second line returns the user's password from the AUTH_ PASSWORD variable if the user is logged on with Basic authentication.
The line that changes the password is
at callout D. The first parameter to ChangePassword is the user's current password (sPassword). The second parameter is the user's new password (sNewPassword). After the script has finished running, the new password will take effect.
Figure 2, page 123, shows the Change PasswordEntry.asp form in action. In Figure 2, I've entered a username, current password, and new password. When I click Submit, ChangePassword1.asp executes. Figure 3 shows the results that the Response.Write statements return. If I enter an incorrect existing password, ADSI notifies me that the password isn't correct, as Figure 4 shows. ADSI won't let users without the proper credentials change their passwords.
When you use ADSI or any other technique to change a user's password through a Web interface, you need to set up the pages to run under HTTP over Secure Sockets Layer (HTTPS). HTTPS encrypts the user's account information so that it doesn't transmit in clear text.
Working with AD and NT Domains
ChangePasswordEntry.asp and ChangePassword1.asp contain few lines of code but provide the Web interface to let users change their passwords over the Web or an intranet. The code works if the server runs Win2K or NT 4.0 with users whose accounts are stored on the local server. However, the code doesn't work if the Web server is running Win2K AD or participates in an NT domain.
To make ChangePassword1.asp work for user accounts stored in Win2K AD, you need to use the Lightweight Directory Access Protocol (LDAP) provider for ADSI instead of the WinNT provider. The LDAP provider lets you perform tasks on a server that is part of an AD domain. To use the LDAP provider, you simply change the connection string in ChangePassword1.asp to
sUser & ",OU=users, " &
The changes adapt the connection string to the AD interface. Instead of just passing positional parameters, as the WinNT provider does, the LDAP provider code uses AD identifiers such as CN for common name and OU for organizational unit. After the GetObject function executes for the connection string, you can work with the LDAP provider just as you would the WinNT provider. Aside from the changes to the connection string, the code remains the same whether you use the WinNT provider or the LDAP provider.
For the ChangePassword1.asp code to work in an NT 4.0 domain, the connection string needs to specify the domain name instead of the computer name. For example,
"MyDomain/" & sUser & ",user"
sets the connect string to point to the user object in MyDomain instead of the computer running the Web server. As you can see, the beauty of ADSI is that it lets you use virtually the same code to access user account objects on either Win2K or NT 4.0.
You'll notice differences among various ADSI providers' objects and interfaces. Each provider's creator can implement unique objects and interfaces, which are pertinent to the type of resource that the provider accesses. The AD and WinNT providers have similar interfaces because they both expose the IADsUser interface. The WinNT implementation of the interface maps to user accounts in the SAM. Table 1 shows the user properties that the IADsUser interface lets you set or change.
To see the differences between various providers' interfaces, you can study the LDAP provider's IADsUser interface. The interface lets you set or change the ADSI properties that you see in Table 2. Table 2 also shows how ADSI proper-ties map to AD properties. For more information about ADSI properties, see the Microsoft Developer Network (MSDN) Online Library article "IADs User" (http://msdn.microsoft.com/library/ default.asp?url=/library/psdk/adsi/if_ pers_488i.htm).
ADSI is a powerful programming interface for Win2K, NT 4.0, and other systems that providers can expose. You can use ADSI to let users change passwords through a Web interface, and you can use ADSI to maintain many other properties of AD or NT 4.0.