Novell Home

DeveloperNet University's NDS 102 Using C and LDAP

Articles and Tips: article

LAWRENCE V. FISHER
Senior Research Engineer
Developer Information

01 Mar 1999


This lesson in DeveloperNet University's NDS category provides you with the information necessary to use LDAP libraries to build a Win32 client-side-only application that can establish an authenticated connection to an NDS tree.

Introduction

This is another lesson in DeveloperNet University's NDS 102 category. The following table describes what you will need in order to build this sample application.


Objective
Using this example as a guide, a C/C++ programmer will be able to use LDAP libraries to build a Win32 client-side-only application that can establish an authenticated connection to an NDS tree.

Prerequisites

Entry level C programming skills. In order to understand the concepts and code in this article, you should be familiar with the concepts explained in the article, "DeveloperNet University's NDS 101 Using C and LDAP" in the December 1998 issue of Developer Notes.

Required Items

A Win32 development environment. A recent version of Netscape Navigator. The Netscape LDAP SSL SDK for C and documentation installed. Installs providing Netscape's LDAP SDKs for C are available free from the following location: http://developer.netscape.com/tech/directory

Optional Items

Novell's NetWare Administrator (NWAdmin) or ConsoleOne NDS Administration tools are available along with a free DeveloperNet subscription from: http://developer.novell.com/ndk/

NWAdmin and ConsoleOne are also available from the standard NetWare 5 install CD.

Required Setup

TCP/IP network access to at least one NetWare server running LDAP Services for NDS (available from the standard NetWare 5 install CD).

In the "NDS 101 Using C and LDAP" lesson, the tree associated with Novell's LDAP Services NLM required a publicly accessible object with public attributes in order for the program to read them via an unauthenticated connection (anonymous bind). In this lesson we demonstrate how to obtain a connection via SSL in order to perform an authenticated bind. This will allow your applications to read any value, as long as the user object specified in your bind call has the appropriate access.

NDS102 LDAP Concepts

An understanding of the following topics may help in learning how to use LDAP with NDS.

  • Network Security Terms

  • NetWare's Primary Authentication Protocol

  • NetWare's Server-side Background Authentication Protocol

For information on these and other NetWare connection related concepts, you should read the article titled, "NDS102: Authenticating to NDS Using C and NDAP APIs" in the February 1999 issue of Novell Developer Notes.

The NDS101 GUI

We provide simple GUIs for all examples. Figure 1 shows the GUI provided for NDS101 Using C.

Figure 1: The GUI is kept seperate from the example code discussed in the DeveloperNet University articles.

When the user clicks the "Read Attribute" button, the GUI code will execute the lab code to obtain an authenticated connection and then read the attribute specified by "Attribute Name" from the object specified by "Object Name" in the tree associated with the NDS server specified by "Server ID."

Figure 2 shows a code snippet that could be used to obtain an authenticated connection through Secure Sockets Layer (SSL) and then perform an NDS read operation.

Figure 2: You can modify the example code so that the GUI will call your experiments.

As you can see, there isn't much code necessary to obtain and use an authenticated SSL connection with LDAP.

LDAP SSL Connections to Novell's LDAP Services NLM

As illustrated in Figure 3, calls made to NDS from applications built with the NetWare C client SDK (using the Novell Directory Access Protocol or NDAP), go through NetWare DLLs which are installed with the NetWare client software.

Figure 3: Each LDAP client must create its own IP connection to the LDAP Services for NetWare NLM.

NetWare's client DLLs maintain connection information in connection reference tables available to any application running on the platform. This means that NDAP applications can share connections via background authentication, removing the need for each of them to log in separately. The NDAP NDS 101 and 102 lessons from this series are examples of such applications.

LDAP client applications, however, are independent and cannot share connection information. Therefore, each LDAP application must create its own separate IP connection to the server.

LDAP applications do not connect directly to NDS as an NDAP application would. Instead, LDAP applications first establish a Secure Sockets Layer (SSL) connection to the Novell LDAP Services NLM running on an NDS server which then connects to NDS (see Figure 4).

The connection between the LDAP services NLM and NDS is authenticated using NetWare's primary NDS authentication protocol that was discussed in the article titled, "NDS 102: Authenticating to NDS Using C and NDAP APIs."

The SSL authentication protocol uses asymmetric key cryptography to secure transactions between the client and server. In order to understand this protocol, you will need to understand what a certificate is.

Certificates and Certificate Authorities

Note: For information on terms such as public keys, private keys, signatures, etc., refer to the lesson, "NDS 102: Authenticating to NDS Using C and NDAP APIs."

A certificate is a digital token which is used to prove the identity of a participant during network transactions. It is attached to a message by the sender and verified at the other end by the receiver to ensure that the message is from a trusted source.

