зеркало из https://github.com/mozilla/pjs.git
223 строки
11 KiB
Plaintext
223 строки
11 KiB
Plaintext
<!--
|
|
|
|
Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
|
|
Portions copyright 1999 Netscape Communications Corporation. All
|
|
Rights Reserved.
|
|
|
|
The contents of this document are subject to the terms of the
|
|
Creative Commons Attribution-ShareAlike 2.5 license or any later
|
|
version (the "License"). You may not use this document except in
|
|
compliance with the License.
|
|
|
|
See the License for the specific language governing
|
|
permissions and limitations under the License. You can obtain
|
|
a copy of the License at
|
|
http://creativecommons.org/licenses/by-sa/2.5/legalcode.
|
|
|
|
-->
|
|
<chapter id="csdk-sasl"><title>SASL Authentication With &DirectorySDKForC;</title>
|
|
<indexterm>
|
|
<primary>C SDK</primary>
|
|
<secondary>Simple Authentication and Security Layer (SASL)</secondary>
|
|
</indexterm><highlights>
|
|
<para>This chapter describes the process of using a Simple Authentication
|
|
and Security Layer (SASL) mechanism to authenticate an LDAP client to an LDAP
|
|
server.</para>
|
|
<itemizedlist>
|
|
<para>This chapter covers the following topics:</para>
|
|
<listitem><para><olink targetptr="bdaig">Understanding SASL and Directory
|
|
SDK for C</olink></para></listitem>
|
|
<listitem><para><olink targetptr="bdaih">Determining Supported SASL Mechanisms
|
|
With Directory SDK for C</olink></para></listitem>
|
|
<listitem><para><olink targetptr="bdaii">Authenticating Using SASL With Directory
|
|
SDK for C</olink></para></listitem>
|
|
</itemizedlist>
|
|
</highlights>
|
|
<sect1 id="bdaig"><title>Understanding SASL and &DirectorySDKForC;</title>
|
|
<para>The ability to authenticate to an LDAP server with a SASL mechanism
|
|
is a feature that is new to LDAP v3. LDAP v2 servers do not support this method
|
|
of authentication.</para>
|
|
<para>SASL is described in <ulink url="http://www.ietf.org/rfc/rfc4422.txt"
|
|
type="text_url"><?Pub Caret>RFC 4422</ulink>, <citetitle>Simple Authentication
|
|
and Security Layer (SASL)</citetitle>.</para></sect1>
|
|
<sect1 id="bdaih"><title>Determining Supported SASL Mechanisms With &DirectorySDKForC;
|
|
</title>
|
|
<para>To determine the SASL mechanisms supported by an LDAP v3 server, get
|
|
the root DSE of the server, and check the <literal>supportedSASLMechanisms</literal> attribute.
|
|
The values of this attribute are the names of the SASL mechanisms supported
|
|
by the server.</para>
|
|
<para>If the root DSE does not have a <literal>supportedSASLMechanisms</literal> attribute,
|
|
the server does not support any SASL mechanisms.</para>
|
|
<para>For information about getting the root DSE, see <olink targetptr="bdahv">To
|
|
Get the Root DSE</olink>.</para></sect1>
|
|
<sect1 id="bdaii"><title>Authenticating Using SASL With &DirectorySDKForC;</title>
|
|
<itemizedlist>
|
|
<para>To authenticate to the server with a SASL mechanism, call one of the
|
|
following:</para>
|
|
<listitem><para>The synchronous <function>ldap_sasl_bind_s</function> function</para>
|
|
</listitem>
|
|
<listitem><para>The asynchronous <function>ldap_sasl_bind</function> function</para>
|
|
<para>If you call the asynchronous function <function>ldap_sasl_bind</function>,
|
|
you need to call the <function>ldap_result</function> and <function>ldap_parse_sasl_bind_result
|
|
</function> functions to get the result of the SASL bind operation.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>Authentication with a SASL mechanism can take one or more round—trips
|
|
between your client and the server. The server might send a number of <firstterm>
|
|
challenges</firstterm> to the client. You might need to call <function>ldap_sasl_bind_s
|
|
</function> several times, or <function>ldap_sasl_bind</function>, <function>ldap_result
|
|
</function>, and <function>ldap_parse_sasl_bind_result</function> several
|
|
times in order to respond to each server challenge.</para>
|
|
<para>Before calling the function to perform a SASL bind operation, make sure
|
|
to specify that your client is LDAP v3 compliant. If you do not, an <errorcode>LDAP_NOT_SUPPORTED
|
|
</errorcode> result code is returned. See <olink targetptr="bdaci">Specifying
|
|
the LDAP Version of Your Client</olink>.</para>
|
|
<sect2 id="bdaij"><title>Synchronous SASL Bind Operation</title>
|
|
<para>If you want to wait for the results of the SASL bind operation to complete
|
|
before continuing, call the synchronous <function>ldap_sasl_bind_s</function> function.
|
|
This function sends a SASL bind request to the server. This function blocks
|
|
other work until the server sends the results of the operation back to your
|
|
client.</para>
|
|
<itemizedlist>
|
|
<para><function>ldap_sasl_bind_s</function> returns one of the following values:</para>
|
|
<listitem><para><errorcode>LDAP_SUCCESS</errorcode> if your client has successfully
|
|
authenticated.</para></listitem>
|
|
<listitem><para><errorcode>LDAP_SASL_BIND_IN_PROGRESS</errorcode> if the server
|
|
sends a challenge to your client. If you receive this result code, check the <literal>
|
|
servercredp</literal> argument for the <structname>berval</structname> structure
|
|
that contains the server’s challenge. Call the <function>ldap_sasl_bind</function> function
|
|
again to send a response to that challenge.</para></listitem>
|
|
<listitem><para>An LDAP error code if a problem occurred or if authentication
|
|
failed. See the <olink targetptr="bdaux">ldap_sasl_bind_s</olink> function
|
|
documentation for a list of the possible result codes.</para></listitem>
|
|
</itemizedlist>
|
|
</sect2>
|
|
<sect2 id="bdaik"><title>Asynchronous SASL Bind Operation</title>
|
|
<para>If you want to perform other work in parallel while waiting for the
|
|
SASL bind operation to complete, use the following procedure.</para>
|
|
<task><title>To Bind Asynchronously Over SASL</title>
|
|
<procedure>
|
|
<step><para>Call the asynchronous <function>ldap_sasl_bind</function> function
|
|
to send an LDAP SASL bind request.</para><para>This function returns an <errorcode>
|
|
LDAP_SUCCESS</errorcode> result code if the request was successfully sent,
|
|
or an LDAP result code if an error occurred while sending the request. The
|
|
function also sets the <literal>msgidp</literal> argument to point to a message
|
|
ID identifying the SASL bind operation.</para></step>
|
|
<step><para>Call the <function>ldap_result</function> function, passing in
|
|
this message ID to determine whether the server sent a response for this operation
|
|
to your client.</para><para>The <function>ldap_result</function> function
|
|
uses the message ID to determine if the server sent a SASL bind response.
|
|
The function passes back the response in an <structname>LDAPMessage</structname> structure.
|
|
</para></step>
|
|
<step><para>Call the <function>ldap_parse_sasl_bind_result</function> function
|
|
to parse the <structname>LDAPMessage</structname> structure and retrieve information
|
|
from the server’s response.</para><para>If the server sent a challenge
|
|
to your client, the challenge is specified in the <structname>berval</structname> structure
|
|
passed back as the <literal>servercredp</literal> argument.</para></step>
|
|
<step><para>Call the <function>ldap_get_lderrno</function> function to get
|
|
the LDAP result code for the operation.</para>
|
|
<itemizedlist>
|
|
<para>The function can return one of the following values:</para>
|
|
<listitem><para><errorcode>LDAP_SUCCESS</errorcode> if your client successfully
|
|
authenticated to the server.</para></listitem>
|
|
<listitem><para><errorcode>LDAP_SASL_BIND_IN_PROGRESS</errorcode> if the server
|
|
sent a challenge to your client.</para><para>If the server returned an <errorcode>
|
|
LDAP_SASL_BIND_IN_PROGRESS</errorcode> result code, check the <literal>servercredp
|
|
</literal> argument for the <structname>berval</structname> structure that
|
|
contains the server’s challenge.</para></listitem>
|
|
<listitem><para>An LDAP error code if a problem occurred or if authentication
|
|
failed.</para><para>See the <function>ldap_sasl_bind</function> function documentation
|
|
for a list of result codes that the server can return for this operation.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</step>
|
|
<step><para>If the result code is <errorcode>LDAP_SASL_BIND_IN_PROGRESS</errorcode> and
|
|
if the server passed back another challenge, determine the response to that
|
|
challenge by calling the <function>ldap_sasl_bind</function> function again
|
|
to send that response to the server.</para><para>You can call <function>ldap_result
|
|
</function> and <function>ldap_parse_sasl_bind_result</function> again to
|
|
get the next challenge sent from the server, if the result is again <errorcode>LDAP_SASL_BIND_IN_PROGRESS
|
|
</errorcode>.</para></step>
|
|
</procedure>
|
|
<example>
|
|
<title>Authenticating Over SASL</title>
|
|
<para>This example shows an LDAP client that authenticates using the SASL
|
|
mechanism that is named <literal>babsmechanism</literal>.</para>
|
|
<programlisting>#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include "ldap.h"
|
|
|
|
int
|
|
main( int argc, char **argv )
|
|
{
|
|
LDAP *ld;
|
|
LDAPMod mod0;
|
|
LDAPMod mod1;
|
|
LDAPMod *mods[ 3 ];
|
|
char *vals0[ 2 ];
|
|
char *vals1[ 2 ];
|
|
time_t now;
|
|
char buf[ 128 ];
|
|
struct berval cred;
|
|
struct berval *servcred;
|
|
int version;
|
|
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
|
|
if ( (ld = ldap_init( "localhost", 389 )) == NULL ) {
|
|
perror( "ldap_init" );
|
|
return( 1 );
|
|
}
|
|
/* Set the LDAP protocol version supported by the client
|
|
to 3. (By default, this is set to 2. SASL authentication
|
|
is part of version 3 of the LDAP protocol.) */
|
|
version = LDAP_VERSION3;
|
|
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
|
|
/* authenticate */
|
|
cred.bv_val = "magic";
|
|
cred.bv_len = sizeof( "magic" ) - 1;
|
|
if ( ldap_sasl_bind_s( ld, "uid=bjensen,ou=people,dc=example,dc=com",
|
|
"babsmechanism", &cred, NULL, NULL,
|
|
&servcred ) != LDAP_SUCCESS ) {
|
|
ldap_perror( ld, "ldap_sasl_bind_s" );
|
|
return( 1 );
|
|
}
|
|
/* get and print the credentials returned by the server */
|
|
printf( "Server credentials: %s\n", servcred->bv_val );
|
|
/* construct the list of modifications to make */
|
|
mod0.mod_op = LDAP_MOD_REPLACE;
|
|
mod0.mod_type = "mail";
|
|
vals0[0] = "babs@example.com";
|
|
vals0[1] = NULL;
|
|
mod0.mod_values = vals0;
|
|
mod1.mod_op = LDAP_MOD_ADD;
|
|
mod1.mod_type = "description";
|
|
time( &now );
|
|
sprintf( buf, "This entry was modified with the modattrs program on %s",
|
|
ctime( &now ));
|
|
/* Get rid of \n which ctime put on the end of the time string */
|
|
if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
|
|
buf[ strlen( buf ) - 1 ] = '\0';
|
|
}
|
|
vals1[ 0 ] = buf;
|
|
vals1[ 1 ] = NULL;
|
|
mod1.mod_values = vals1;
|
|
mods[ 0 ] = &mod0;
|
|
mods[ 1 ] = &mod1;
|
|
mods[ 2 ] = NULL;
|
|
/* make the change */
|
|
if ( ldap_modify_s(ld, "uid=bjensen,ou=people,dc=example,dc=com", mods)
|
|
!= LDAP_SUCCESS ) {
|
|
ldap_perror( ld, "ldap_modify_s" );
|
|
return( 1 );
|
|
}
|
|
ldap_unbind( ld );
|
|
printf( "modification was successful\n" );
|
|
return( 0 );
|
|
}</programlisting>
|
|
</example>
|
|
</task>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter>
|