Applicaiton Security, Part 13


Manipulating ADAM programmatically can be a little challenging.  First, the documentation that is installed with ADAM does not cover its programming interfaces.  However, that documentation can be found within MSDN, under Networking and Directory Services.  Second, while that documentation provides samples in VBScript, Visual Basic and C#, I could only get the VBScript code to work and translated that into C# code myself.  When manipulating ADAM programmatically, one uses the same tools as one would use to manipulate Active Directory, which brings us to the last of our challenges.  The .NET Framework Class Library includes a DirectoryServices namespace for working with entries in a Directory Service, but that namespace has very limited facilities, which is why I often refer to it as the ghetto of the .NET Framework.  The most important class in the namespace, the DirectoryEntry class, has a property called NativeObject that allows one to work with the directory using the COM Active Directory Service Interface library. 


 


Here, then, is the code for creating the application directory partition for TaskVision II within ADAM, and for creating a container for users within it. 


 



using System;


using System.Configuration;


using System.DirectoryServices;


namespace Microsoft.DeveloperAndPlatformEvangelism.Demonstrations.TaskVisionII.Utility


{



public class CConfigurator


{


private const string c_sConfigurationSection_Credentials = @"Credentials";


private const string c_sConfigurationSection_ADAMInstance = @"ADAMInstance";


private const string c_sKey_Credentials_UserName = @"UserName";


private const string c_sKey_Credentials_Password = @"Password";


private const string c_sKey_ADAMInstance_ADsPath = @"ADsPath";


private const string c_sKey_ADAMInstance_Server = @"Server";


private const string c_sKey_ADAMInstance_Port = @"Port";


private const string c_sKey_ADAMInstance_Country = @"Country";


private const string c_sKey_ADAMInstance_ApplicationDirectoryPartition = @"ApplicationDirectoryPartition";


private const string c_sKey_ADAMInstance_ApplicationDirectoryPartitionDescription = @"ApplicationDirectoryPartitionDescription";


private const string c_sProvider = "LDAP";


private const string c_sMessage_Exception_Unknown = @"Unknown exception.";


private const string c_sMessage_Exception_Known = @"Exception: ";


[FlagsAttribute]


private enum DIRECTORY_SERVICE_CONTAINER_PROPERTIES


{


HEAD = 1,


WRITABLE = 4


};


 


 


[STAThread]


static void Main()


{


try


{


//Read configuration data


System.Collections.Hashtable rConfigurationSection = null;



rConfigurationSection = (System.Collections.Hashtable)System.Configuration.ConfigurationSettings.GetConfig(CConfigurator.c_sConfigurationSection_Credentials);


string sUserName = (string)rConfigurationSection[c_sKey_Credentials_UserName];


string sPassword = (string)rConfigurationSection[c_sKey_Credentials_Password];


rConfigurationSection = (System.Collections.Hashtable)System.Configuration.ConfigurationSettings.GetConfig(CConfigurator.c_sConfigurationSection_ADAMInstance);


string sServer = (string)rConfigurationSection[CConfigurator.c_sKey_ADAMInstance_Server];


string sPort = (string)rConfigurationSection[CConfigurator.c_sKey_ADAMInstance_Port];


string sCountry = (string)rConfigurationSection[CConfigurator.c_sKey_ADAMInstance_Country];


string sADsPath = string.Format("{0}://{1}:{2}/C={3}",CConfigurator.c_sProvider,sServer,sPort,sCountry);


string sApplicationDirectoryPartition = (string)rConfigurationSection[CConfigurator.c_sKey_ADAMInstance_ApplicationDirectoryPartition];


string sADsPath_ApplicationDirectoryPartition = string.Format("{0}://{1}:{2}/O={4},C={3}",CConfigurator.c_sProvider,sServer,sPort,sCountry,sApplicationDirectoryPartition);


string sApplicationDirectoryPartitionDescription = (string)rConfigurationSection[CConfigurator.c_sKey_ADAMInstance_ApplicationDirectoryPartitionDescription];


bool fExists = true;


//Deterimine if the application directory partition already exists.


try


{


DirectoryEntry.Exists(sADsPath_ApplicationDirectoryPartition);


}


catch(Exception)


{


fExists = false;


}


if(!(fExists))


{


//Create the application directory partition.


ActiveDs.IADsOpenDSObject rOpenObject = (ActiveDs.IADsOpenDSObject)new DirectoryEntry(string.Format("{0}:",CConfigurator.c_sProvider)).NativeObject;


ActiveDs.IADsContainer rContainer = (ActiveDs.IADsContainer)rOpenObject.OpenDSObject(sADsPath,sUserName,sPassword,(int)ActiveDs.ADS_AUTHENTICATION_ENUM.ADS_USE_DELEGATION|(int)ActiveDs.ADS_AUTHENTICATION_ENUM.ADS_FAST_BIND|(int)ActiveDs.ADS_AUTHENTICATION_ENUM.ADS_SECURE_AUTHENTICATION);


ActiveDs.IADs rObject = (ActiveDs.IADs)rContainer.Create("organization",string.Format("O={0}",sApplicationDirectoryPartition));


rObject.Put("instanceType",DIRECTORY_SERVICE_CONTAINER_PROPERTIES.HEAD|DIRECTORY_SERVICE_CONTAINER_PROPERTIES.WRITABLE);


rObject.Put("description",sApplicationDirectoryPartitionDescription);


rObject.SetInfo();


//Create the container for users within that partition.


rContainer = (ActiveDs.IADsContainer)rOpenObject.OpenDSObject(sADsPath_ApplicationDirectoryPartition,sUserName,sPassword,(int)ActiveDs.ADS_AUTHENTICATION_ENUM.ADS_USE_DELEGATION|(int)ActiveDs.ADS_AUTHENTICATION_ENUM.ADS_FAST_BIND|(int)ActiveDs.ADS_AUTHENTICATION_ENUM.ADS_SECURE_AUTHENTICATION);


rObject = (ActiveDs.IADs)rContainer.Create("container",string.Format("CN={0}","Users"));


rObject.SetInfo();


}



}


catch(Exception rException)


{


System.Console.WriteLine(((rException.Message == null)||(rException.Message == string.Empty))?CConfigurator.c_sMessage_Exception_Unknown:string.Concat(CConfigurator.c_sMessage_Exception_Known,rException.Message));


}


return;



}


}


}


 


 


