SSL Connections With &DirectorySDKForC;
C SDK
Secure Sockets Layer (SSL)
This chapter describes the process of enabling an LDAP client to connect
to an LDAP server over the Secure Sockets Layer (SSL) protocol.
This chapter covers the following topics:
How SSL Works With Directory SDK
for C
Connecting to a Server Over SSL With
Directory SDK for C
Handling Errors With Directory SDK
for C
Starting Transport Layer
Security With Directory SDK for C
Installing Your Own SSL I/O Functions
With Directory SDK for C
Using Certificate-Based Client Authentication
With Directory SDK for C
How SSL Works With &DirectorySDKForC;
The primary goal of the SSL protocol is to provide privacy and reliability
between two communicating applications.
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 client’s 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.
&DirectorySDKForC; includes functions that allow you to connect an
LDAP client to an LDAP server over SSL. The functions make the following assumptions:
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 database used contains any one of the following:
The certificate of the CA that issued the server’s 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.
If you plan to use certificate-based client authentication, you also
need the following:
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
The functions allow you to do the following:
Set the session option for communicating with the server over
SSL.See Connecting to a Server Over
SSL With Directory SDK for C for details.
Start transport layer security by using the Start TLS extended
operationSee Starting Transport
Layer Security With Directory SDK for C for details.
Replace the default I/O functions with your own I/O functions
for communicating over SSLSee Installing
Your Own SSL I/O Functions With Directory SDK for C for details.
Enable your client to send certificates to authenticate itself
See Using Certificate-Based Client Authentication
With Directory SDK for C for details.
Connecting to a Server Over SSL With &DirectorySDKForC;
C SDK
Secure Sockets Layer (SSL)
connecting to the server
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
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.
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.
To Initialize a Client SSL Connection by using 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
After initializing your client, initialize an LDAP session with
the server by calling the standard initialization function ldap_init.
Install the standard SSL I/O functions by calling ldapssl_install_routines
.
Set the SSL option in the LDAP structure by calling ldap_set_option
.
Initializing a Client SSL Initialization (Alternative Method Using
ldap_init)
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 &DirectorySDKForC;
C SDK
Secure Sockets Layer (SSL)
handling errors
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 &DirectorySDKForC;
C SDK
Secure Sockets Layer (SSL)
start TLS
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.
The process of initializing the client opens the certificate
database.
Get a handle to an LDAP connection.
Request Start TLS with ldap_start_tls_s.
Authenticate to the directory to perform additional operations.
Using Start TLS
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 );
}
See Performing a Who Am I? Extended
Operation With Directory SDK for C for details on using the “Who
am I?” extended operation.
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 &DirectorySDKForC;
C SDK
Secure Sockets Layer (SSL)
custom I/O functions
The ldapssl_init and ldapssl_install_routines
functions both set up the session to use the standard SSL I/O
functions provided with &DirectorySDKForC;. 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
Create an ldap_x_ext_io_fns structure,
and set the fields to point to your I/O functions.
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 &DirectorySDKForC;
C SDK
Secure Sockets Layer (SSL)
certificate-based authentication
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
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.
Initialize an LDAP session with the secure server by calling
ldapssl_init.
Enable your client to authenticate with the secure server by calling
ldapssl_enable_clientauth.
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 &cnDirectoryServer;, 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.