Microsoft Identity Integration Server 2003 Developer Reference

Example: Setting Passwords

This topic contains code examples to set passwords on connected data sources using the WMI Provider.

Note  For clarity, the passwords are exposed in the example. We recommend that you modify the examples so that the passwords are encrypted and not exposed.

[VBScript]

The following Visual Basic Scripting Edition (VBScript) example changes the password on an ADAM, Sun, or Netscape data source using the WMI provider. The example has the following functions:

If you saved this script to a file called Setpassword.vbs, the following is the syntax for the script: setpassword.vbs SearchDomain SearchUser NewPassword.

The script requires the following arguments if this script is run from the MIIS server using the account that is a member of the MIISPasswordSet security group:

An example of this script would be:

setpassword.vbs fabrikam, jeffsmith, NewPassword

If the script is run remotely, you must also supply the following arguments:

setpassword.vbs SearchDomain SearchUser NewPassword MIIS_AccountName MIIS_Password MIIS_MachineName

An example of this script would be:

setpassword.vbs fabrikam, jeffsmith, NewPassword, loripenor, MIISAdminPassword, MIISServer
Option Explicit

On Error resume next

Dim MIIS_AccountName

Dim MIIS_Password

Dim MIIS_MachineName

Dim SearchDomain

Dim SearchUser

Dim NewPassword

Dim Service

Dim objLocator 

Dim WMIQuery

Dim CsObjects

Dim CSObject

Dim CSObjectMVGUID

Dim RelatedCSObjects

Dim RelatedCSObject

Dim MVQuery

Dim LenMV

Dim MAQuery

Dim MAObjects

Dim MAObject

Dim Status

Const MIIS_WMI_Namespace		= "root\MicrosoftIdentityIntegrationServer"

Const PktPrivacy				= 6

Const wbemAuthenticationLevelPkt= 6

Const impersonate			 = 3

' Check that you have the correct number of options.
If WScript.Arguments.Count <> 3 and WScript.Arguments.Count <> 6 Then
   
	WScript.Echo "Missing Arguments"

	WScript.Quit(1)

End If

SearchDomain = WScript.Arguments.Item(0)

SearchUser = WScript.Arguments.Item(1)

NewPassword = WScript.Arguments.Item(2)

If WScript.Arguments.Count = 6 then

	MIIS_AccountName = WScript.Arguments.Item(3)

	MIIS_Password = WScript.Arguments.Item(4)

	MIIS_MachineName = WScript.Arguments.Item(5)

End If

If MIIS_AccountName = "" then

   Set Service = GetObject("WinMgmts:{impersonationLevel=impersonate,authenticationLevel=PktPrivacy}!" & MIIS_WMI_Namespace)

Else

   Set objLocator = CreateObject("WbemScripting.SWbemLocator")

   objLocator.Security_.ImpersonationLevel = impersonate

   objLocator.Security_.AuthenticationLevel = wbemAuthenticationLevelPkt

   Set Service = objLocator.ConnectServer(MIIS_MachineName , MIIS_WMI_Namespace)',  MIIS_AccountName, MIIS_Password)

End if

If Err.Number <> 0 Then ErrorHandler("ERROR: " & Err.Description)

FindCSObject

