3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
8 * BindRequest ::= SEQUENCE {
10 * name DistinguishedName, -- who
11 * authentication CHOICE {
12 * simple [0] OCTET STRING -- passwd
13 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
14 * krbv42ldap [1] OCTET STRING
15 * krbv42dsa [2] OCTET STRING
17 * sasl [3] SaslCredentials -- LDAPv3
21 * BindResponse ::= SEQUENCE {
22 * COMPONENTS OF LDAPResult,
23 * serverSaslCreds OCTET STRING OPTIONAL -- LDAPv3
32 #include <ac/socket.h>
33 #include <ac/string.h>
41 * ldap_sasl_bind - bind to the ldap server (and X.500).
42 * The dn (usually NULL), mechanism, and credentials are provided.
43 * The message id of the request initiated is provided upon successful
44 * (LDAP_SUCCESS) return.
47 * ldap_sasl_bind( ld, NULL, "mechanism",
48 * cred, NULL, NULL, &msgid )
55 LDAP_CONST char *mechanism,
64 Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 );
67 assert( LDAP_VALID( ld ) );
68 assert( msgidp != NULL );
70 if( msgidp == NULL ) {
71 ld->ld_errno = LDAP_PARAM_ERROR;
75 if( mechanism == LDAP_SASL_SIMPLE ) {
76 if( dn == NULL && cred != NULL ) {
77 /* use default binddn */
78 dn = ld->ld_defbinddn;
81 } else if( ld->ld_version < LDAP_VERSION3 ) {
82 ld->ld_errno = LDAP_NOT_SUPPORTED;
90 /* create a message to send */
91 if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
92 ld->ld_errno = LDAP_NO_MEMORY;
96 assert( BER_VALID( ber ) );
98 if( mechanism == LDAP_SASL_SIMPLE ) {
100 rc = ber_printf( ber, "{it{istON}" /*}*/,
101 ++ld->ld_msgid, LDAP_REQ_BIND,
102 ld->ld_version, dn, LDAP_AUTH_SIMPLE,
105 } else if ( cred == NULL ) {
106 /* SASL bind w/o creditials */
107 rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/,
108 ++ld->ld_msgid, LDAP_REQ_BIND,
109 ld->ld_version, dn, LDAP_AUTH_SASL,
113 /* SASL bind w/ creditials */
114 rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/,
115 ++ld->ld_msgid, LDAP_REQ_BIND,
116 ld->ld_version, dn, LDAP_AUTH_SASL,
121 ld->ld_errno = LDAP_ENCODING_ERROR;
126 /* Put Server Controls */
127 if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
132 if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
133 ld->ld_errno = LDAP_ENCODING_ERROR;
139 if ( ld->ld_cache != NULL ) {
140 ldap_flush_cache( ld );
142 #endif /* !LDAP_NOCACHE */
144 /* send the message */
145 *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber );
158 LDAP_CONST char *mechanism,
160 LDAPControl **sctrls,
161 LDAPControl **cctrls,
162 struct berval **servercredp )
166 struct berval *scredp = NULL;
168 Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind_s\n", 0, 0, 0 );
170 /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
171 if( servercredp != NULL ) {
172 if (ld->ld_version < LDAP_VERSION3) {
173 ld->ld_errno = LDAP_NOT_SUPPORTED;
179 rc = ldap_sasl_bind( ld, dn, mechanism, cred, sctrls, cctrls, &msgid );
181 if ( rc != LDAP_SUCCESS ) {
185 if ( ldap_result( ld, msgid, 1, NULL, &result ) == -1 ) {
186 return( ld->ld_errno ); /* ldap_result sets ld_errno */
189 /* parse the results */
191 if( servercredp != NULL ) {
192 rc = ldap_parse_sasl_bind_result( ld, result, &scredp, 0 );
195 if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) {
196 ldap_msgfree( result );
200 rc = ldap_result2error( ld, result, 1 );
202 if ( rc == LDAP_SUCCESS || rc == LDAP_SASL_BIND_IN_PROGRESS ) {
203 if( servercredp != NULL ) {
204 *servercredp = scredp;
209 if ( scredp != NULL ) {
218 * Parse BindResponse:
220 * BindResponse ::= [APPLICATION 1] SEQUENCE {
221 * COMPONENTS OF LDAPResult,
222 * serverSaslCreds [7] OCTET STRING OPTIONAL }
224 * LDAPResult ::= SEQUENCE {
225 * resultCode ENUMERATED,
227 * errorMessage LDAPString,
228 * referral [3] Referral OPTIONAL }
232 ldap_parse_sasl_bind_result(
235 struct berval **servercredp,
239 struct berval* scred;
244 Debug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 );
246 assert( ld != NULL );
247 assert( LDAP_VALID( ld ) );
248 assert( res != NULL );
250 if ( ld == NULL || res == NULL ) {
251 return LDAP_PARAM_ERROR;
254 if( servercredp != NULL ) {
255 if( ld->ld_version < LDAP_VERSION2 ) {
256 return LDAP_NOT_SUPPORTED;
261 if( res->lm_msgtype != LDAP_RES_BIND ) {
262 ld->ld_errno = LDAP_PARAM_ERROR;
268 if ( ld->ld_error ) {
269 LDAP_FREE( ld->ld_error );
272 if ( ld->ld_matched ) {
273 LDAP_FREE( ld->ld_matched );
274 ld->ld_matched = NULL;
279 ber = ber_dup( res->lm_ber );
282 ld->ld_errno = LDAP_NO_MEMORY;
286 if ( ld->ld_version < LDAP_VERSION2 ) {
287 tag = ber_scanf( ber, "{ia}",
288 &errcode, &ld->ld_error );
290 if( tag == LBER_ERROR ) {
292 ld->ld_errno = LDAP_DECODING_ERROR;
299 tag = ber_scanf( ber, "{iaa" /*}*/,
300 &errcode, &ld->ld_matched, &ld->ld_error );
302 if( tag == LBER_ERROR ) {
304 ld->ld_errno = LDAP_DECODING_ERROR;
308 tag = ber_peek_tag(ber, &len);
310 if( tag == LDAP_TAG_REFERRAL ) {
312 if( ber_scanf( ber, "x" ) == LBER_ERROR ) {
314 ld->ld_errno = LDAP_DECODING_ERROR;
318 tag = ber_peek_tag(ber, &len);
321 if( tag == LDAP_TAG_SASL_RES_CREDS ) {
322 if( ber_scanf( ber, "O", &scred ) == LBER_ERROR ) {
324 ld->ld_errno = LDAP_DECODING_ERROR;
332 if ( servercredp != NULL ) {
333 *servercredp = scred;
335 } else if ( scred != NULL ) {
339 ld->ld_errno = errcode;
345 return( ld->ld_errno );
348 #ifdef HAVE_CYRUS_SASL
350 * Various Cyrus SASL related stuff.
353 #define MAX_BUFF_SIZE 65536
354 #define MIN_BUFF_SIZE 4096
357 array2str( char **a )
362 for ( v = a; *v != NULL; v++ ) {
363 len += strlen( *v ) + 1; /* for a space */
370 s = LDAP_MALLOC ( len ); /* last space holds \0 */
377 for ( v = a; *v != NULL; v++ ) {
381 strncpy( p, " ", 1 );
385 strncpy( p, *v, len );
394 int ldap_pvt_sasl_init( void )
396 /* XXX not threadsafe */
397 static int sasl_initialized = 0;
399 if ( sasl_initialized ) {
403 sasl_set_alloc( ber_memalloc, ber_memcalloc, ber_memrealloc, ber_memfree );
404 #endif /* CSRIMALLOC */
406 if ( sasl_client_init( NULL ) == SASL_OK ) {
407 sasl_initialized = 1;
415 * SASL encryption support for LBER Sockbufs
418 struct sb_sasl_data {
419 sasl_conn_t *sasl_context;
420 Sockbuf_Buf sec_buf_in;
426 sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg )
428 struct sb_sasl_data *p;
430 assert( sbiod != NULL );
432 p = LBER_MALLOC( sizeof( *p ) );
435 p->sasl_context = (sasl_conn_t *)arg;
436 ber_pvt_sb_buf_init( &p->sec_buf_in );
437 ber_pvt_sb_buf_init( &p->buf_in );
438 ber_pvt_sb_buf_init( &p->buf_out );
439 if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, MIN_BUFF_SIZE ) < 0 ) {
444 sbiod->sbiod_pvt = p;
450 sb_sasl_remove( Sockbuf_IO_Desc *sbiod )
452 struct sb_sasl_data *p;
454 assert( sbiod != NULL );
456 p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
457 ber_pvt_sb_buf_destroy( &p->sec_buf_in );
458 ber_pvt_sb_buf_destroy( &p->buf_in );
459 ber_pvt_sb_buf_destroy( &p->buf_out );
461 sbiod->sbiod_pvt = NULL;
466 sb_sasl_pkt_length( const char *buf, int debuglevel )
471 assert( buf != NULL );
473 tmp = *((long *)buf);
476 if ( size > MAX_BUFF_SIZE ) {
477 /* somebody is trying to mess me up. */
478 ber_log_printf( LDAP_DEBUG_ANY, debuglevel,
479 "sb_sasl_pkt_length: received illegal packet length "
480 "of %lu bytes\n", (unsigned long)size );
481 size = 16; /* this should lead to an error. */
484 return size + 4; /* include the size !!! */
487 /* Drop a processed packet from the input buffer */
489 sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel )
493 len = sec_buf_in->buf_ptr - sec_buf_in->buf_end;
495 memmove( sec_buf_in->buf_base, sec_buf_in->buf_base +
496 sec_buf_in->buf_end, len );
499 sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base,
503 sec_buf_in->buf_end = 0;
505 sec_buf_in->buf_ptr = len;
509 sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
511 struct sb_sasl_data *p;
512 ber_slen_t ret, bufptr;
514 assert( sbiod != NULL );
515 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
517 p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
519 /* Are there anything left in the buffer? */
520 ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len );
527 ber_pvt_sb_buf_destroy( &p->buf_in );
529 /* Read the length of the packet */
530 while ( p->sec_buf_in.buf_ptr < 4 ) {
531 ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base,
532 4 - p->sec_buf_in.buf_ptr );
534 if ( ( ret < 0 ) && ( errno == EINTR ) )
540 p->sec_buf_in.buf_ptr += ret;
543 /* The new packet always starts at p->sec_buf_in.buf_base */
544 ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base,
545 sbiod->sbiod_sb->sb_debug );
547 /* Grow the packet buffer if neccessary */
548 if ( ( p->sec_buf_in.buf_size < ret ) &&
549 ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) {
553 p->sec_buf_in.buf_end = ret;
555 /* Did we read the whole encrypted packet? */
556 while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) {
557 /* No, we have got only a part of it */
558 ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr;
560 ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base +
561 p->sec_buf_in.buf_ptr, ret );
563 if ( ( ret < 0 ) && ( errno == EINTR ) )
569 p->sec_buf_in.buf_ptr += ret;
572 /* Decode the packet */
573 ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base,
574 p->sec_buf_in.buf_end, &p->buf_in.buf_base,
575 (unsigned *)&p->buf_in.buf_end );
576 if ( ret != SASL_OK ) {
577 ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
578 "sb_sasl_read: failed to decode packet: %s\n",
579 sasl_errstring( ret, NULL, NULL ) );
580 sb_sasl_drop_packet( &p->sec_buf_in,
581 sbiod->sbiod_sb->sb_debug );
586 /* Drop the packet from the input buffer */
587 sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug );
589 p->buf_in.buf_size = p->buf_in.buf_end;
591 bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len );
597 sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
599 struct sb_sasl_data *p;
602 assert( sbiod != NULL );
603 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
605 p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
607 /* Are there anything left in the buffer? */
608 if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
609 ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
614 /* now encode the next packet. */
615 ber_pvt_sb_buf_destroy( &p->buf_out );
616 ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base,
617 (unsigned *)&p->buf_out.buf_size );
618 if ( ret != SASL_OK ) {
619 ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
620 "sb_sasl_write: failed to encode packet: %s\n",
621 sasl_errstring( ret, NULL, NULL ) );
624 p->buf_out.buf_end = p->buf_out.buf_size;
626 ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
633 sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
635 struct sb_sasl_data *p;
637 p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
639 if ( opt == LBER_SB_OPT_DATA_READY ) {
640 if ( p->buf_in.buf_ptr != p->buf_in.buf_end )
644 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
647 Sockbuf_IO ldap_pvt_sockbuf_io_sasl =
649 sb_sasl_setup, /* sbi_setup */
650 sb_sasl_remove, /* sbi_remove */
651 sb_sasl_ctrl, /* sbi_ctrl */
652 sb_sasl_read, /* sbi_read */
653 sb_sasl_write, /* sbi_write */
657 int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
659 /* don't install the stuff unless security has been negotiated */
661 if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO,
662 &ldap_pvt_sockbuf_io_sasl ) )
663 ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl,
664 LBER_SBIOD_LEVEL_APPLICATION, ctx_arg );
670 sasl_err2ldap( int saslerr )
676 rc = LDAP_MORE_RESULTS_TO_RETURN;
682 rc = LDAP_LOCAL_ERROR;
688 rc = LDAP_AUTH_UNKNOWN;
691 rc = LDAP_AUTH_UNKNOWN;
694 rc = LDAP_PARAM_ERROR;
698 rc = LDAP_AUTH_UNKNOWN;
701 rc = LDAP_LOCAL_ERROR;
705 assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) );
710 ldap_pvt_sasl_getmechs ( LDAP *ld, char **pmechlist )
712 /* we need to query the server for supported mechs anyway */
713 LDAPMessage *res, *e;
714 char *attrs[] = { "supportedSASLMechanisms", NULL };
715 char **values, *mechlist;
718 Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_getmech\n", 0, 0, 0 );
720 rc = ldap_search_s( ld, NULL, LDAP_SCOPE_BASE,
721 NULL, attrs, 0, &res );
723 if ( rc != LDAP_SUCCESS ) {
727 e = ldap_first_entry( ld, res );
729 if ( ld->ld_errno == LDAP_SUCCESS ) {
730 ld->ld_errno = LDAP_UNAVAILABLE;
735 values = ldap_get_values( ld, e, "supportedSASLMechanisms" );
736 if ( values == NULL ) {
737 ld->ld_errno = LDAP_NO_SUCH_ATTRIBUTE;
742 mechlist = array2str( values );
743 if ( mechlist == NULL ) {
744 ld->ld_errno = LDAP_NO_MEMORY;
745 LDAP_VFREE( values );
750 LDAP_VFREE( values );
753 *pmechlist = mechlist;
762 LDAP_CONST char *mechs,
763 LDAP_CONST sasl_callback_t *callbacks,
764 LDAPControl **sctrls,
765 LDAPControl **cctrls )
769 sasl_ssf_t *ssf = NULL;
771 struct berval ccred, *scred;
773 sasl_interact_t *client_interact = NULL;
774 struct sockaddr_in sin;
776 sasl_security_properties_t secprops;
779 Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_bind\n", 0, 0, 0 );
781 /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
782 if (ld->ld_version < LDAP_VERSION3) {
783 ld->ld_errno = LDAP_NOT_SUPPORTED;
787 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
789 if ( sd == AC_SOCKET_INVALID ) {
790 /* not connected yet */
791 int rc = ldap_open_defconn( ld );
793 if( rc < 0 ) return ld->ld_errno;
794 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
797 /* XXX this doesn't work with PF_LOCAL hosts */
798 host = ldap_host_connected_to( ld->ld_sb );
800 if ( host == NULL ) {
801 ld->ld_errno = LDAP_UNAVAILABLE;
805 if ( ld->ld_sasl_context != NULL ) {
806 sasl_dispose( &ld->ld_sasl_context );
809 saslrc = sasl_client_new( "ldap", host, callbacks, SASL_SECURITY_LAYER,
810 &ld->ld_sasl_context );
814 if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
815 ld->ld_errno = sasl_err2ldap( saslrc );
816 sasl_dispose( &ld->ld_sasl_context );
821 if ( getpeername( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
822 Debug( LDAP_DEBUG_ANY, "SASL: can't query remote IP.\n",
824 ld->ld_errno = LDAP_OPERATIONS_ERROR;
827 sasl_setprop( ld->ld_sasl_context, SASL_IP_REMOTE, &sin );
830 if ( getsockname( sd, (struct sockaddr *)&sin, &len ) == -1 ) {
831 Debug( LDAP_DEBUG_ANY, "SASL: can't query local IP.\n",
833 ld->ld_errno = LDAP_OPERATIONS_ERROR;
836 sasl_setprop( ld->ld_sasl_context, SASL_IP_LOCAL, &sin );
838 memset( &secprops, '\0', sizeof( secprops ) );
839 secprops.min_ssf = ld->ld_options.ldo_sasl_minssf;
840 secprops.max_ssf = ld->ld_options.ldo_sasl_maxssf;
841 secprops.security_flags = SASL_SECURITY_LAYER;
842 secprops.maxbufsize = 65536;
843 sasl_setprop( ld->ld_sasl_context, SASL_SEC_PROPS, &secprops );
848 saslrc = sasl_client_start( ld->ld_sasl_context,
856 ccred.bv_len = credlen;
858 if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
859 ld->ld_errno = sasl_err2ldap( saslrc );
860 sasl_dispose( &ld->ld_sasl_context );
868 sasl_interact_t *client_interact = NULL;
870 rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred );
871 if ( rc == LDAP_SUCCESS ) {
873 } else if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) {
874 if ( ccred.bv_val != NULL ) {
875 LDAP_FREE( ccred.bv_val );
877 sasl_dispose( &ld->ld_sasl_context );
881 if ( ccred.bv_val != NULL ) {
882 LDAP_FREE( ccred.bv_val );
886 saslrc = sasl_client_step( ld->ld_sasl_context,
887 (scred == NULL) ? NULL : scred->bv_val,
888 (scred == NULL) ? 0 : scred->bv_len,
893 ccred.bv_len = credlen;
896 if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
897 ld->ld_errno = sasl_err2ldap( saslrc );
898 sasl_dispose( &ld->ld_sasl_context );
901 } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
903 assert ( rc == LDAP_SUCCESS );
905 if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, (void **)&ssf )
906 == SASL_OK && ssf && *ssf ) {
907 ldap_pvt_sasl_install( ld->ld_sb, ld->ld_sasl_context );
913 /* based on sample/sample-client.c */
915 ldap_pvt_sasl_getsecret(sasl_conn_t *conn,
916 void *context, int id, sasl_secret_t **psecret)
918 struct berval *passphrase = (struct berval *)context;
921 if ( conn == NULL || psecret == NULL || id != SASL_CB_PASS ) {
922 return SASL_BADPARAM;
925 len = (passphrase != NULL) ? (size_t)passphrase->bv_len: 0;
927 *psecret = (sasl_secret_t *) LDAP_MALLOC( sizeof( sasl_secret_t ) + len );
928 if ( *psecret == NULL ) {
932 (*psecret)->len = passphrase->bv_len;
934 if ( passphrase != NULL ) {
935 memcpy((*psecret)->data, passphrase->bv_val, len);
942 ldap_pvt_sasl_getsimple(void *context, int id, const char **result, int *len)
944 const char *value = (const char *)context;
946 if ( result == NULL ) {
947 return SASL_BADPARAM;
952 case SASL_CB_AUTHNAME:
955 *len = value ? strlen( value ) : 0;
957 case SASL_CB_LANGUAGE:
963 return SASL_BADPARAM;
970 ldap_pvt_sasl_get_option( LDAP *ld, int option, void *arg )
978 case LDAP_OPT_X_SASL_MINSSF:
979 *(int *)arg = ld->ld_options.ldo_sasl_minssf;
981 case LDAP_OPT_X_SASL_MAXSSF:
982 *(int *)arg = ld->ld_options.ldo_sasl_maxssf;
984 case LDAP_OPT_X_SASL_ACTSSF:
985 if ( ld->ld_sasl_context == NULL ) {
989 if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF,
990 (void **) &ssf ) != SASL_OK )
1003 ldap_pvt_sasl_set_option( LDAP *ld, int option, void *arg )
1009 case LDAP_OPT_X_SASL_MINSSF:
1010 ld->ld_options.ldo_sasl_minssf = *(int *)arg;
1012 case LDAP_OPT_X_SASL_MAXSSF:
1013 ld->ld_options.ldo_sasl_maxssf = *(int *)arg;
1015 case LDAP_OPT_X_SASL_ACTSSF:
1016 /* This option is read-only */
1024 * ldap_negotiated_sasl_bind_s - bind to the ldap server (and X.500)
1025 * using SASL authentication.
1027 * This routine attempts to authenticate the user referred by the
1028 * authentication id using the provided password. An optional
1029 * authorization identity may be provided. An DN is generally not
1030 * provided [see AuthMethod].
1032 * If the mechanism negotiated does not require a password, the
1033 * passwd field is ignored. [A callback mechanism should really
1036 * LDAP_SUCCESS is returned upon success, the ldap error code
1040 * ldap_negotiated_sasl_bind_s( ld, NULL,
1042 * NULL, NULL, NULL, NULL );
1044 * ldap_negotiated_sasl_bind_s( ld, NULL,
1045 * "user@OPENLDAP.ORG", NULL, NULL,
1046 * "GSSAPI", NULL, NULL, NULL );
1048 * ldap_negotiated_sasl_bind_s( ld, NULL,
1049 * "manager", "dn:cn=user,dc=openldap,dc=org", NULL,
1050 * "DIGEST-MD5", NULL, NULL, NULL );
1052 * ldap_negotiated_sasl_bind_s( ld, NULL,
1053 * "root@OPENLDAP.ORG", "u:user@OPENLDAP.ORG", NULL,
1054 * "GSSAPI", NULL, NULL, NULL );
1056 * ldap_negotiated_sasl_bind_s( ld, NULL,
1057 * "manager", "dn:cn=user,dc=openldap,dc=org", NULL,
1058 * "DIGEST-MD5", NULL, NULL, NULL );
1061 ldap_negotiated_sasl_bind_s(
1063 LDAP_CONST char *dn, /* usually NULL */
1064 LDAP_CONST char *authenticationId,
1065 LDAP_CONST char *authorizationId, /* commonly NULL */
1066 LDAP_CONST char *saslMechanism,
1067 struct berval *passPhrase,
1068 LDAPControl **serverControls,
1069 LDAPControl **clientControls)
1072 sasl_callback_t callbacks[4];
1075 Debug( LDAP_DEBUG_TRACE, "ldap_negotiated_sasl_bind_s\n", 0, 0, 0 );
1077 if( saslMechanism == NULL || *saslMechanism == '\0' ) {
1079 rc = ldap_pvt_sasl_getmechs( ld, &mechs );
1081 if( rc != LDAP_SUCCESS ) {
1085 saslMechanism = mechs;
1088 /* SASL Authentication Identity */
1089 callbacks[n=0].id = SASL_CB_AUTHNAME;
1090 callbacks[n].proc = ldap_pvt_sasl_getsimple;
1091 callbacks[n].context = (void *)authenticationId;
1093 /* SASL Authorization Identity (userid) */
1094 if( authorizationId != NULL ) {
1095 callbacks[++n].id = SASL_CB_USER;
1096 callbacks[n].proc = ldap_pvt_sasl_getsimple;
1097 callbacks[n].context = (void *)authorizationId;
1100 callbacks[++n].id = SASL_CB_PASS;
1101 callbacks[n].proc = ldap_pvt_sasl_getsecret;
1102 callbacks[n].context = (void *)passPhrase;
1104 callbacks[++n].id = SASL_CB_LIST_END;
1105 callbacks[n].proc = NULL;
1106 callbacks[n].context = NULL;
1108 assert( n * sizeof(sasl_callback_t) < sizeof(callbacks) );
1110 rc = ldap_pvt_sasl_bind(ld, dn, saslMechanism, callbacks,
1111 serverControls, clientControls);
1115 #endif /* HAVE_CYRUS_SASL */