The app.config file:


 


<?xml version="1.0" encoding="utf-8" ?>


<configuration>


<configSections>


<section name="Credentials"


type="System.Configuration.DictionarySectionHandler"


/>


<section name="ADAMInstance"


type="System.Configuration.DictionarySectionHandler"


/>


</configSections>



<Credentials>


<add key="UserName" value="Administrator" />


<add key="Password" value="PERCY123marta" />


</Credentials>



<ADAMInstance>


<add key="Server" value="localhost" />


<add key="Port" value="50000" />


<add key="Country" value="US" />


<add key="ApplicationDirectoryPartition" value="TaskVisionII" />


<add key="ApplicationDirectoryPartitionDescription" value="TaskVisionII Directory Partition" />


</ADAMInstance>



</configuration>


 


The .NET Directory Entry class is used merely to check whether or not the application directory partition already exists, and if it does not, to retrieve a reference to the COM Active Directory Service Interfaces.  Those interfaces are then used to create a directory partition for the application, with the path, o=TaskVisionII,c=US, and then to create a container for users, CN=Users,o=TaskVisionII,c=US, within that partition. 


 


[This posting is provided "AS IS" with no warranties, and confers no rights.]


Comments (9)

  1. Darrell says:

    I agree, the AD support in .NET is quite weak. All those string literals everywhere suck.

  2. bobby says:

    If you post your code into Word 2003 and then into .Text text field the syntax highlighting will be retained but you won't get the double newlines and the indenting will persist.

    It's very difficult to read posts formated this way.

  3. Craig: See my post (http://blogs.pingpoet.com/overflow/archive/2004/03/04/427.aspx) mentioning the .NET C# LDAP Library. You'll find it much friendlier than "the ghetto of the .NET Framework".

  4. PeterZT says:

    Where I can found taskvision 2?

  5. Craig McMurtry says:

    PeterZT:

    "TaskVision II" is the name I gave the application I am using to demonstrate MIIS and AD/AM in action. So, the code for TaskVision II will be progressively posted as part of this series.

  6. Dan Mork says:

    We are using ADAM to secure our application. ADAM is a lightweight Active Directory implementation that

Skip to main content