A certificate authority or CA is an organization (private or public) which issues digital certificates (often for a fee) to users so that they can use them to guarantee the identity of their sent messages. This is a digital equivalent to the historical practice of sealing letters with a printed wax insignia from some authorizing power, a king for example.

A certificate consists of the name of the certificate authority that issued the certificate, the owning organization (company name for example), the user's public key, the certificate's validity period, and the hostname of the server from which the certificate was issued. The certificate is digitally signed (hashed) by the certificate authority so that the receiver can verify the integrity of the certificate's contents. Then the whole thing, including the signature, is encrypted with the CA's private key, effectively sealing it.

Once a certificate is obtained from a certificate authority, it can be used for its validity period (often as long as a year), or until it is specifically invalidated by the CA for some reason (perhaps because it was stolen).

The digital certificates used in SSL are defined in the X.509 standard.

Figure 4: LDAP Services for NetWare performs the NDS authentication protocol for all of its connected clients.

How Certificates are Used in the LDAP/SSL Authentication Protocol

When the sending participant wishes to send a message with a certificate, he encrypts his data with his private key and then attaches the appropriate certificate (he can have several).

The receiving participant must possess the public key from the appropriate CA in order to participate in the transaction. If the receiving participant has the appropriate public key, she can use it to decrypt the certificate part of the message (remember the certificate was encrypted with the CA's private key and in asymmetric cryptography, public keys are used to decrypt messages encrypted with private keys).

If the decryption is successful, the receiver knows that it is a valid certificate and so can be confident that the message is from a trusted source. The receiver can then obtain the sender's public key from the certificate and use it to decrypt the data portion of the sender's message, confident that its integrity is guaranteed by the certificate authority.

In order for a client to authenticate to the server using SSL, the client must send the server's certificate along with the message requesting authentication.

Client applications built with the Netscape LDAP libraries (as used in our examples) obtain certificates from Netscape certificate database files.

If the LDAP services NLM denies an authenticated SSL connection for some reason, it will award an unauthenticated connection (anonymous bind) instead.

Setting Up to Run this Example

Before you can implement SSL connections to NetWare with a Netscape LDAP client application, you must perform four steps to enable your app to find and use your server's certificate:

  1. From the NWAdmin application, use NDS security objects to create and export a server certificate (.der file)

  2. Run PKIS.reg (located in SYS:PUBLIC on NetWare 5 servers) to enable your default browser to understand .der files.

  3. From your browser, import the server's certificate into the browser's certificate database.

  4. Copy the certificate database file (Cert7.db) into the directory containing your LDAP executable code so that when the executable is run, it can find and open the database file.

For help in performing the above steps and some very useful additional information about LDAP, refer to the article, "Configuring LDAP Services for NDS" by Nancy McLain in the November, 1998 issue of Novell Developer Notes.

Source Code

The following is the source code listing for this lesson. All LDAP data types and functions are in bold. The large italic, double-underlined numbers refer to explanations after the code listing.

There are several LDAP SDKs available free. This example uses Netscape's nsldapssl32V30 library. Since it is LDAP, it can be used with any LDAP accessible directory including NDS.

You can install Netscape's Libraries for LDAP from the Web: http://developer.netscape.com/tech/directory/

Once you have installed the LDAP SDK, make sure that you add the appropriate path names to your development environment so it can access the headers and libraries before you attempt to build this sample application.

/*  Includes */

   #include 

   #include 

   #include 

   #include 

   #include 



   #include 

   #include 





1  LPSTR serverName    = "Deved3";

   LPSTR objectName   = "cn=lFisher,o=Novell";

   LPSTR attributeName = "cn";  //cn, givenname, sn, mail, telephonenumber, o, etc.





   // getFieldStringValue is exported so can be called by the NDS102 GUI exe

   void __declspec(dllexport) WINAPI  getFieldStringValue( LPSTR theBuffer  );

   void   freeReadResources (  LDAP *connInfo, LDAPMessage *resultBfr );

   void displayError(   LDAP * connInfo, LPSTR theBuffer, LDAPMessage *resultBfr );

 

   //---------------------------------------------------------------------

   // Function : getFieldStringValue - for establishing an authenticated connection

                                     And then reading object data in DS tree over it.

   //---------------------------------------------------------------------

   void __declspec(dllexport) WINAPI  getFieldStringValue(LPSTR theBuffer)

   { LDAP    *connInfo = NULL;

     LDAPMessage  *resultBfr = NULL,*entry = NULL;

     BerElement  *berEl;

     char    *attribute;

     char    **vals;

     int      valIndex;

     char*    attrs[2];

  

     attrs[0]= attributeName;  attrs[1]= NULL;



2    if ( ldapssl_client_init( "cert7.db", NULL ) < 0) 

          (void)lstrcat( theBuffer, "ldapssl_init error" );

       else

     {

3    if ( ( connInfo = ldapssl_init( serverName, LDAPS_PORT, 1 ) ) == NULL )

         (void)lstrcat( theBuffer, "ldapssl_init error" );

        else

4     {  if ( ldap_simple_bind_s( connInfo, objectName, passWord) != LDAP_SUCCESS )

                displayError( connInfo, theBuffer, resultBfr );

              else

              { if( ldap_search_s(  connInfo, objectName, LDAP_SCOPE_BASE,

                           "(objectclass=*)",attrs,0,&resultBfr) != LDAP_SUCCESS)&
                  displayError( connInfo, theBuffer, resultBfr );

                else

                { for(entry = ldap_first_entry( connInfo, resultBfr);

                      entry!= NULL;

                      entry = ldap_next_entry( connInfo,entry ) )

                  {

                    for(attribute = ldap_first_attribute(connInfo, entry,&berEl ); &
                        attribute != NULL; 

                        attribute = ldap_next_attribute( connInfo, entry, berEl) )

                   { if(( vals = ldap_get_values( connInfo, entry, attribute )) != NULL)

                      {

                        for( valIndex = 0 ; vals[valIndex] != NULL; valIndex++ )

                          (void)lstrcat( theBuffer, vals[valIndex] );

                        ldap_value_free( vals );

                      }

                      ldap_memfree( attribute );

                   }

                   if ( berEl != NULL )

                 ber_free(berEl,0);

               }

            }

         }

         freeReadResources (  connInfo, resultBfr );

       }

     }

   }



   void   freeReadResources (  LDAP *connInfo, LDAPMessage *resultBfr )

   { if (resultBfr != NULL)  {  ldap_msgfree( resultBfr);    }

     if (connInfo != NULL)  {  ldap_unbind(connInfo);    }

   }



   void displayError(   LDAP * connInfo, LPSTR theBuffer, LDAPMessage *resultBfr )

   { char  *firstGoodDN,*errMsg,tempstr[512]="";

     int    errID;

     errID = ldap_get_lderrno( connInfo, &firstGoodDN, &errMsg );&
     lstrcat(theBuffer,errMsg);

     lstrcat(tempstr,errMsg);

     if( errID == LDAP_NO_SUCH_OBJECT)

     {  lstrcat(tempstr,"\nFirst existing object in dName = ");

       lstrcat(tempstr,firstGoodDN);

     }

     MessageBox(NULL, tempstr, "DEBUG", MB_OK);

     freeReadResources (  connInfo, resultBfr );

   }

Note: Very little code has been added to this lesson. Most of the code listed here was already explained in the "NDS101 Using C and LDAP" lesson.

  1. Enter the domain name or IP address for the server running Nldap.nlm into serverName. Nldap.nlm moderates access to the NDS tree associated with its server.

    Enter the distinguished name for the object to be read. Notice that LDAP delimits the objects and containers in the distinguished name path with `,' instead of Novell's name delimiter character `.'

    Enter the selected attribute into attributeName. For our sample code, we need to choose an attribute that we know will always exist in the object, like the "cn" attribute. Also, because our GUI interface expects a String, we need an attribute with a syntax that can be viewed as a String. Some NDS syntaxes have no human readable String value.

  2. Among other things, the ldapssl_client_init( ) call loads the Netscape certificate database file, "Cert7.db". Make sure that you have performed the necessary steps as described in the section above "Setting Up to Run This Example" so that you have a valid certificate from the server in the database.

  3. This call contains a valid name and password. Because both of these parameters are non-null and because the port number specified is LDAPS_PORT (636) as opposed to LDAP_PORT (389), LDAP services for NDS will attempt to authenticate this connection to the directory.

Note: If you would like more information on the rest of the code in this example, refer to the "NDS101 using C and LDAP" lesson.

Conclusion

In this article, we have discussed how digital certificates can be used in an LDAP C application to establish authenticated binds between an LDAP application and Novell's LDAP Services NLM.

Accessing NDS with LDAP really isn't difficult.

As you experiment with the code example, try rebuilding it to connect to different trees.

Note: Other DeveloperNet University examples present additional ways to develop to NDS, like ActiveX.

For more information about other examples in this series, refer to: http://developer.novell.com/education/

To download the project corresponding to this article, refer to: http://www.novell.com/coolsolutions/tools/15625.html

There is an LDAP Services for NDS test server available for your programming experiments on the usual LDAP port 389 at: www.nldap.com

Try the following URL to run an interesting LDAP demo with your browser: http://ldap.novell.com/


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© 2014 Novell