10Sstevel@tonic-gate /*
27068Schinlong * CDDL HEADER START
37068Schinlong *
47068Schinlong * The contents of this file are subject to the terms of the
57068Schinlong * Common Development and Distribution License (the "License").
67068Schinlong * You may not use this file except in compliance with the License.
77068Schinlong *
87068Schinlong * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97068Schinlong * or http://www.opensolaris.org/os/licensing.
107068Schinlong * See the License for the specific language governing permissions
117068Schinlong * and limitations under the License.
127068Schinlong *
137068Schinlong * When distributing Covered Code, include this CDDL HEADER in each
147068Schinlong * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157068Schinlong * If applicable, add the following below this CDDL HEADER, with the
167068Schinlong * fields enclosed by brackets "[]" replaced with your own identifying
177068Schinlong * information: Portions Copyright [yyyy] [name of copyright owner]
187068Schinlong *
197068Schinlong * CDDL HEADER END
207068Schinlong */
217068Schinlong /*
22*12023SDoug.Leavitt@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #ifdef LDAP_SASLIO_HOOKS
270Sstevel@tonic-gate #include <assert.h>
280Sstevel@tonic-gate #include "ldap-int.h"
290Sstevel@tonic-gate #include "../ber/lber-int.h"
300Sstevel@tonic-gate #include <sasl/sasl.h>
310Sstevel@tonic-gate #include <thread.h>
320Sstevel@tonic-gate #include <synch.h>
330Sstevel@tonic-gate
340Sstevel@tonic-gate #define SEARCH_TIMEOUT_SECS 120
350Sstevel@tonic-gate #define NSLDAPI_SM_BUF 128
360Sstevel@tonic-gate
370Sstevel@tonic-gate extern void *sasl_create_context(void);
380Sstevel@tonic-gate extern void sasl_free_context(void *ctx);
390Sstevel@tonic-gate extern int _sasl_client_init(void *ctx, const sasl_callback_t *callbacks);
400Sstevel@tonic-gate extern int _sasl_client_new(void *ctx, const char *service,
410Sstevel@tonic-gate const char *serverFQDN, const char *iplocalport,
420Sstevel@tonic-gate const char *ipremoteport,
430Sstevel@tonic-gate const sasl_callback_t *prompt_supp,
440Sstevel@tonic-gate unsigned flags, sasl_conn_t **pconn);
450Sstevel@tonic-gate extern int _sasl_server_init(void *ctx,
460Sstevel@tonic-gate const sasl_callback_t *callbacks, const char *appname);
470Sstevel@tonic-gate extern int _sasl_server_new(void *ctx, const char *service,
480Sstevel@tonic-gate const char *serverFQDN, const char *user_realm,
490Sstevel@tonic-gate const char *iplocalport, const char *ipremoteport,
500Sstevel@tonic-gate const sasl_callback_t *callbacks,
510Sstevel@tonic-gate unsigned flags, sasl_conn_t **pconn);
520Sstevel@tonic-gate
530Sstevel@tonic-gate static int nsldapi_sasl_close( LDAP *ld, Sockbuf *sb );
54*12023SDoug.Leavitt@Sun.COM static void destroy_sasliobuf(Sockbuf *sb);
550Sstevel@tonic-gate
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate * SASL Dependent routines
580Sstevel@tonic-gate *
590Sstevel@tonic-gate * SASL security and integrity options are supported through the
600Sstevel@tonic-gate * use of the extended I/O functionality. Because the extended
610Sstevel@tonic-gate * I/O functions may already be in use prior to enabling encryption,
620Sstevel@tonic-gate * when SASL encryption is enabled, these routine interpose themselves
630Sstevel@tonic-gate * over the existng extended I/O routines and add an additional level
640Sstevel@tonic-gate * of indirection.
650Sstevel@tonic-gate * IE: Before SASL: client->libldap->lber->extio
660Sstevel@tonic-gate * After SASL: client->libldap->lber->saslio->extio
670Sstevel@tonic-gate * Any extio functions are still used for the raw i/O [IE prldap]
680Sstevel@tonic-gate * but SASL will decrypt before passing to lber.
690Sstevel@tonic-gate * SASL cannot decrypt a stream so full packets must be read
700Sstevel@tonic-gate * before proceeding.
710Sstevel@tonic-gate */
720Sstevel@tonic-gate
nsldapi_sasl_fail()730Sstevel@tonic-gate static int nsldapi_sasl_fail()
740Sstevel@tonic-gate {
750Sstevel@tonic-gate return( SASL_FAIL );
760Sstevel@tonic-gate }
770Sstevel@tonic-gate
780Sstevel@tonic-gate /*
790Sstevel@tonic-gate * Global SASL Init data
800Sstevel@tonic-gate */
810Sstevel@tonic-gate
820Sstevel@tonic-gate static sasl_callback_t client_callbacks[] = {
830Sstevel@tonic-gate { SASL_CB_GETOPT, nsldapi_sasl_fail, NULL },
840Sstevel@tonic-gate { SASL_CB_GETREALM, NULL, NULL },
850Sstevel@tonic-gate { SASL_CB_USER, NULL, NULL },
860Sstevel@tonic-gate { SASL_CB_AUTHNAME, NULL, NULL },
870Sstevel@tonic-gate { SASL_CB_PASS, NULL, NULL },
880Sstevel@tonic-gate { SASL_CB_ECHOPROMPT, NULL, NULL },
890Sstevel@tonic-gate { SASL_CB_NOECHOPROMPT, NULL, NULL },
900Sstevel@tonic-gate { SASL_CB_LIST_END, NULL, NULL }
910Sstevel@tonic-gate };
920Sstevel@tonic-gate static mutex_t sasl_mutex = DEFAULTMUTEX;
930Sstevel@tonic-gate static int nsldapi_sasl_inited = 0;
940Sstevel@tonic-gate static void *gctx; /* intentially not freed - avoid libsasl re-inits */
950Sstevel@tonic-gate
nsldapi_sasl_init(void)960Sstevel@tonic-gate int nsldapi_sasl_init( void )
970Sstevel@tonic-gate {
980Sstevel@tonic-gate int saslrc;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate mutex_lock(&sasl_mutex);
1010Sstevel@tonic-gate if ( nsldapi_sasl_inited ) {
1020Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
1030Sstevel@tonic-gate return( 0 );
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate if ((gctx = (void *)sasl_create_context()) != NULL) {
1060Sstevel@tonic-gate saslrc = _sasl_client_init(gctx, client_callbacks);
1070Sstevel@tonic-gate if (saslrc == SASL_OK ) {
1080Sstevel@tonic-gate nsldapi_sasl_inited = 1;
1090Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
1100Sstevel@tonic-gate return( 0 );
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
1140Sstevel@tonic-gate return( -1 );
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate * SASL encryption routines
1190Sstevel@tonic-gate */
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate /*
1220Sstevel@tonic-gate * Get the 4 octet header [size] for a sasl encrypted buffer.
1230Sstevel@tonic-gate * See RFC222 [section 3].
1240Sstevel@tonic-gate */
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate static int
nsldapi_sasl_pktlen(char * buf,int maxbufsize)1270Sstevel@tonic-gate nsldapi_sasl_pktlen( char *buf, int maxbufsize )
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate int size;
1300Sstevel@tonic-gate
1317068Schinlong #if defined( _WINDOWS ) || defined( _WIN32 )
1320Sstevel@tonic-gate size = ntohl(*(long *)buf);
1337068Schinlong #else
1347068Schinlong size = ntohl(*(uint32_t *)buf);
1357068Schinlong #endif
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate if ( size < 0 || size > maxbufsize ) {
1380Sstevel@tonic-gate return (-1 );
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate return( size + 4 ); /* include the first 4 bytes */
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate static int
nsldapi_sasl_read(int s,void * buf,int len,struct lextiof_socket_private * arg)1450Sstevel@tonic-gate nsldapi_sasl_read( int s, void *buf, int len,
1460Sstevel@tonic-gate struct lextiof_socket_private *arg)
1470Sstevel@tonic-gate {
1480Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
1490Sstevel@tonic-gate LDAP *ld;
1500Sstevel@tonic-gate const char *dbuf;
1510Sstevel@tonic-gate char *cp;
1520Sstevel@tonic-gate int ret;
1530Sstevel@tonic-gate unsigned dlen, blen;
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate if (sb == NULL) {
1560Sstevel@tonic-gate return( -1 );
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate ld = (LDAP *)sb->sb_sasl_prld;
1600Sstevel@tonic-gate if (ld == NULL) {
1610Sstevel@tonic-gate return( -1 );
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate /* Is there anything left in the existing buffer? */
1650Sstevel@tonic-gate if ((ret = sb->sb_sasl_ilen) > 0) {
1660Sstevel@tonic-gate ret = (ret > len ? len : ret);
1670Sstevel@tonic-gate SAFEMEMCPY( buf, sb->sb_sasl_iptr, ret );
1680Sstevel@tonic-gate if (ret == sb->sb_sasl_ilen) {
1690Sstevel@tonic-gate sb->sb_sasl_ilen = 0;
1700Sstevel@tonic-gate sb->sb_sasl_iptr = NULL;
1710Sstevel@tonic-gate } else {
1720Sstevel@tonic-gate sb->sb_sasl_ilen -= ret;
1730Sstevel@tonic-gate sb->sb_sasl_iptr += ret;
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate return( ret );
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate /* buffer is empty - fill it */
1790Sstevel@tonic-gate cp = sb->sb_sasl_ibuf;
1800Sstevel@tonic-gate dlen = 0;
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate /* Read the length of the packet */
1830Sstevel@tonic-gate while ( dlen < 4 ) {
1840Sstevel@tonic-gate if (sb->sb_sasl_fns.lbextiofn_read != NULL) {
1850Sstevel@tonic-gate ret = sb->sb_sasl_fns.lbextiofn_read(
1860Sstevel@tonic-gate s, cp, 4 - dlen,
1870Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg);
1880Sstevel@tonic-gate } else {
1890Sstevel@tonic-gate ret = read( sb->sb_sd, cp, 4 - dlen );
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate #ifdef EINTR
1920Sstevel@tonic-gate if ( ( ret < 0 ) && ( LDAP_GET_ERRNO(ld) == EINTR ) )
1930Sstevel@tonic-gate continue;
1940Sstevel@tonic-gate #endif
1950Sstevel@tonic-gate if ( ret <= 0 )
1960Sstevel@tonic-gate return( ret );
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate cp += ret;
1990Sstevel@tonic-gate dlen += ret;
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate blen = 4;
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate ret = nsldapi_sasl_pktlen( sb->sb_sasl_ibuf, sb->sb_sasl_bfsz );
2050Sstevel@tonic-gate if (ret < 0) {
2060Sstevel@tonic-gate LDAP_SET_ERRNO(ld, EIO);
2070Sstevel@tonic-gate return( -1 );
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate dlen = ret - dlen;
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate /* read the rest of the encrypted packet */
2120Sstevel@tonic-gate while ( dlen > 0 ) {
2130Sstevel@tonic-gate if (sb->sb_sasl_fns.lbextiofn_read != NULL) {
2140Sstevel@tonic-gate ret = sb->sb_sasl_fns.lbextiofn_read(
2150Sstevel@tonic-gate s, cp, dlen,
2160Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg);
2170Sstevel@tonic-gate } else {
2180Sstevel@tonic-gate ret = read( sb->sb_sd, cp, dlen );
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate #ifdef EINTR
2220Sstevel@tonic-gate if ( ( ret < 0 ) && ( LDAP_GET_ERRNO(ld) == EINTR ) )
2230Sstevel@tonic-gate continue;
2240Sstevel@tonic-gate #endif
2250Sstevel@tonic-gate if ( ret <= 0 )
2260Sstevel@tonic-gate return( ret );
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate cp += ret;
2290Sstevel@tonic-gate blen += ret;
2300Sstevel@tonic-gate dlen -= ret;
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /* Decode the packet */
2340Sstevel@tonic-gate ret = sasl_decode( sb->sb_sasl_ctx,
2350Sstevel@tonic-gate sb->sb_sasl_ibuf, blen,
2360Sstevel@tonic-gate &dbuf, &dlen);
2370Sstevel@tonic-gate if ( ret != SASL_OK ) {
2380Sstevel@tonic-gate /* sb_sasl_read: failed to decode packet, drop it, error */
2390Sstevel@tonic-gate sb->sb_sasl_iptr = NULL;
2400Sstevel@tonic-gate sb->sb_sasl_ilen = 0;
2410Sstevel@tonic-gate LDAP_SET_ERRNO(ld, EIO);
2420Sstevel@tonic-gate return( -1 );
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate /* copy decrypted packet to the input buffer */
2460Sstevel@tonic-gate SAFEMEMCPY( sb->sb_sasl_ibuf, dbuf, dlen );
2470Sstevel@tonic-gate sb->sb_sasl_iptr = sb->sb_sasl_ibuf;
2480Sstevel@tonic-gate sb->sb_sasl_ilen = dlen;
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate ret = (dlen > (unsigned) len ? len : dlen);
2510Sstevel@tonic-gate SAFEMEMCPY( buf, sb->sb_sasl_iptr, ret );
2520Sstevel@tonic-gate if (ret == sb->sb_sasl_ilen) {
2530Sstevel@tonic-gate sb->sb_sasl_ilen = 0;
2540Sstevel@tonic-gate sb->sb_sasl_iptr = NULL;
2550Sstevel@tonic-gate } else {
2560Sstevel@tonic-gate sb->sb_sasl_ilen -= ret;
2570Sstevel@tonic-gate sb->sb_sasl_iptr += ret;
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate return( ret );
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate static int
nsldapi_sasl_write(int s,const void * buf,int len,struct lextiof_socket_private * arg)2630Sstevel@tonic-gate nsldapi_sasl_write( int s, const void *buf, int len,
2640Sstevel@tonic-gate struct lextiof_socket_private *arg)
2650Sstevel@tonic-gate {
2660Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
267*12023SDoug.Leavitt@Sun.COM int ret = 0;
268*12023SDoug.Leavitt@Sun.COM const char *obuf, *optr, *cbuf = (const char *)buf;
269*12023SDoug.Leavitt@Sun.COM unsigned olen, clen, tlen = 0;
270*12023SDoug.Leavitt@Sun.COM unsigned *maxbuf;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate if (sb == NULL) {
2730Sstevel@tonic-gate return( -1 );
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
276*12023SDoug.Leavitt@Sun.COM ret = sasl_getprop(sb->sb_sasl_ctx, SASL_MAXOUTBUF,
277*12023SDoug.Leavitt@Sun.COM (const void **)&maxbuf);
2780Sstevel@tonic-gate if ( ret != SASL_OK ) {
279*12023SDoug.Leavitt@Sun.COM /* just a sanity check, should never happen */
2800Sstevel@tonic-gate return( -1 );
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate
283*12023SDoug.Leavitt@Sun.COM while (len > 0) {
284*12023SDoug.Leavitt@Sun.COM clen = (len > *maxbuf) ? *maxbuf : len;
285*12023SDoug.Leavitt@Sun.COM /* encode the next packet. */
286*12023SDoug.Leavitt@Sun.COM ret = sasl_encode( sb->sb_sasl_ctx, cbuf, clen, &obuf, &olen);
287*12023SDoug.Leavitt@Sun.COM if ( ret != SASL_OK ) {
288*12023SDoug.Leavitt@Sun.COM /* XXX Log error? "sb_sasl_write: failed to encode packet..." */
289*12023SDoug.Leavitt@Sun.COM return( -1 );
2900Sstevel@tonic-gate }
291*12023SDoug.Leavitt@Sun.COM /* Write everything now, buffer is only good until next sasl_encode */
292*12023SDoug.Leavitt@Sun.COM optr = obuf;
293*12023SDoug.Leavitt@Sun.COM while (olen > 0) {
294*12023SDoug.Leavitt@Sun.COM if (sb->sb_sasl_fns.lbextiofn_write != NULL) {
295*12023SDoug.Leavitt@Sun.COM ret = sb->sb_sasl_fns.lbextiofn_write(
296*12023SDoug.Leavitt@Sun.COM s, optr, olen,
297*12023SDoug.Leavitt@Sun.COM sb->sb_sasl_fns.lbextiofn_socket_arg);
298*12023SDoug.Leavitt@Sun.COM } else {
299*12023SDoug.Leavitt@Sun.COM ret = write( sb->sb_sd, optr, olen);
300*12023SDoug.Leavitt@Sun.COM }
301*12023SDoug.Leavitt@Sun.COM if ( ret < 0 )
302*12023SDoug.Leavitt@Sun.COM return( ret );
303*12023SDoug.Leavitt@Sun.COM optr += ret;
304*12023SDoug.Leavitt@Sun.COM olen -= ret;
305*12023SDoug.Leavitt@Sun.COM }
306*12023SDoug.Leavitt@Sun.COM len -= clen;
307*12023SDoug.Leavitt@Sun.COM cbuf += clen;
308*12023SDoug.Leavitt@Sun.COM tlen += clen;
3090Sstevel@tonic-gate }
310*12023SDoug.Leavitt@Sun.COM return( tlen );
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate static int
nsldapi_sasl_poll(LDAP_X_PollFD fds[],int nfds,int timeout,struct lextiof_session_private * arg)3140Sstevel@tonic-gate nsldapi_sasl_poll(
3150Sstevel@tonic-gate LDAP_X_PollFD fds[], int nfds, int timeout,
3160Sstevel@tonic-gate struct lextiof_session_private *arg )
3170Sstevel@tonic-gate {
3180Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
3190Sstevel@tonic-gate LDAP *ld;
3200Sstevel@tonic-gate int i;
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate if (sb == NULL) {
3230Sstevel@tonic-gate return( -1 );
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate ld = (LDAP *)sb->sb_sasl_prld;
3260Sstevel@tonic-gate if (ld == NULL) {
3270Sstevel@tonic-gate return( -1 );
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate if (fds && nfds > 0) {
3310Sstevel@tonic-gate for(i = 0; i < nfds; i++) {
3320Sstevel@tonic-gate if (fds[i].lpoll_socketarg ==
3330Sstevel@tonic-gate (struct lextiof_socket_private *)sb) {
3340Sstevel@tonic-gate fds[i].lpoll_socketarg =
3350Sstevel@tonic-gate (struct lextiof_socket_private *)
3360Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg;
3370Sstevel@tonic-gate }
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate return ( ld->ld_sasl_io_fns.lextiof_poll( fds, nfds, timeout,
3420Sstevel@tonic-gate (void *)ld->ld_sasl_io_fns.lextiof_session_arg) );
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate /* no encryption indirect routines */
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate static int
nsldapi_sasl_ne_read(int s,void * buf,int len,struct lextiof_socket_private * arg)3480Sstevel@tonic-gate nsldapi_sasl_ne_read( int s, void *buf, int len,
3490Sstevel@tonic-gate struct lextiof_socket_private *arg)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate if (sb == NULL) {
3540Sstevel@tonic-gate return( -1 );
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate return( sb->sb_sasl_fns.lbextiofn_read( s, buf, len,
3580Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg) );
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate static int
nsldapi_sasl_ne_write(int s,const void * buf,int len,struct lextiof_socket_private * arg)3620Sstevel@tonic-gate nsldapi_sasl_ne_write( int s, const void *buf, int len,
3630Sstevel@tonic-gate struct lextiof_socket_private *arg)
3640Sstevel@tonic-gate {
3650Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate if (sb == NULL) {
3680Sstevel@tonic-gate return( -1 );
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate return( sb->sb_sasl_fns.lbextiofn_write( s, buf, len,
3720Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg) );
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate static int
nsldapi_sasl_close_socket(int s,struct lextiof_socket_private * arg)3760Sstevel@tonic-gate nsldapi_sasl_close_socket(int s, struct lextiof_socket_private *arg )
3770Sstevel@tonic-gate {
3780Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
3790Sstevel@tonic-gate LDAP *ld;
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate if (sb == NULL) {
3820Sstevel@tonic-gate return( -1 );
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate ld = (LDAP *)sb->sb_sasl_prld;
3850Sstevel@tonic-gate if (ld == NULL) {
3860Sstevel@tonic-gate return( -1 );
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate /* undo function pointer interposing */
3890Sstevel@tonic-gate ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &ld->ld_sasl_io_fns );
3900Sstevel@tonic-gate ber_sockbuf_set_option( sb,
3910Sstevel@tonic-gate LBER_SOCKBUF_OPT_EXT_IO_FNS,
3920Sstevel@tonic-gate (void *)&sb->sb_sasl_fns);
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate /* undo SASL */
3950Sstevel@tonic-gate nsldapi_sasl_close( ld, sb );
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate return ( ld->ld_sasl_io_fns.lextiof_close( s,
3980Sstevel@tonic-gate (struct lextiof_socket_private *)
3990Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg ) );
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate /*
4030Sstevel@tonic-gate * install encryption routines if security has been negotiated
4040Sstevel@tonic-gate */
4050Sstevel@tonic-gate static int
nsldapi_sasl_install(LDAP * ld,Sockbuf * sb,void * ctx_arg,sasl_ssf_t * ssf)4060Sstevel@tonic-gate nsldapi_sasl_install( LDAP *ld, Sockbuf *sb, void *ctx_arg, sasl_ssf_t *ssf)
4070Sstevel@tonic-gate {
4080Sstevel@tonic-gate struct lber_x_ext_io_fns fns;
4090Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns;
4100Sstevel@tonic-gate sasl_security_properties_t *secprops;
4110Sstevel@tonic-gate int rc, value;
4120Sstevel@tonic-gate int bufsiz;
4130Sstevel@tonic-gate int encrypt = 0;
4140Sstevel@tonic-gate
4150Sstevel@tonic-gate if (ssf && *ssf) {
4160Sstevel@tonic-gate encrypt = 1;
4170Sstevel@tonic-gate }
418*12023SDoug.Leavitt@Sun.COM if ( sb == NULL ) {
419*12023SDoug.Leavitt@Sun.COM return( LDAP_LOCAL_ERROR );
420*12023SDoug.Leavitt@Sun.COM }
4210Sstevel@tonic-gate rc = ber_sockbuf_get_option( sb,
4220Sstevel@tonic-gate LBER_SOCKBUF_OPT_TO_FILE_ONLY,
4230Sstevel@tonic-gate (void *) &value);
4240Sstevel@tonic-gate if (rc != 0 || value != 0)
4250Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate if (encrypt) {
4280Sstevel@tonic-gate /* initialize input buffer - use MAX SIZE to avoid reallocs */
4290Sstevel@tonic-gate sb->sb_sasl_ctx = (sasl_conn_t *)ctx_arg;
4300Sstevel@tonic-gate rc = sasl_getprop( sb->sb_sasl_ctx, SASL_SEC_PROPS,
4310Sstevel@tonic-gate (const void **)&secprops );
4320Sstevel@tonic-gate if (rc != SASL_OK)
4330Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
4340Sstevel@tonic-gate bufsiz = secprops->maxbufsize;
4350Sstevel@tonic-gate if (bufsiz <= 0) {
4360Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate if ((sb->sb_sasl_ibuf = NSLDAPI_MALLOC(bufsiz)) == NULL) {
4390Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate sb->sb_sasl_iptr = NULL;
4420Sstevel@tonic-gate sb->sb_sasl_bfsz = bufsiz;
4430Sstevel@tonic-gate sb->sb_sasl_ilen = 0;
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /* Reset Session then Socket Args */
4470Sstevel@tonic-gate /* Get old values */
4480Sstevel@tonic-gate (void) memset( &sb->sb_sasl_fns, 0, LBER_X_EXTIO_FNS_SIZE);
4490Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
4500Sstevel@tonic-gate rc = ber_sockbuf_get_option( sb,
4510Sstevel@tonic-gate LBER_SOCKBUF_OPT_EXT_IO_FNS,
4520Sstevel@tonic-gate (void *)&sb->sb_sasl_fns);
453*12023SDoug.Leavitt@Sun.COM if (rc != 0) {
454*12023SDoug.Leavitt@Sun.COM destroy_sasliobuf(sb);
455*12023SDoug.Leavitt@Sun.COM return( LDAP_LOCAL_ERROR );
456*12023SDoug.Leavitt@Sun.COM }
4570Sstevel@tonic-gate memset( &ld->ld_sasl_io_fns, 0, sizeof(iofns));
4580Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
4590Sstevel@tonic-gate rc = ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS,
4600Sstevel@tonic-gate &ld->ld_sasl_io_fns );
461*12023SDoug.Leavitt@Sun.COM if (rc != 0 ) {
462*12023SDoug.Leavitt@Sun.COM destroy_sasliobuf(sb);
4630Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
464*12023SDoug.Leavitt@Sun.COM }
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate /* Set new values */
4670Sstevel@tonic-gate if ( ld->ld_sasl_io_fns.lextiof_read != NULL ||
4680Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_write != NULL ||
4690Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_poll != NULL ||
4700Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_connect != NULL ||
4710Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_close != NULL ) {
4720Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns));
4730Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
4740Sstevel@tonic-gate if (encrypt) {
4750Sstevel@tonic-gate iofns.lextiof_read = nsldapi_sasl_read;
4760Sstevel@tonic-gate iofns.lextiof_write = nsldapi_sasl_write;
4770Sstevel@tonic-gate iofns.lextiof_poll = nsldapi_sasl_poll;
4780Sstevel@tonic-gate } else {
4790Sstevel@tonic-gate iofns.lextiof_read = nsldapi_sasl_ne_read;
4800Sstevel@tonic-gate iofns.lextiof_write = nsldapi_sasl_ne_write;
4810Sstevel@tonic-gate iofns.lextiof_poll = nsldapi_sasl_poll;
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate iofns.lextiof_connect = ld->ld_sasl_io_fns.lextiof_connect;
4840Sstevel@tonic-gate iofns.lextiof_close = nsldapi_sasl_close_socket;
4850Sstevel@tonic-gate iofns.lextiof_newhandle = ld->ld_sasl_io_fns.lextiof_newhandle;
4860Sstevel@tonic-gate iofns.lextiof_disposehandle =
4870Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_disposehandle;
4880Sstevel@tonic-gate iofns.lextiof_session_arg =
4890Sstevel@tonic-gate (void *) sb;
4900Sstevel@tonic-gate /* ld->ld_sasl_io_fns.lextiof_session_arg; */
4910Sstevel@tonic-gate rc = ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS,
4920Sstevel@tonic-gate &iofns );
493*12023SDoug.Leavitt@Sun.COM if (rc != 0 ) {
494*12023SDoug.Leavitt@Sun.COM destroy_sasliobuf(sb);
4950Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
496*12023SDoug.Leavitt@Sun.COM }
4970Sstevel@tonic-gate sb->sb_sasl_prld = (void *)ld;
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate if (encrypt) {
5010Sstevel@tonic-gate (void) memset( &fns, 0, LBER_X_EXTIO_FNS_SIZE);
5020Sstevel@tonic-gate fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
5030Sstevel@tonic-gate fns.lbextiofn_read = nsldapi_sasl_read;
5040Sstevel@tonic-gate fns.lbextiofn_write = nsldapi_sasl_write;
5050Sstevel@tonic-gate fns.lbextiofn_socket_arg =
5060Sstevel@tonic-gate (void *) sb;
5070Sstevel@tonic-gate /* (void *)sb->sb_sasl_fns.lbextiofn_socket_arg; */
5080Sstevel@tonic-gate rc = ber_sockbuf_set_option( sb,
5090Sstevel@tonic-gate LBER_SOCKBUF_OPT_EXT_IO_FNS,
5100Sstevel@tonic-gate (void *)&fns);
511*12023SDoug.Leavitt@Sun.COM if (rc != 0) {
512*12023SDoug.Leavitt@Sun.COM destroy_sasliobuf(sb);
5130Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
514*12023SDoug.Leavitt@Sun.COM }
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate return( LDAP_SUCCESS );
5180Sstevel@tonic-gate }
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate static int
nsldapi_sasl_cvterrno(LDAP * ld,int err,char * msg)521*12023SDoug.Leavitt@Sun.COM nsldapi_sasl_cvterrno( LDAP *ld, int err, char *msg )
5220Sstevel@tonic-gate {
5230Sstevel@tonic-gate int rc = LDAP_LOCAL_ERROR;
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate switch (err) {
5260Sstevel@tonic-gate case SASL_OK:
5270Sstevel@tonic-gate rc = LDAP_SUCCESS;
5280Sstevel@tonic-gate break;
5290Sstevel@tonic-gate case SASL_NOMECH:
5300Sstevel@tonic-gate rc = LDAP_AUTH_UNKNOWN;
5310Sstevel@tonic-gate break;
5320Sstevel@tonic-gate case SASL_BADSERV:
5330Sstevel@tonic-gate rc = LDAP_CONNECT_ERROR;
5340Sstevel@tonic-gate break;
5350Sstevel@tonic-gate case SASL_DISABLED:
5360Sstevel@tonic-gate case SASL_ENCRYPT:
5370Sstevel@tonic-gate case SASL_EXPIRED:
5380Sstevel@tonic-gate case SASL_NOUSERPASS:
5390Sstevel@tonic-gate case SASL_NOVERIFY:
5400Sstevel@tonic-gate case SASL_PWLOCK:
5410Sstevel@tonic-gate case SASL_TOOWEAK:
5420Sstevel@tonic-gate case SASL_UNAVAIL:
5430Sstevel@tonic-gate case SASL_WEAKPASS:
5440Sstevel@tonic-gate rc = LDAP_INAPPROPRIATE_AUTH;
5450Sstevel@tonic-gate break;
5460Sstevel@tonic-gate case SASL_BADAUTH:
5470Sstevel@tonic-gate case SASL_NOAUTHZ:
5480Sstevel@tonic-gate rc = LDAP_INVALID_CREDENTIALS;
5490Sstevel@tonic-gate break;
5500Sstevel@tonic-gate case SASL_NOMEM:
5510Sstevel@tonic-gate rc = LDAP_NO_MEMORY;
5520Sstevel@tonic-gate break;
5530Sstevel@tonic-gate case SASL_NOUSER:
5540Sstevel@tonic-gate rc = LDAP_NO_SUCH_OBJECT;
5550Sstevel@tonic-gate break;
5560Sstevel@tonic-gate case SASL_CONTINUE:
5570Sstevel@tonic-gate case SASL_FAIL:
5580Sstevel@tonic-gate case SASL_INTERACT:
5590Sstevel@tonic-gate default:
5600Sstevel@tonic-gate rc = LDAP_LOCAL_ERROR;
5610Sstevel@tonic-gate break;
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate
564*12023SDoug.Leavitt@Sun.COM LDAP_SET_LDERRNO( ld, rc, NULL, msg );
5650Sstevel@tonic-gate return( rc );
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate int
nsldapi_sasl_open(LDAP * ld)5690Sstevel@tonic-gate nsldapi_sasl_open(LDAP *ld)
5700Sstevel@tonic-gate {
5710Sstevel@tonic-gate Sockbuf *sb;
5720Sstevel@tonic-gate char * host;
5730Sstevel@tonic-gate int saslrc;
574*12023SDoug.Leavitt@Sun.COM sasl_conn_t *ctx = NULL;
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate if (ld == NULL) {
5770Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
5780Sstevel@tonic-gate }
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate if (ld->ld_defconn == NULL) {
5810Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
5820Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate sb = ld->ld_defconn->lconn_sb;
5850Sstevel@tonic-gate host = ld->ld_defhost;
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate if ( sb == NULL || host == NULL ) {
5880Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
5890Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate
592*12023SDoug.Leavitt@Sun.COM if (sb->sb_sasl_ctx) {
593*12023SDoug.Leavitt@Sun.COM sasl_dispose(&sb->sb_sasl_ctx);
594*12023SDoug.Leavitt@Sun.COM sb->sb_sasl_ctx = NULL;
595*12023SDoug.Leavitt@Sun.COM }
596*12023SDoug.Leavitt@Sun.COM
5970Sstevel@tonic-gate /* SASL is not properly initialized */
5980Sstevel@tonic-gate mutex_lock(&sasl_mutex);
5990Sstevel@tonic-gate if (gctx == NULL) {
6000Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
6010Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
6020Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate saslrc = _sasl_client_new(gctx, "ldap", host,
6060Sstevel@tonic-gate NULL, NULL, /* iplocal ipremote strings currently unused */
6070Sstevel@tonic-gate NULL, 0, &ctx );
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate if ( saslrc != SASL_OK ) {
6100Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
611*12023SDoug.Leavitt@Sun.COM sasl_dispose(&ctx);
612*12023SDoug.Leavitt@Sun.COM return( nsldapi_sasl_cvterrno( ld, saslrc, NULL ) );
6130Sstevel@tonic-gate }
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate sb->sb_sasl_ctx = (void *)ctx;
6160Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate return( LDAP_SUCCESS );
6190Sstevel@tonic-gate }
6200Sstevel@tonic-gate
62110285SMilan.Jurik@Sun.COM static void
destroy_sasliobuf(Sockbuf * sb)62210285SMilan.Jurik@Sun.COM destroy_sasliobuf(Sockbuf *sb)
62310285SMilan.Jurik@Sun.COM {
62410285SMilan.Jurik@Sun.COM if (sb != NULL && sb->sb_sasl_ibuf != NULL) {
62510285SMilan.Jurik@Sun.COM NSLDAPI_FREE(sb->sb_sasl_ibuf);
62610285SMilan.Jurik@Sun.COM sb->sb_sasl_ibuf = NULL;
627*12023SDoug.Leavitt@Sun.COM sb->sb_sasl_iptr = NULL;
628*12023SDoug.Leavitt@Sun.COM sb->sb_sasl_bfsz = 0;
629*12023SDoug.Leavitt@Sun.COM sb->sb_sasl_ilen = 0;
63010285SMilan.Jurik@Sun.COM }
63110285SMilan.Jurik@Sun.COM }
63210285SMilan.Jurik@Sun.COM
6330Sstevel@tonic-gate static int
nsldapi_sasl_close(LDAP * ld,Sockbuf * sb)6340Sstevel@tonic-gate nsldapi_sasl_close( LDAP *ld, Sockbuf *sb )
6350Sstevel@tonic-gate {
6360Sstevel@tonic-gate sasl_conn_t *ctx = (sasl_conn_t *)sb->sb_sasl_ctx;
6370Sstevel@tonic-gate
63810285SMilan.Jurik@Sun.COM destroy_sasliobuf(sb);
63910285SMilan.Jurik@Sun.COM
6400Sstevel@tonic-gate if( ctx != NULL ) {
6410Sstevel@tonic-gate sasl_dispose( &ctx );
6420Sstevel@tonic-gate sb->sb_sasl_ctx = NULL;
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate return( LDAP_SUCCESS );
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate static int
nsldapi_sasl_do_bind(LDAP * ld,const char * dn,const char * mechs,unsigned flags,LDAP_SASL_INTERACT_PROC * callback,void * defaults,LDAPControl ** sctrl,LDAPControl ** cctrl)6480Sstevel@tonic-gate nsldapi_sasl_do_bind( LDAP *ld, const char *dn,
6490Sstevel@tonic-gate const char *mechs, unsigned flags,
6500Sstevel@tonic-gate LDAP_SASL_INTERACT_PROC *callback, void *defaults,
6510Sstevel@tonic-gate LDAPControl **sctrl, LDAPControl **cctrl )
6520Sstevel@tonic-gate {
6530Sstevel@tonic-gate sasl_interact_t *prompts = NULL;
6540Sstevel@tonic-gate sasl_conn_t *ctx;
6550Sstevel@tonic-gate sasl_ssf_t *ssf = NULL;
6560Sstevel@tonic-gate const char *mech = NULL;
6570Sstevel@tonic-gate int saslrc, rc;
6580Sstevel@tonic-gate struct berval ccred;
6590Sstevel@tonic-gate unsigned credlen;
660*12023SDoug.Leavitt@Sun.COM int stepnum = 1;
661*12023SDoug.Leavitt@Sun.COM char *sasl_username = NULL;
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate if (NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3) {
6640Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
6650Sstevel@tonic-gate return( LDAP_NOT_SUPPORTED );
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate /* shouldn't happen */
6690Sstevel@tonic-gate if (callback == NULL) {
6700Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
6710Sstevel@tonic-gate }
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate if ( ld->ld_defconn == NULL ||
6740Sstevel@tonic-gate ld->ld_defconn->lconn_status != LDAP_CONNST_CONNECTED) {
6750Sstevel@tonic-gate rc = nsldapi_open_ldap_defconn( ld );
6760Sstevel@tonic-gate if( rc < 0 ) {
6770Sstevel@tonic-gate return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate /* should have a valid ld connection - now create sasl connection */
6820Sstevel@tonic-gate if ((rc = nsldapi_sasl_open(ld)) != LDAP_SUCCESS) {
6830Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
6840Sstevel@tonic-gate return( rc );
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate /* expect context to be initialized when connection is open */
6880Sstevel@tonic-gate ctx = (sasl_conn_t *)ld->ld_defconn->lconn_sb->sb_sasl_ctx;
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate if( ctx == NULL ) {
6910Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
6920Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate /* (re)set security properties */
6960Sstevel@tonic-gate sasl_setprop( ctx, SASL_SEC_PROPS, &ld->ld_sasl_secprops );
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate ccred.bv_val = NULL;
6990Sstevel@tonic-gate ccred.bv_len = 0;
7000Sstevel@tonic-gate
701*12023SDoug.Leavitt@Sun.COM LDAPDebug(LDAP_DEBUG_TRACE, "Starting SASL/%s authentication\n",
702*12023SDoug.Leavitt@Sun.COM (mech ? mech : ""), 0, 0 );
703*12023SDoug.Leavitt@Sun.COM
7040Sstevel@tonic-gate do {
7050Sstevel@tonic-gate saslrc = sasl_client_start( ctx,
7060Sstevel@tonic-gate mechs,
7070Sstevel@tonic-gate &prompts,
7080Sstevel@tonic-gate (const char **)&ccred.bv_val,
7090Sstevel@tonic-gate &credlen,
7100Sstevel@tonic-gate &mech );
7110Sstevel@tonic-gate
712*12023SDoug.Leavitt@Sun.COM LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of client start for SASL/%s authentication\n",
713*12023SDoug.Leavitt@Sun.COM stepnum, (mech ? mech : ""), 0 );
714*12023SDoug.Leavitt@Sun.COM stepnum++;
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate if( saslrc == SASL_INTERACT &&
7170Sstevel@tonic-gate (callback)(ld, flags, defaults, prompts) != LDAP_SUCCESS ) {
7180Sstevel@tonic-gate break;
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate } while ( saslrc == SASL_INTERACT );
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate ccred.bv_len = credlen;
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
725*12023SDoug.Leavitt@Sun.COM return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) );
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate
728*12023SDoug.Leavitt@Sun.COM stepnum = 1;
729*12023SDoug.Leavitt@Sun.COM
7300Sstevel@tonic-gate do {
7310Sstevel@tonic-gate struct berval *scred;
732*12023SDoug.Leavitt@Sun.COM int clientstepnum = 1;
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate scred = NULL;
7350Sstevel@tonic-gate
736*12023SDoug.Leavitt@Sun.COM LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of bind for SASL/%s authentication\n",
737*12023SDoug.Leavitt@Sun.COM stepnum, (mech ? mech : ""), 0 );
738*12023SDoug.Leavitt@Sun.COM stepnum++;
739*12023SDoug.Leavitt@Sun.COM
7400Sstevel@tonic-gate /* notify server of a sasl bind step */
7410Sstevel@tonic-gate rc = ldap_sasl_bind_s(ld, dn, mech, &ccred,
7420Sstevel@tonic-gate sctrl, cctrl, &scred);
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate if ( ccred.bv_val != NULL ) {
7450Sstevel@tonic-gate ccred.bv_val = NULL;
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) {
749*12023SDoug.Leavitt@Sun.COM ber_bvfree( scred );
7500Sstevel@tonic-gate return( rc );
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) {
7540Sstevel@tonic-gate /* we're done, no need to step */
755*12023SDoug.Leavitt@Sun.COM if( scred ) {
756*12023SDoug.Leavitt@Sun.COM if (scred->bv_len == 0 ) { /* MS AD sends back empty screds */
757*12023SDoug.Leavitt@Sun.COM LDAPDebug(LDAP_DEBUG_ANY,
758*12023SDoug.Leavitt@Sun.COM "SASL BIND complete - ignoring empty credential response\n",
759*12023SDoug.Leavitt@Sun.COM 0, 0, 0);
760*12023SDoug.Leavitt@Sun.COM ber_bvfree( scred );
761*12023SDoug.Leavitt@Sun.COM } else {
7620Sstevel@tonic-gate /* but server provided us with data! */
763*12023SDoug.Leavitt@Sun.COM LDAPDebug(LDAP_DEBUG_TRACE,
764*12023SDoug.Leavitt@Sun.COM "SASL BIND complete but invalid because server responded with credentials - length [%u]\n",
765*12023SDoug.Leavitt@Sun.COM scred->bv_len, 0, 0);
7660Sstevel@tonic-gate ber_bvfree( scred );
7670Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR,
768*12023SDoug.Leavitt@Sun.COM NULL, nsldapi_strdup( dgettext(TEXT_DOMAIN,
769*12023SDoug.Leavitt@Sun.COM "Error during SASL handshake - "
770*12023SDoug.Leavitt@Sun.COM "invalid server credential response") ));
7710Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
772*12023SDoug.Leavitt@Sun.COM }
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate break;
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate /* perform the next step of the sasl bind */
7780Sstevel@tonic-gate do {
779*12023SDoug.Leavitt@Sun.COM LDAPDebug(LDAP_DEBUG_TRACE, "Doing client step %d of bind step %d for SASL/%s authentication\n",
780*12023SDoug.Leavitt@Sun.COM clientstepnum, stepnum, (mech ? mech : "") );
781*12023SDoug.Leavitt@Sun.COM clientstepnum++;
7820Sstevel@tonic-gate saslrc = sasl_client_step( ctx,
7830Sstevel@tonic-gate (scred == NULL) ? NULL : scred->bv_val,
7840Sstevel@tonic-gate (scred == NULL) ? 0 : scred->bv_len,
7850Sstevel@tonic-gate &prompts,
7860Sstevel@tonic-gate (const char **)&ccred.bv_val,
7870Sstevel@tonic-gate &credlen );
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate if( saslrc == SASL_INTERACT &&
7900Sstevel@tonic-gate (callback)(ld, flags, defaults, prompts)
7910Sstevel@tonic-gate != LDAP_SUCCESS ) {
7920Sstevel@tonic-gate break;
7930Sstevel@tonic-gate }
7940Sstevel@tonic-gate } while ( saslrc == SASL_INTERACT );
7950Sstevel@tonic-gate
7960Sstevel@tonic-gate ccred.bv_len = credlen;
7970Sstevel@tonic-gate ber_bvfree( scred );
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
800*12023SDoug.Leavitt@Sun.COM return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) );
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate if ( rc != LDAP_SUCCESS ) {
8050Sstevel@tonic-gate return( rc );
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate if ( saslrc != SASL_OK ) {
809*12023SDoug.Leavitt@Sun.COM return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) );
810*12023SDoug.Leavitt@Sun.COM }
811*12023SDoug.Leavitt@Sun.COM
812*12023SDoug.Leavitt@Sun.COM saslrc = sasl_getprop( ctx, SASL_USERNAME, (const void **) &sasl_username );
813*12023SDoug.Leavitt@Sun.COM if ( (saslrc == SASL_OK) && sasl_username ) {
814*12023SDoug.Leavitt@Sun.COM LDAPDebug(LDAP_DEBUG_TRACE, "SASL identity: %s\n", sasl_username, 0, 0);
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate saslrc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf );
8180Sstevel@tonic-gate if( saslrc == SASL_OK ) {
819*12023SDoug.Leavitt@Sun.COM if( ssf && *ssf ) {
820*12023SDoug.Leavitt@Sun.COM LDAPDebug(LDAP_DEBUG_TRACE,
821*12023SDoug.Leavitt@Sun.COM "SASL install encryption, for SSF: %lu\n",
822*12023SDoug.Leavitt@Sun.COM (unsigned long) *ssf, 0, 0 );
823*12023SDoug.Leavitt@Sun.COM }
8240Sstevel@tonic-gate rc = nsldapi_sasl_install(ld, ld->ld_conns->lconn_sb, ctx, ssf);
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate
8270Sstevel@tonic-gate return( rc );
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate #ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER
8310Sstevel@tonic-gate /*
8320Sstevel@tonic-gate * Get available SASL Mechanisms supported by the server
8330Sstevel@tonic-gate */
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate static int
nsldapi_get_sasl_mechs(LDAP * ld,char ** pmech)8360Sstevel@tonic-gate nsldapi_get_sasl_mechs ( LDAP *ld, char **pmech )
8370Sstevel@tonic-gate {
8380Sstevel@tonic-gate char *attr[] = { "supportedSASLMechanisms", NULL };
8390Sstevel@tonic-gate char **values, **v, *mech, *m;
8400Sstevel@tonic-gate LDAPMessage *res, *e;
8410Sstevel@tonic-gate struct timeval timeout;
8420Sstevel@tonic-gate int slen, rc;
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
8450Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate timeout.tv_sec = SEARCH_TIMEOUT_SECS;
8490Sstevel@tonic-gate timeout.tv_usec = 0;
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate rc = ldap_search_st( ld, "", LDAP_SCOPE_BASE,
8520Sstevel@tonic-gate "objectclass=*", attr, 0, &timeout, &res );
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate if ( rc != LDAP_SUCCESS ) {
8550Sstevel@tonic-gate return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
8560Sstevel@tonic-gate }
8570Sstevel@tonic-gate
8580Sstevel@tonic-gate e = ldap_first_entry( ld, res );
8590Sstevel@tonic-gate if ( e == NULL ) {
8600Sstevel@tonic-gate ldap_msgfree( res );
8610Sstevel@tonic-gate if ( ld->ld_errno == LDAP_SUCCESS ) {
8620Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_OBJECT, NULL, NULL );
8630Sstevel@tonic-gate }
8640Sstevel@tonic-gate return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate values = ldap_get_values( ld, e, "supportedSASLMechanisms" );
8680Sstevel@tonic-gate if ( values == NULL ) {
8690Sstevel@tonic-gate ldap_msgfree( res );
8700Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL );
8710Sstevel@tonic-gate return( LDAP_NO_SUCH_ATTRIBUTE );
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate slen = 0;
8750Sstevel@tonic-gate for(v = values; *v != NULL; v++ ) {
8760Sstevel@tonic-gate slen += strlen(*v) + 1;
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate if ( (mech = NSLDAPI_CALLOC(1, slen)) == NULL) {
8790Sstevel@tonic-gate ldap_value_free( values );
8800Sstevel@tonic-gate ldap_msgfree( res );
8810Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
8820Sstevel@tonic-gate return( LDAP_NO_MEMORY );
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate m = mech;
8850Sstevel@tonic-gate for(v = values; *v; v++) {
8860Sstevel@tonic-gate if (v != values) {
8870Sstevel@tonic-gate *m++ = ' ';
8880Sstevel@tonic-gate }
8890Sstevel@tonic-gate slen = strlen(*v);
8900Sstevel@tonic-gate strncpy(m, *v, slen);
8910Sstevel@tonic-gate m += slen;
8920Sstevel@tonic-gate }
8930Sstevel@tonic-gate *m = '\0';
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate ldap_value_free( values );
8960Sstevel@tonic-gate ldap_msgfree( res );
8970Sstevel@tonic-gate
8980Sstevel@tonic-gate *pmech = mech;
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate return( LDAP_SUCCESS );
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate #endif
9030Sstevel@tonic-gate
nsldapi_sasl_secprops(const char * in,sasl_security_properties_t * secprops)9040Sstevel@tonic-gate int nsldapi_sasl_secprops(
9050Sstevel@tonic-gate const char *in,
9060Sstevel@tonic-gate sasl_security_properties_t *secprops )
9070Sstevel@tonic-gate {
9080Sstevel@tonic-gate int i;
9090Sstevel@tonic-gate char **props = NULL;
9100Sstevel@tonic-gate char *inp;
9110Sstevel@tonic-gate unsigned sflags = 0;
9120Sstevel@tonic-gate sasl_ssf_t max_ssf = 0;
9130Sstevel@tonic-gate sasl_ssf_t min_ssf = 0;
9140Sstevel@tonic-gate unsigned maxbufsize = 0;
9150Sstevel@tonic-gate int got_sflags = 0;
9160Sstevel@tonic-gate int got_max_ssf = 0;
9170Sstevel@tonic-gate int got_min_ssf = 0;
9180Sstevel@tonic-gate int got_maxbufsize = 0;
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate if (in == NULL) {
9210Sstevel@tonic-gate return LDAP_PARAM_ERROR;
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate inp = nsldapi_strdup(in);
9240Sstevel@tonic-gate if (inp == NULL) {
9250Sstevel@tonic-gate return LDAP_PARAM_ERROR;
9260Sstevel@tonic-gate }
9270Sstevel@tonic-gate props = ldap_str2charray( inp, "," );
9280Sstevel@tonic-gate NSLDAPI_FREE( inp );
9290Sstevel@tonic-gate
9300Sstevel@tonic-gate if( props == NULL || secprops == NULL ) {
9310Sstevel@tonic-gate return LDAP_PARAM_ERROR;
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate for( i=0; props[i]; i++ ) {
9350Sstevel@tonic-gate if( strcasecmp(props[i], "none") == 0 ) {
9360Sstevel@tonic-gate got_sflags++;
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate } else if( strcasecmp(props[i], "noactive") == 0 ) {
9390Sstevel@tonic-gate got_sflags++;
9400Sstevel@tonic-gate sflags |= SASL_SEC_NOACTIVE;
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate } else if( strcasecmp(props[i], "noanonymous") == 0 ) {
9430Sstevel@tonic-gate got_sflags++;
9440Sstevel@tonic-gate sflags |= SASL_SEC_NOANONYMOUS;
9450Sstevel@tonic-gate
9460Sstevel@tonic-gate } else if( strcasecmp(props[i], "nodict") == 0 ) {
9470Sstevel@tonic-gate got_sflags++;
9480Sstevel@tonic-gate sflags |= SASL_SEC_NODICTIONARY;
9490Sstevel@tonic-gate
9500Sstevel@tonic-gate } else if( strcasecmp(props[i], "noplain") == 0 ) {
9510Sstevel@tonic-gate got_sflags++;
9520Sstevel@tonic-gate sflags |= SASL_SEC_NOPLAINTEXT;
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate } else if( strcasecmp(props[i], "forwardsec") == 0 ) {
9550Sstevel@tonic-gate got_sflags++;
9560Sstevel@tonic-gate sflags |= SASL_SEC_FORWARD_SECRECY;
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate } else if( strcasecmp(props[i], "passcred") == 0 ) {
9590Sstevel@tonic-gate got_sflags++;
9600Sstevel@tonic-gate sflags |= SASL_SEC_PASS_CREDENTIALS;
9610Sstevel@tonic-gate
9620Sstevel@tonic-gate } else if( strncasecmp(props[i],
9630Sstevel@tonic-gate "minssf=", sizeof("minssf")) == 0 ) {
9640Sstevel@tonic-gate if( isdigit( props[i][sizeof("minssf")] ) ) {
9650Sstevel@tonic-gate got_min_ssf++;
9660Sstevel@tonic-gate min_ssf = atoi( &props[i][sizeof("minssf")] );
9670Sstevel@tonic-gate } else {
9680Sstevel@tonic-gate return LDAP_NOT_SUPPORTED;
9690Sstevel@tonic-gate }
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate } else if( strncasecmp(props[i],
9720Sstevel@tonic-gate "maxssf=", sizeof("maxssf")) == 0 ) {
9730Sstevel@tonic-gate if( isdigit( props[i][sizeof("maxssf")] ) ) {
9740Sstevel@tonic-gate got_max_ssf++;
9750Sstevel@tonic-gate max_ssf = atoi( &props[i][sizeof("maxssf")] );
9760Sstevel@tonic-gate } else {
9770Sstevel@tonic-gate return LDAP_NOT_SUPPORTED;
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate } else if( strncasecmp(props[i],
9810Sstevel@tonic-gate "maxbufsize=", sizeof("maxbufsize")) == 0 ) {
9820Sstevel@tonic-gate if( isdigit( props[i][sizeof("maxbufsize")] ) ) {
9830Sstevel@tonic-gate got_maxbufsize++;
9840Sstevel@tonic-gate maxbufsize = atoi( &props[i][sizeof("maxbufsize")] );
9850Sstevel@tonic-gate if( maxbufsize &&
9860Sstevel@tonic-gate (( maxbufsize < SASL_MIN_BUFF_SIZE )
9870Sstevel@tonic-gate || (maxbufsize > SASL_MAX_BUFF_SIZE ))) {
9880Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
9890Sstevel@tonic-gate }
9900Sstevel@tonic-gate } else {
9910Sstevel@tonic-gate return( LDAP_NOT_SUPPORTED );
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate } else {
9940Sstevel@tonic-gate return( LDAP_NOT_SUPPORTED );
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate }
9970Sstevel@tonic-gate
9980Sstevel@tonic-gate if(got_sflags) {
9990Sstevel@tonic-gate secprops->security_flags = sflags;
10000Sstevel@tonic-gate }
10010Sstevel@tonic-gate if(got_min_ssf) {
10020Sstevel@tonic-gate secprops->min_ssf = min_ssf;
10030Sstevel@tonic-gate }
10040Sstevel@tonic-gate if(got_max_ssf) {
10050Sstevel@tonic-gate secprops->max_ssf = max_ssf;
10060Sstevel@tonic-gate }
10070Sstevel@tonic-gate if(got_maxbufsize) {
10080Sstevel@tonic-gate secprops->maxbufsize = maxbufsize;
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate
10110Sstevel@tonic-gate ldap_charray_free( props );
10120Sstevel@tonic-gate return( LDAP_SUCCESS );
10130Sstevel@tonic-gate }
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate /*
10160Sstevel@tonic-gate * SASL Authentication Interface: ldap_sasl_interactive_bind_s
10170Sstevel@tonic-gate *
10180Sstevel@tonic-gate * This routine takes a DN, SASL mech list, and a SASL callback
10190Sstevel@tonic-gate * and performs the necessary sequencing to complete a SASL bind
10200Sstevel@tonic-gate * to the LDAP connection ld. The user provided callback can
10210Sstevel@tonic-gate * use an optionally provided set of default values to complete
10220Sstevel@tonic-gate * any necessary interactions.
10230Sstevel@tonic-gate *
10240Sstevel@tonic-gate * Currently inpose the following restrictions:
10250Sstevel@tonic-gate * A mech list must be provided, only LDAP_SASL_INTERACTIVE
10260Sstevel@tonic-gate * mode is supported
10270Sstevel@tonic-gate */
10280Sstevel@tonic-gate int
10290Sstevel@tonic-gate LDAP_CALL
ldap_sasl_interactive_bind_s(LDAP * ld,const char * dn,const char * saslMechanism,LDAPControl ** sctrl,LDAPControl ** cctrl,unsigned flags,LDAP_SASL_INTERACT_PROC * callback,void * defaults)10300Sstevel@tonic-gate ldap_sasl_interactive_bind_s( LDAP *ld, const char *dn,
10310Sstevel@tonic-gate const char *saslMechanism,
10320Sstevel@tonic-gate LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags,
10330Sstevel@tonic-gate LDAP_SASL_INTERACT_PROC *callback, void *defaults )
10340Sstevel@tonic-gate {
10350Sstevel@tonic-gate #ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER
10360Sstevel@tonic-gate char *smechs;
10370Sstevel@tonic-gate #endif
10380Sstevel@tonic-gate int rc;
10390Sstevel@tonic-gate
10400Sstevel@tonic-gate LDAPDebug(LDAP_DEBUG_TRACE, "ldap_sasl_interactive_bind_s\n", 0, 0, 0);
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
10430Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
10440Sstevel@tonic-gate }
10450Sstevel@tonic-gate
10460Sstevel@tonic-gate if (flags != LDAP_SASL_INTERACTIVE || callback == NULL) {
10470Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate
10500Sstevel@tonic-gate LDAP_MUTEX_LOCK(ld, LDAP_SASL_LOCK );
10510Sstevel@tonic-gate
10520Sstevel@tonic-gate if( saslMechanism == NULL || *saslMechanism == '\0' ) {
10530Sstevel@tonic-gate #ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER
10540Sstevel@tonic-gate rc = nsldapi_get_sasl_mechs( ld, &smechs );
10550Sstevel@tonic-gate if( rc != LDAP_SUCCESS ) {
10560Sstevel@tonic-gate LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK );
10570Sstevel@tonic-gate return( rc );
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate saslMechanism = smechs;
10600Sstevel@tonic-gate #else
10610Sstevel@tonic-gate LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK );
10620Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
10630Sstevel@tonic-gate #endif
10640Sstevel@tonic-gate }
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate /* initialize SASL library */
10670Sstevel@tonic-gate if ( nsldapi_sasl_init() < 0 ) {
10680Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate
10710Sstevel@tonic-gate rc = nsldapi_sasl_do_bind( ld, dn, saslMechanism,
10720Sstevel@tonic-gate flags, callback, defaults, sctrl, cctrl);
10730Sstevel@tonic-gate
10740Sstevel@tonic-gate LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK );
10750Sstevel@tonic-gate return( rc );
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate
10780Sstevel@tonic-gate #endif
1079