If CsObjects.Count = 0 Then 

	ErrorHandler("Unable to locate " & SearchDomain & "\" & SearchUser & ".")

End If

If IsNull(CSObject.MvGuid) Then 

	ErrorHandler("The connector space object is a disconnector. The password was not set.")

End If

Wscript.Echo ""

Wscript.Echo "Located CS Object for " & SearchDomain & "\" & SearchUser & "."

Wscript.Echo "Locating related connectors..."

MVQuery = "Select * from MIIS_CSObject where mvguid='" & CSObject.MVGUID & "'"

Set RelatedCSObjects = Service.ExecQuery(MVQuery)

If RelatedCSObjects.Count = 0 Then

	ErrorHandler("No related CS objects found for " & SearchDomain & "\" & SearchUser & ".")

End If

Wscript.Echo "Located " & RelatedCSObjects.Count & " connectors for MV Object."

Wscript.Echo "Locating MA(s) for connected CS object(s)..."

Wscript.Echo ""

For Each RelatedCSObject in RelatedCSObjects

	If (LCase(RelatedCSObject.ObjectType) <> "inetorgperson") and (LCase(RelatedCSObject.ObjectType) <> "user") then
	
		Wscript.Echo "Wrong object type detected, Skipping " & RelatedCSObject.MaName & "'s CS object: " & LCase(RelatedCSObject.ObjectType)
		
			Wscript.Echo "DN	 : " & RelatedCSObject.Dn
	
		Else
	
			GetMATypeFromCSObject

			If IsNull(MAObject) Then
		
				Wscript.Echo "Unable to retrieve the MA " & RelatedCSObject.MaName & "'s for CS Object:"
		
				Wscript.Echo "DN	 : " & RelatedCSObject.Dn
			
				Wscript.Echo "MA Type: Unknown"
		
			Else
				If MAObject.Type <> "Active Directory Application Mode (ADAM)" and MAObject.Type <> "Sun and Netscape directory servers" Then
					
						Wscript.Echo "Wrong MA type detected, Skipping " & RelatedCSObject.MaName & "'s CS Object:"
					
						Wscript.Echo "DN	 : " & RelatedCSObject.Dn
					
						Wscript.Echo "MA Type: " & MAObject.Type
			
				Else
					
						Wscript.Echo "Updating password for " & RelatedCSObject.MaName & "'s CS Object:"
					
						Wscript.Echo "DN	 : " & RelatedCSObject.Dn
					
						Wscript.Echo "MA Type: " & MAObject.Type

						Status = RelatedCSObject.SetPassword(newPassword)

						If Status = "success" then
					
							Wscript.Echo "Result : Successful."
					
						Else
					
							Wscript.Echo "Result : Failed."
					
							Wscript.Echo "Status : " & Status
					
						End If
					
				End If

			End If

	End If

   Wscript.Echo ""
   
Next

Function GetMATypeFromCSObject()

	MAQuery = "Select * from MIIS_ManagementAgent where guid='" + RelatedCSObject.MaGuid + "'" 

	Set MAObjects = Service.ExecQuery(MAQuery)

	'Move to the first object in the MAObjects Collection and Exit
	For Each MAObject in MAObjects

		Exit for

	Next

End Function

Function FindCSObject()

	WMIQuery = "Select * from MIIS_CSObject where " + _
				"(Domain='" + searchDomain + "' and Account='" + searchUser + "') or " + _
				"(FullyQualifiedDomain='" + searchDomain + "' and Account='" + searchUser + "') or " + _
				"(Domain='" + searchDomain + "' and UserPrincipalName='" + searchUser + "') or " + _
				"(FullyQualifiedDomain='" + searchDomain + "' and UserPrincipalName='" + searchUser + "')"

	Set CsObjects = Service.ExecQuery(WMIQuery)

	'Move to the first object in the CsObjects Collection and Exit
	For Each CsObject in CsObjects

		Exit for

	Next
   
End Function

Sub ErrorHandler (ErrorMessage)

	WScript.Echo ErrorMessage

	WScript.Quit(1)

End Sub

[C#]

The following C# example changes the password on an ADAM, Sun, or Netscape data source using System.Management namespace to invoke the WMI provider. The example has to be run by an account that is a member of the MIISPasswordSet security group.

The example has the following functions:

using System;
using System.Management;

namespace MIISSamples
{
  public class SetPasswordExample
  {
	// These constants assume that this application is on the same server
	// as MIIS. If this program is run from a separate computer, change
	// the following constants.  

	const string MIIS_AccountName  = null; // MIISPasswordSet Group member
	const string MIIS_Password	 = null; // Password for above member
	const string MIIS_MachineName  = null; // MIIS Server name

	// WMI namespace path for the MIIS server.
		const string MIIS_WMI_Namespace = @"root\MicrosoftIdentityIntegrationServer";

	static void Main( 
					string searchDomain, 
					string searchUser, 
					string newPassword
					)
	{ 
	ManagementScope WMInamespace;

	// Create the WMI management scope object to connect to the
	// MIIS server. If the password for the MIISPasswordSet group
	// member is null, then MIIS is installed on the local machine.
	// Enable the PacketPrivacy Connection Option to ensure that all
	// communication is encrypted.

	if ( MIIS_Password != null )
	{
		ConnectionOptions connOpt = new ConnectionOptions();
		connOpt.Username = MIIS_AccountName;
		connOpt.Password = MIIS_Password;
		connOpt.Authentication = AuthenticationLevel.PacketPrivacy;
		WMInamespace = new ManagementScope(
											String.Format(@"\\{0}\{1}",
											MIIS_MachineName,
											MIIS_WMI_Namespace),
											connOpt
										 );
}
		
	else
	{
		ConnectionOptions connOpt = new ConnectionOptions();
		connOpt.Authentication = AuthenticationLevel.PacketPrivacy;
		WMInamespace = new ManagementScope(MIIS_WMI_Namespace,connOpt);
}

	try
	{
		// Locate the CSobject corresponding to the domain and name using 
		// an internal function. Display an error message if the object
		// does not exist.

		ManagementObject CSobject = FindCSObject(
												WMInamespace,
												searchDomain,
												searchUser
												 );
		if ( CSobject == null )
		{
		Console.WriteLine(
							 "Unable to find the CS object corresponding to: {0}\\{1}.",
							 searchDomain,
							 searchUser
							);
		return;
	}
		Console.WriteLine();
		Console.WriteLine(
						 "Located CS Object for {0}\\{1}.",
							searchDomain,
							searchUser
						);

		// If the CSobject is a disconnector object, then the
		// program cannot change the password.

		if( CSobject["mvGuid"] == null )
		{
		Console.WriteLine( "The connector space object is a disconnector." );
		Console.WriteLine( "The password was not set.");
		return;
	}

		// Locate all the other CSobjects connected to that MVobject.

		Console.WriteLine("Locating related connectors.");
		string CSobjGUID = CSobject["mvGuid"].ToString();
		string queryString = String.Format( 
											"Select * from MIIS_CSObject where mvGuid ='{0}'",
											 CSobjGUID													 
										 );
		ObjectQuery MVQuery = new ObjectQuery( queryString);
		ManagementObjectSearcher MVSearcher = new ManagementObjectSearcher(WMInamespace,MVQuery);
		ManagementObjectCollection relatedCSObjects = MVSearcher.Get();
		int relCount = GetManagementObjectCount(relatedCSObjects);
		Console.WriteLine("Found {0} connectors for MV Object.", relCount);

		// Enumerate through each CSObject in the collection.

		Console.WriteLine("Locating MA(s) for connected CS object(s)...");

		foreach (ManagementObject Connector in relatedCSObjects )
		{
		string Dn		 = Connector["Dn"].ToString();
		string MaName	 = Connector["MaName"].ToString();
		string ObjectType = Connector["ObjectType"].ToString().ToLower();
		string MaType;

		Console.WriteLine();

		// Look for CSobjects of type 'inetorgperson' or 'user'.

		if ( !(ObjectType.Equals("inetorgperson") || ObjectType.Equals("user")) )
		{
			Console.WriteLine(
							 "Wrong object type detected, Skipping {0}'s CS object:",
								MaName
							);
			Console.WriteLine("DN	 : {0}.",Dn);
			continue;
	}

		// In this example, we only want to change passwords
		// for ADAM, Sun, or Netscape connected directories.

		MaType = GetMATypeFromCSObject(WMInamespace,Connector);
		if( !(MaType.Equals("Active Directory Application Mode (ADAM)") ||
		MaType.Equals("Sun and Netscape directory servers")) )
		{
			Console.WriteLine("Wrong MA type detected, Skipping {0}'s CS object:",MaName);
			Console.WriteLine("DN	 : {0}.",Dn);
			Console.WriteLine("MA Type: {0}.",MaType);
			continue;
	}				
		// Set the password.

		Console.WriteLine("Updating password for {0}'s CS object:", MaName);
		Console.WriteLine("DN	 : {0}.",Dn);
		Console.WriteLine("MA Type: {0}.",MaType);

		string status = (string)Connector.InvokeMethod(
														"SetPassword", 
														 new string[] { newPassword } 
														 );
		 if ( status.Equals("success") )
		 {
			 Console.WriteLine("Result : Successful.");
		 }
		 else
		 {
			 Console.WriteLine("Result : Failed.");
			 Console.WriteLine("Status : {0}",status);
		 }
	}
}
		
	catch(ManagementException mgmtExp)
	{
		Console.WriteLine("System.Management Error: {0}.",mgmtExp.Message);
}
}
	
	// This internal function returns a ManagementObject object that 
	// represents the CSObject with the specified domain and username.
	static ManagementObject FindCSObject(
										ManagementScope WMInamespace,
										string searchDomain,
										string searchUser
										 )
	{
		ManagementObject CSObjectFound = null;

		// Build a WMI query string for our search.

		string wmiQuery = String.Format(
			
				"Select * from MIIS_CSObject where (Domain='{0}' and Account='{1}') or " +
			
				"(FullyQualifiedDomain='{0}' and Account='{1}') or (Domain='{0}' " +
			
				"and UserPrincipalName='{1}') or (FullyQualifiedDomain='{0}' and UserPrincipalName='{1}')",
			
				searchDomain,
			
				searchUser
			
				);

			// Run the WMI query.
			ObjectQuery query = new ObjectQuery(wmiQuery);
		
			wmiQuery = null;
		
			ManagementObjectSearcher CSsearcher = new ManagementObjectSearcher(WMInamespace,query);
		
			ManagementObjectCollection CSobjects = CSsearcher.Get();

			// The search returned an enumeration, but we only expect to get back a a single
			// object. Return the first object from the enumeration.
			try
			{
			ManagementObjectCollection.ManagementObjectEnumerator Enum = CSobjects.GetEnumerator();
			Enum.MoveNext();
			CSObjectFound = (ManagementObject)Enum.Current;
			Enum.Dispose();
		}
		
			catch
			{
		
				// Handle exceptions for the enumeration here.
		
		}

			return CSObjectFound;
	}

		// Returns the type of the MA that is associated with the specified CSobject.
		static string GetMATypeFromCSObject( 
											 ManagementScope WMInamespace,
											 
											 ManagementObject CSObject
											 
										 )
		{
	
			string MAGuid = CSObject["maGuid"].ToString();
		
			string queryString = String.Format( "Select * from MIIS_ManagementAgent where guid = '{0}'",
		
												MAGuid
											
											);
		
			ObjectQuery MAQuery = new ObjectQuery( queryString );

			ManagementObjectSearcher MASearcher = new ManagementObjectSearcher(WMInamespace,MAQuery);
					
			ManagementObjectCollection MAObjects = MASearcher.Get();

			ManagementObjectCollection.ManagementObjectEnumerator Enum = MAObjects.GetEnumerator();
		
			Enum.MoveNext();
		
			ManagementObject MAObject = ( ManagementObject)Enum.Current;
		
			Enum.Dispose();

			return MAObject["Type"].ToString();
	}

		//
		// This helper routine 
		// explicitly enumerates the ManagementObjectCollection object after the count property is read.
		//
		static int GetManagementObjectCount(ManagementObjectCollection Obj)
		{
			ManagementObjectCollection.ManagementObjectEnumerator Enumerator = Obj.GetEnumerator();
		
			int count = 0;

			while ( Enumerator.MoveNext() )
		
				count++;

			return count;
		
	}
}
}

[Visual Basic .NET]

The following Visual Basic .NET example changes the password on an ADAM, Sun, or Netscape data source using System.Management namespace to invoke the WMI provider. The example has to be run by an account that is a member of the MIISPasswordSet security group.

The example has the following functions:

Option Explicit On 

Imports System

Imports System.Management

Public Class SetPasswordExample

	' These constants assume that this application is on the same server
	' as MIIS. If this program is run from a seperate computer, change
	' the following constants.  

	' MIISPasswordSet Group member
	Private Const MIIS_AccountName As String = Nothing

	' Password for above account
	Private Const MIIS_Password As String = Nothing

	' MIIS Server name
	Private Const MIIS_MachineName As String = Nothing

	' WMI namespace path for the MIIS server.
	Private Const MIIS_WMI_Namespace As String = "root\MicrosoftIdentityIntegrationServer"


	Shared Sub Main()

		' Pass the domain name, user name, and new password to the method
		' that will change the password.
		SetNewPassword("MIISServer", "PCUser2", "ABC!1234")

	End Sub

	' This method sets the password.
	Private Shared Sub SetNewPassword(ByVal searchDomain As String, _
									ByVal searchUser As String, _
									ByVal newPassword As String)

		Dim WMInamespace As ManagementScope

		' Create the WMI management scope object to connect to the
		' MIIS server. If the password for the MIISPasswordSet group
		' member is null, then MIIS is installed on the local machine.
		' Enable the PacketPrivacy Connection Option to ensure all
		' communication is encrypted.
		If Not (MIIS_Password Is Nothing) Then

			Dim connOpt As New ConnectionOptions

			connOpt.Username = MIIS_AccountName

			connOpt.Password = MIIS_Password

			connOpt.Authentication = AuthenticationLevel.PacketPrivacy

			WMInamespace = New ManagementScope(String.Format("\\{0}\{1}", _
															MIIS_MachineName, _
															MIIS_WMI_Namespace), connOpt)

		Else

			Dim connOpt As New ConnectionOptions

			connOpt.Authentication = AuthenticationLevel.PacketPrivacy

			WMInamespace = New ManagementScope(MIIS_WMI_Namespace, connOpt)

		End If

		Try
			' Locate the CSobject corresponding to the domain and name using 
			' an internal function. Display an error message if the object
			' does not exist.
			Dim CSobject As ManagementObject = FindCSObject(WMInamespace, searchDomain, searchUser)

			If CSobject Is Nothing Then

				Console.WriteLine("Unable to find the CS object corresponding to: {0}\{1}.", _
								 searchDomain, searchUser)

				Return
			End If

			Console.WriteLine()

			Console.WriteLine("Located CS Object for {0}\{1}.", searchDomain, searchUser)

			' If the CSobject is a disconnector object, then the
			' program cannot change the password.
			If CSobject("mvGuid") Is Nothing Then

				Console.WriteLine("The connector space object is a disconnector.")

				Console.WriteLine("The password was not set.")

				Return

			End If

			' Locate all the other CSobjects connected to that MVobject.
			Console.WriteLine("Locating related connectors.")

			Dim CSobjGUID As String = CSobject("mvGuid").ToString()

			Dim queryString As String = String.Format("Select * from MIIS_CSObject where mvGuid ='{0}'", _
													 CSobjGUID)

			Dim MVQuery As New ObjectQuery(queryString)

			Dim MVSearcher As New ManagementObjectSearcher(WMInamespace, MVQuery)

			Dim relatedCSObjects As ManagementObjectCollection = MVSearcher.Get()

			Dim relCount As Integer = GetManagementObjectCount(relatedCSObjects)

			Console.WriteLine("Found {0} connectors for MV Object.", relCount)

			' Enumerate through each CSObject in the collection.
			Console.WriteLine("Locating MA(s) for connected CS object(s)...")

			Dim Connector As ManagementObject

			For Each Connector In relatedCSObjects

				Dim Dn As String = Connector("Dn").ToString()

				Dim MaName As String = Connector("MaName").ToString()

				Dim ObjectType As String = Connector("ObjectType").ToString().ToLower()

				Dim MaType As String

				Console.WriteLine()

				' Look for CSobjects of type 'inetorgperson' or 'user'.
				If Not (ObjectType.Equals("inetorgperson") OrElse ObjectType.Equals("user")) Then

					Console.WriteLine("Wrong object type detected, Skipping {0}'s CS object:", MaName)

					Console.WriteLine("DN	 : {0}.", Dn)

					GoTo ContinueForEach1

				End If

				' In this example, we only want to change passwords
				' for ADAM or Sun and Netscape connected directories.
				MaType = GetMATypeFromCSObject(WMInamespace, Connector)

				If Not (MaType.Equals("Active Directory Application Mode (ADAM)") OrElse _
						MaType.Equals("Sun and Netscape directory servers")) Then

					Console.WriteLine("Wrong MA type detected, Skipping {0}'s CS object:", MaName)

					Console.WriteLine("DN	 : {0}.", Dn)

					Console.WriteLine("MA Type: {0}.", MaType)

					GoTo ContinueForEach1

				End If

				' Set the password.
				Console.WriteLine("Updating password for {0}'s CS object:", MaName)

				Console.WriteLine("DN	 : {0}.", Dn)

				Console.WriteLine("MA Type: {0}.", MaType)

				Dim status As String = CStr(Connector.InvokeMethod("SetPassword", _
											New String() {newPassword}))

				If status.Equals("success") Then

					Console.WriteLine("Result : Successful.")

				Else

					Console.WriteLine("Result : Failed.")

					Console.WriteLine("Status : {0}", status)

				End If

ContinueForEach1:
			Next Connector

		Catch mgmtExp As ManagementException

			Console.WriteLine("System.Management Error: {0}.", mgmtExp.Message)

		End Try

	End Sub

	' This internal function returns a ManagementObject object that 
	' represents the CSObject with the specified domain and username.
	Shared Function FindCSObject(ByVal WMInamespace As ManagementScope, _
								 ByVal searchDomain As String, _
								 ByVal searchUser As String) As ManagementObject

		Dim CSObjectFound As ManagementObject = Nothing

		' Build a WMI query string for our search.
		Dim wmiQuery As String = String.Format("Select * from MIIS_CSObject where (Domain='{0}' and Account='{1}') or " + "(FullyQualifiedDomain='{0}' and Account='{1}') or (Domain='{0}' " + "and UserPrincipalName='{1}') or (FullyQualifiedDomain='{0}' and UserPrincipalName='{1}')", searchDomain, searchUser)

		' Run the WMI query.
		Dim query As New ObjectQuery(wmiQuery)

		wmiQuery = Nothing

		Dim CSsearcher As New ManagementObjectSearcher(WMInamespace, query)

		Dim CSobjects As ManagementObjectCollection = CSsearcher.Get()

		' The search returned an enumeration, but we only expect to get back a a single
		' object. Return the first object from the enumeration.
		Try

			Dim enumObject As ManagementObjectCollection.ManagementObjectEnumerator = CSobjects.GetEnumerator()

			enumObject.MoveNext()

			CSObjectFound = CType(enumObject.Current, ManagementObject)

			enumObject.Dispose()

		Catch

		' Handle exceptions for the enumeration block here.

		End Try

		Return CSObjectFound

	End Function 'FindCSObject

	' Returns the type of the MA associated with the specified CSobject.
	Shared Function GetMATypeFromCSObject(ByVal WMInamespace As ManagementScope, _
										ByVal CSObject As ManagementObject) As String

		Dim MAGuid As String = CSObject("maGuid").ToString()

		Dim queryString As String

		queryString = String.Format("Select * from MIIS_ManagementAgent where guid = '{0}'", MAGuid)

		Dim MAQuery As New ObjectQuery(queryString)

		Dim MASearcher As New ManagementObjectSearcher(WMInamespace, MAQuery)

		Dim MAObjects As ManagementObjectCollection = MASearcher.Get()

		Dim objectEnum As ManagementObjectCollection.ManagementObjectEnumerator = MAObjects.GetEnumerator()

		objectEnum.MoveNext()

		Dim MAObject As ManagementObject = CType(objectEnum.Current, ManagementObject)

		objectEnum.Dispose()

		Return MAObject("Type").ToString()

	End Function

	'
	' This helper routine works explicitly enumerates the ManagementObjectCollection after the Count property has been read.  
	'
	Shared Function GetManagementObjectCount(ByVal Obj As ManagementObjectCollection) As Integer

		Dim Enumerator As ManagementObjectCollection.ManagementObjectEnumerator = Obj.GetEnumerator()

		Dim count As Integer = 0

		While Enumerator.MoveNext()

			count += 1

		End While

		Return count

	End Function

End Class