Using DirectoryServices for Novell eDirectory

Thursday, 8 July 2010 00:08 by RanjanBanerji

I recently had to work with creating and editing accounts in Novell Directory Services (NDS) or eDirectory.  The LDAP application comes with C and Java SDK and lately even boasts a .Net SDK.  Its the .Net SDK that I set out to use.  You can find detailed documentation on how to use it here:  Also here:

Both the links above require that you download the Novell LDAP SDK in C# assembly from here  The problem with using the Novell SDK for eDirectory is that:

  1. If you are developing a Windows based application you need to go get the Mono.Security.dll.  Not a big deal but an additional step.
  2. You then need to configure your server/s to have a key store.  You will have to download other mono utilities etc.  Its all in the documentation.  Not difficult but additional steps.
  3. The link for downloading the  Novell LDAP SDK in C# ( has been down for months.  I sent Novell an email, a month later I got a response the problem is being fixed.  as of this writing the download site is still unreachable.

Clearly I needed a better approach.  I searched the web and found a few roundabout approaches and then finally decided to use DirectoryServices as packaged with the .Net framework.  At first I was getting no luck.  I was getting extremely meaningful (sarcasm) COM error messages that perhaps even Microsoft cannot decipher.  So I decided to look into the documentation for the Novell eDiretory web services, C SDK and Java SDK.  The three put together gave some valuable insights.  In retrospect if I had a tool to browse their schema things could have been easier.

Anyway, since my task was relatively easy what I am about to show does not cover all that is eDirectory and its SDK.  I simply needed to add, edit and delete users.  The code below is merely a rough example.  I am sure it can be written much more elegantly.  As I often tell developers, you are extremely well paid.  So put in some effort and make it elegant :-)

The main issue with using the DirectoryServices classes for eDirectory is to understand the subtle differences in syntax.

Also, if you are using SSL for your communication to eDirectory you will have to issue a certificate from eDiretory and install it on the server.  In this case this is much easier than the process required for the Novell dll that requires various mono dlls and tools and steps.  Just double click on the certificate file and Windows will install it.

Here is the sample code to add, edit, delete a user.

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Net;
using System.Linq;
using System.Text;

namespace eDirectory {
    class Program {
        static void Main( string[] args ) {
            //Connect using SSL port 636 default
            //In the function below I believe for Active Directory you just put the username as in "bob".  
            //For eDirectory you need to put the proper dn as shown below
            DirectoryEntry de = new DirectoryEntry( "LDAP://,o=YourCompanyName", 
                "cn=ADMINUser,o=YourCompanyName", "AdminPASSWORD", AuthenticationTypes.ServerBind );
            //Here again in AD I believe you say "user"
            DirectorySearcher ds = new DirectorySearcher( de, "(objectClass=user)" );

            //The code below is just a test to see if I can properties for all users.  
            //The code does not work since not all properties are strings.  But I can print 
            //all the property names
            var test = ds.FindAll();
            foreach( SearchResult result in test ) {
                foreach( string propName in result.Properties.PropertyNames ) {
                    Console.Write( propName + "\t" );
                    //foreach( string val in result.Properties[ propName ] ) {
                    //    Console.Write( val + "\t" );
                    Console.WriteLine( " " );

            string username = "newUserName";
            string givenname = "SomeGivenName";
            string sn = "Five";
            string password = "1234!5";
            string newPassword = "123!15";
            string newUserName = "NewUserNameforUser";

            CreateUser( de, username, givenname, sn, password );
            //ChangePassword( de, username, newPassword );
            //DeleteUser( de, username );

        /// <summary>
        /// Deletes a user
        /// </summary>
        /// <param name="de"></param>
        /// <param name="username">User to delete</param>
        private static void DeleteUser( DirectoryEntry de, string username ) {
            //Note syntax for filter
            DirectorySearcher ds = new DirectorySearcher( de, "(&(objectclass=User)" + "(cn=" + username + "))" );
            var test = ds.FindOne();
            if( test != null ) {
                //Note proper dn is required 
                DirectoryEntry userDE = new DirectoryEntry( test.Path, "cn=ADMINUser,o=YourCompanyName", 
                    "AdminPASSWORD", AuthenticationTypes.ServerBind );

        /// <summary>
        /// Edits a user.  Changes password.  Notice difference in syntax compared to AD.  AD uses an Invoke command.
        /// </summary>
        /// <param name="de"></param>
        /// <param name="username"></param>
        /// <param name="newPassword"></param>
        private static void ChangePassword( DirectoryEntry de, string username, string newPassword ) {
            DirectorySearcher ds = new DirectorySearcher( de, "(&(objectclass=User)" + "(cn=" + username + "))" );
            var test = ds.FindOne();

            if( test != null ) {
                //Note proper dn is required 
                DirectoryEntry userDE = new DirectoryEntry( test.Path, "cn=ADMINUser,o=YourCompanyName", 
                    "AdminPASSWORD", AuthenticationTypes.ServerBind );
                userDE.Properties[ "userPassword" ].Add( newPassword );

        /// <summary>
        /// Creates a user
        /// </summary>
        /// <param name="de"></param>
        /// <param name="username"></param>
        /// <param name="givenname"></param>
        /// <param name="sn"></param>
        private static void CreateUser( DirectoryEntry de, string username, string givenname, string sn, string newPassword ) {
            DirectoryEntry newDE = de.Children.Add( "cn=" + username, de.SchemaClassName );
            newDE.Properties[ "objectclass" ].Add( "top" );
            newDE.Properties[ "objectclass" ].Add( "person" );
            newDE.Properties[ "objectclass" ].Add( "organizationalPerson" );
            newDE.Properties[ "objectclass" ].Add( "inetOrgPerson" );
            newDE.Properties[ "objectclass" ].Add( "ndsLoginProperties" );
            newDE.Properties[ "givenname" ].Add( givenname );
            newDE.Properties[ "sn" ].Add( sn );
            newDE.Properties[ "title" ].Add( "BLAH" );
            newDE.Properties[ "userPassword" ].Add( newPassword );


error CS1548: Cryptographic failure while signing assembly. Unknown error (8013141c)

Tuesday, 7 October 2008 22:07 by RanjanBanerji

I have two computers on which I was working on a project and on one of them all of a sudden I started getting this error.  After hours of trying to figure out what went wrong I finally gave up and started to search the web.  I would have started the web search sooner but the errors surfaced soon after I upgraded to Visual Studio 2008.  Well VS 2008 had nothing to do with the error.  It turns out that on one of my two machines I ran a Windows update for a non critical patch.  I realized this after finding this post:

Thank you Julian M Bucknall.  You mention that you wasted 2 hours trying to solve this.  Well I wasted about 4.  I should have found your blog sooner.

Anyway, the solution is simple.  Give your user (whatever account you use to log onto your computer and work on Visual Studio) Full Access to the following folder: C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys

Right Click, Properties, Security Tab, Add your user and make sure it has full access.

Categories:   .Net
Actions:   E-mail | Permalink | Comments (1) | Comment RSSRSS comment feed