Mozilla LDAP SDK Programmer's Guide/SSL Connections With LDAP C SDK

From MozillaWiki
Jump to: navigation, search

This section describes the process of enabling an LDAP client to connect to an LDAP server over the Secure Sockets Layer (SSL) protocol.

How SSL Works With LDAP C SDK

The primary goal of the SSL protocol is to provide privacy and reliability between two communicating applications.

Note: SSL is not supported on all LDAP servers.
SSL communication must take place on a separate TCP port unless the server supports Start TLS.

When an LDAP client connects to an LDAP server over SSL, the server identifies itself by sending a certificate to the client. The client needs to determine whether or not the certificate authority (CA) that issued the certificate is trusted. The client therefore searches a certificate database for the certificate of the CA. If the client cannot find the certificate, the client refuses to connect to the server. If the certificate is marked not trusted, the client also refuses to connect to the server.

The LDAP server can also request that the client send a certificate to authenticate itself. This part of the process is called certificate-based client authentication. If the client receives a request for a certificate from the server, the client retrieves its certificate from the certificate database. The client sends the certificate to the server for authentication. After receiving the clients certificate, the LDAP server determines whether or not the CA that issued the certificate is trusted. If the server cannot find the CA certificate in the certificate database, the server refuses to authenticate the client. If the CA certificate is marked as not trusted, the server also refuses to authenticate the client. If the CA is trusted, the server uses the certificate subject name to determine whether the client has access to perform the requested operation.

  • Your client has access to a certificate database. The function call uses this certificate database to determine if the client can trust the certificate sent from the server.
    Different certificate database versions can be incompatible, which might result in database errors.
    • The certificate of the CA that issued the servers certificate
    • If the CAs are organized in a hierarchy, the certificate of any of the CAs in the hierarchy
    • The certificate of the LDAP server
  • The CA certificate is marked as trusted in the certificate database.
    • A client certificate in the certificate database issued by a CA that is trusted by the LDAP server
    • A public-private key pair in a key file
  • Set the session option for communicating with the server over SSL.
  • Start transport layer security by using the Start TLS extended operation.
  • Replace the default I/O functions with your own I/O functions for communicating over SSL.
  • Enable your client to send certificates to authenticate itself.

Connecting to a Server Over SSL With LDAP C SDK

To enable your LDAP client to connect to an LDAP server with SSL, you need to perform the following procedure.

To Initialize a Client SSL Connection by Using ldapssl_init()

  1. Initialize your client by calling one of the following functions:
    • Call ldapssl_client_init() if you do not plan to use certificate-based client authentication.
    • Call ldapssl_clientauth_init() if you plan to use certificate-based client authentication.
    • Call ldapssl_advclientauth_init().
      If you use certificate-based client authentication, you need to specify the path of the security module database, or to specify the method to verify the server certificate.
      You must initialize your client before initializing the LDAP session. The process of initializing the client opens the certificate database.
  2. Initialize an LDAP session with the secure server by calling the ldapssl_init() function.
    For an alternative way to accomplish this step, see Alternative to ldapssl_init().

This example initializes a client to connect to a secure LDAP server over SSL.

if ( ldapssl_client_init( "/local/examples/alias/", NULL )  0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* get a handle to an LDAP connection */
if ( (ld = ldapssl_init( "cert.example.com", LDAPS_PORT, 1 )) == NULL {
  perror( "ldapssl_init" );
  return( 1 );
}
...
/* Client can now perform LDAP operations on the secure LDAP server. */
...

Alternative to ldapssl_init()


As an alternative to calling the ldapssl_init() function, you can use the following procedure.

To Initialize a Client SSL Connection (Alternative Method Using ldap_init())

  1. After initializing your client, initialize an LDAP session with the server by calling the standard initialization function ldap_init().
  2. Install the standard SSL I/O functions by calling ldapssl_install_routines().
  3. Set the SSL option in the LDAP structure by calling ldap_set_option().

This example prepares a client to connect to a secure LDAP server over SSL using ldap_init().

if ( ldapssl_client_init( "/local/examples/alias/", NULL )  0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* Initialize LDAP session. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, LDAPS_PORT )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}

/* Load SSL routines */
if ( ldapssl_install_routines( ld ) != 0 ) {
  ldap_perror( ld, "ldapssl_install_routines" );
  return( 1 );
}
/* Set up option in LDAP struct for using SSL */
if ( ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_ON ) != 0 ) {
  ldap_perror( ld, "ldap_set_option" );
  return( 1 );
}
/* Client can now perform LDAP operations on the secure LDAP server. */
...

Handling Errors With LDAP C SDK

After calling any of the SSL initialization functions, you can convert SSL-specific error codes to text strings by calling ldapssl_err2string(). The ldapssl_err2string() function provides support for special SSL error messages that are not handled by the normal error conversion routine ldap_err2string().

Starting Transport Layer Security With LDAP C SDK

RFC 4513, Lightweight Directory Access Protocol (LDAP): Authentication Methods and Security Mechanisms, describes the extended operation. Start TLS allows you to connect to a nonsecure port, and then request transport layer security.

To Use Start TLS

Initialize your client with ldapssl_client_init().

  1. The process of initializing the client opens the certificate database.
  2. Get a handle to an LDAP connection.
  3. Request Start TLS with ldap_start_tls_s().
  4. Authenticate to the directory to perform additional operations.

This example connects and uses Start TLS, then requests the Who am I? extended operation. The example relies on a certificate database directory, /local/examples/alias/.

/*
 * Use the Start TLS extended operation.
 */

#include "examples.h"
#include <ldap_ssl.h>

/*
 * Path to certificate database for SSL
 */
#define CERT_DB_PATH    "/local/examples/alias/"

int
main( int argc, char **argv )
{
    int             version;
    LDAP            *ld;
    int             rc;
    char            *authzid;

    /* Initialize access to the certificate database. */
    if ( ldapssl_client_init( CERT_DB_PATH, NULL ) != 0 ) {
        fprintf( stderr, "ldapssl_client_init failed\n" );
        fprintf( stderr, "certificate database path: %s\n", CERT_DB_PATH );
        return( 1 );
    }

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
        fprintf( stderr,
                 "ldap_set_option protocol version to %d failed\n",
                 version );
        return( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Request Start TLS. */
    if ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_start_tls_s" );
        return( 1 );
    }
    printf( "Start TLS operation successful.\n" );

    /* Authenticate to the directory. */
    if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }

    /* Examine my authorization ID. */
    if ( (rc = ldap_whoami_s( ld, NULL, NULL, authzid ) )
         != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_whoami_s: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    printf( "Authorization ID: %s\n", authzid );

    ldap_unbind( ld );
    return( 0 );
}

To troubleshoot Start TLS problems, call the PR_GetError() function. This function gives you access to many Network Security Services (NSS) errors further documented in the Mozilla.org SSL Reference.

Installing Your Own SSL I/O Functions With LDAP C SDK

The ldapssl_init() and ldapssl_install_routines() functions both set up the session to use the standard SSL I/O functions provided with LDAP C SDK. If you want to use your own SSL I/O functions, use the ldap_x_ext_io_fns() structure.

To Install Your Own SSL I/O Functions

  1. Create an ldap_x_ext_io_fns structure, and set the fields to point to your I/O functions.
  2. Call ldap_set_option to point to that structure.
if (ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, my_io_struct) != 0 ) {
      ldap_perror( ld, "ldap_set_option" );
      return( 1 );
}

Using Certificate-Based Client Authentication With LDAP C SDK

Some LDAP servers can be configured to use certificate-based client authentication. The server requests that your client send a certificate to identify itself. Use the following procedure to configure your client to use certificates for authentication.

To Use Certificate-Based Client Authentication

  1. Initialize your LDAP client by calling either ldapssl_clientauth_init() or ldapssl_advclientauth_init(), not ldapssl_client_init().
    Use ldapssl_advclientauth_init() if you want to specify the path of a security module database, or to specify the method used to verify the server certificate.
    You can use one of these functions to initialize your client even if you do not plan to use certificate-based client authentication. The functions are equivalent to ldapssl_client_init().
  2. Initialize an LDAP session with the secure server by calling ldapssl_init().
  3. Enable your client to authenticate with the secure server by calling ldapssl_enable_clientauth().
  4. Perform a Simple Authentication and Security Layer (SASL) bind operation by using the mechanism EXTERNAL. This mechanism indicates to the directory server that certificates should be used to authenticate clients.
    With Directory Server, if you perform a SASL bind operation, but the server cannot find the corresponding directory entry for a client certificate, the server returns an LDAP_INVALID_CREDENTIALS result code with the error message Client Certificate Mapping Failed.