17c478bd9Sstevel@tonic-gate /*
236ca3987Schinlong * CDDL HEADER START
336ca3987Schinlong *
436ca3987Schinlong * The contents of this file are subject to the terms of the
536ca3987Schinlong * Common Development and Distribution License (the "License").
636ca3987Schinlong * You may not use this file except in compliance with the License.
736ca3987Schinlong *
836ca3987Schinlong * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
936ca3987Schinlong * or http://www.opensolaris.org/os/licensing.
1036ca3987Schinlong * See the License for the specific language governing permissions
1136ca3987Schinlong * and limitations under the License.
1236ca3987Schinlong *
1336ca3987Schinlong * When distributing Covered Code, include this CDDL HEADER in each
1436ca3987Schinlong * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1536ca3987Schinlong * If applicable, add the following below this CDDL HEADER, with the
1636ca3987Schinlong * fields enclosed by brackets "[]" replaced with your own identifying
1736ca3987Schinlong * information: Portions Copyright [yyyy] [name of copyright owner]
1836ca3987Schinlong *
1936ca3987Schinlong * CDDL HEADER END
2036ca3987Schinlong */
2136ca3987Schinlong /*
22e6a862fbSDouglas Leavitt * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #ifdef LDAP_SASLIO_HOOKS
277c478bd9Sstevel@tonic-gate #include <assert.h>
287c478bd9Sstevel@tonic-gate #include "ldap-int.h"
297c478bd9Sstevel@tonic-gate #include "../ber/lber-int.h"
307c478bd9Sstevel@tonic-gate #include <sasl/sasl.h>
317c478bd9Sstevel@tonic-gate #include <thread.h>
327c478bd9Sstevel@tonic-gate #include <synch.h>
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #define SEARCH_TIMEOUT_SECS 120
357c478bd9Sstevel@tonic-gate #define NSLDAPI_SM_BUF 128
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate extern void *sasl_create_context(void);
387c478bd9Sstevel@tonic-gate extern void sasl_free_context(void *ctx);
397c478bd9Sstevel@tonic-gate extern int _sasl_client_init(void *ctx, const sasl_callback_t *callbacks);
407c478bd9Sstevel@tonic-gate extern int _sasl_client_new(void *ctx, const char *service,
417c478bd9Sstevel@tonic-gate const char *serverFQDN, const char *iplocalport,
427c478bd9Sstevel@tonic-gate const char *ipremoteport,
437c478bd9Sstevel@tonic-gate const sasl_callback_t *prompt_supp,
447c478bd9Sstevel@tonic-gate unsigned flags, sasl_conn_t **pconn);
457c478bd9Sstevel@tonic-gate extern int _sasl_server_init(void *ctx,
467c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks, const char *appname);
477c478bd9Sstevel@tonic-gate extern int _sasl_server_new(void *ctx, const char *service,
487c478bd9Sstevel@tonic-gate const char *serverFQDN, const char *user_realm,
497c478bd9Sstevel@tonic-gate const char *iplocalport, const char *ipremoteport,
507c478bd9Sstevel@tonic-gate const sasl_callback_t *callbacks,
517c478bd9Sstevel@tonic-gate unsigned flags, sasl_conn_t **pconn);
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate static int nsldapi_sasl_close( LDAP *ld, Sockbuf *sb );
54e6a862fbSDouglas Leavitt static void destroy_sasliobuf(Sockbuf *sb);
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate * SASL Dependent routines
587c478bd9Sstevel@tonic-gate *
597c478bd9Sstevel@tonic-gate * SASL security and integrity options are supported through the
607c478bd9Sstevel@tonic-gate * use of the extended I/O functionality. Because the extended
617c478bd9Sstevel@tonic-gate * I/O functions may already be in use prior to enabling encryption,
627c478bd9Sstevel@tonic-gate * when SASL encryption is enabled, these routine interpose themselves
637c478bd9Sstevel@tonic-gate * over the existng extended I/O routines and add an additional level
647c478bd9Sstevel@tonic-gate * of indirection.
657c478bd9Sstevel@tonic-gate * IE: Before SASL: client->libldap->lber->extio
667c478bd9Sstevel@tonic-gate * After SASL: client->libldap->lber->saslio->extio
677c478bd9Sstevel@tonic-gate * Any extio functions are still used for the raw i/O [IE prldap]
687c478bd9Sstevel@tonic-gate * but SASL will decrypt before passing to lber.
697c478bd9Sstevel@tonic-gate * SASL cannot decrypt a stream so full packets must be read
707c478bd9Sstevel@tonic-gate * before proceeding.
717c478bd9Sstevel@tonic-gate */
727c478bd9Sstevel@tonic-gate
nsldapi_sasl_fail()737c478bd9Sstevel@tonic-gate static int nsldapi_sasl_fail()
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate return( SASL_FAIL );
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate * Global SASL Init data
807c478bd9Sstevel@tonic-gate */
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate static sasl_callback_t client_callbacks[] = {
837c478bd9Sstevel@tonic-gate { SASL_CB_GETOPT, nsldapi_sasl_fail, NULL },
847c478bd9Sstevel@tonic-gate { SASL_CB_GETREALM, NULL, NULL },
857c478bd9Sstevel@tonic-gate { SASL_CB_USER, NULL, NULL },
867c478bd9Sstevel@tonic-gate { SASL_CB_AUTHNAME, NULL, NULL },
877c478bd9Sstevel@tonic-gate { SASL_CB_PASS, NULL, NULL },
887c478bd9Sstevel@tonic-gate { SASL_CB_ECHOPROMPT, NULL, NULL },
897c478bd9Sstevel@tonic-gate { SASL_CB_NOECHOPROMPT, NULL, NULL },
907c478bd9Sstevel@tonic-gate { SASL_CB_LIST_END, NULL, NULL }
917c478bd9Sstevel@tonic-gate };
927c478bd9Sstevel@tonic-gate static mutex_t sasl_mutex = DEFAULTMUTEX;
937c478bd9Sstevel@tonic-gate static int nsldapi_sasl_inited = 0;
947c478bd9Sstevel@tonic-gate static void *gctx; /* intentially not freed - avoid libsasl re-inits */
957c478bd9Sstevel@tonic-gate
nsldapi_sasl_init(void)967c478bd9Sstevel@tonic-gate int nsldapi_sasl_init( void )
977c478bd9Sstevel@tonic-gate {
987c478bd9Sstevel@tonic-gate int saslrc;
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate mutex_lock(&sasl_mutex);
1017c478bd9Sstevel@tonic-gate if ( nsldapi_sasl_inited ) {
1027c478bd9Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
1037c478bd9Sstevel@tonic-gate return( 0 );
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate if ((gctx = (void *)sasl_create_context()) != NULL) {
1067c478bd9Sstevel@tonic-gate saslrc = _sasl_client_init(gctx, client_callbacks);
1077c478bd9Sstevel@tonic-gate if (saslrc == SASL_OK ) {
1087c478bd9Sstevel@tonic-gate nsldapi_sasl_inited = 1;
1097c478bd9Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
1107c478bd9Sstevel@tonic-gate return( 0 );
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
1147c478bd9Sstevel@tonic-gate return( -1 );
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate * SASL encryption routines
1197c478bd9Sstevel@tonic-gate */
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate * Get the 4 octet header [size] for a sasl encrypted buffer.
1237c478bd9Sstevel@tonic-gate * See RFC222 [section 3].
1247c478bd9Sstevel@tonic-gate */
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_pktlen(char * buf,int maxbufsize)1277c478bd9Sstevel@tonic-gate nsldapi_sasl_pktlen( char *buf, int maxbufsize )
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate int size;
1307c478bd9Sstevel@tonic-gate
13136ca3987Schinlong #if defined( _WINDOWS ) || defined( _WIN32 )
1327c478bd9Sstevel@tonic-gate size = ntohl(*(long *)buf);
13336ca3987Schinlong #else
13436ca3987Schinlong size = ntohl(*(uint32_t *)buf);
13536ca3987Schinlong #endif
136*55fea89dSDan Cross
1377c478bd9Sstevel@tonic-gate if ( size < 0 || size > maxbufsize ) {
1387c478bd9Sstevel@tonic-gate return (-1 );
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate return( size + 4 ); /* include the first 4 bytes */
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_read(int s,void * buf,int len,struct lextiof_socket_private * arg)1457c478bd9Sstevel@tonic-gate nsldapi_sasl_read( int s, void *buf, int len,
1467c478bd9Sstevel@tonic-gate struct lextiof_socket_private *arg)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
1497c478bd9Sstevel@tonic-gate LDAP *ld;
1507c478bd9Sstevel@tonic-gate const char *dbuf;
1517c478bd9Sstevel@tonic-gate char *cp;
1527c478bd9Sstevel@tonic-gate int ret;
1537c478bd9Sstevel@tonic-gate unsigned dlen, blen;
154*55fea89dSDan Cross
1557c478bd9Sstevel@tonic-gate if (sb == NULL) {
1567c478bd9Sstevel@tonic-gate return( -1 );
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate ld = (LDAP *)sb->sb_sasl_prld;
1607c478bd9Sstevel@tonic-gate if (ld == NULL) {
1617c478bd9Sstevel@tonic-gate return( -1 );
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate /* Is there anything left in the existing buffer? */
1657c478bd9Sstevel@tonic-gate if ((ret = sb->sb_sasl_ilen) > 0) {
1667c478bd9Sstevel@tonic-gate ret = (ret > len ? len : ret);
1677c478bd9Sstevel@tonic-gate SAFEMEMCPY( buf, sb->sb_sasl_iptr, ret );
1687c478bd9Sstevel@tonic-gate if (ret == sb->sb_sasl_ilen) {
1697c478bd9Sstevel@tonic-gate sb->sb_sasl_ilen = 0;
1707c478bd9Sstevel@tonic-gate sb->sb_sasl_iptr = NULL;
1717c478bd9Sstevel@tonic-gate } else {
1727c478bd9Sstevel@tonic-gate sb->sb_sasl_ilen -= ret;
1737c478bd9Sstevel@tonic-gate sb->sb_sasl_iptr += ret;
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate return( ret );
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate /* buffer is empty - fill it */
1797c478bd9Sstevel@tonic-gate cp = sb->sb_sasl_ibuf;
1807c478bd9Sstevel@tonic-gate dlen = 0;
181*55fea89dSDan Cross
1827c478bd9Sstevel@tonic-gate /* Read the length of the packet */
1837c478bd9Sstevel@tonic-gate while ( dlen < 4 ) {
1847c478bd9Sstevel@tonic-gate if (sb->sb_sasl_fns.lbextiofn_read != NULL) {
1857c478bd9Sstevel@tonic-gate ret = sb->sb_sasl_fns.lbextiofn_read(
1867c478bd9Sstevel@tonic-gate s, cp, 4 - dlen,
1877c478bd9Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg);
1887c478bd9Sstevel@tonic-gate } else {
1897c478bd9Sstevel@tonic-gate ret = read( sb->sb_sd, cp, 4 - dlen );
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate #ifdef EINTR
1927c478bd9Sstevel@tonic-gate if ( ( ret < 0 ) && ( LDAP_GET_ERRNO(ld) == EINTR ) )
1937c478bd9Sstevel@tonic-gate continue;
1947c478bd9Sstevel@tonic-gate #endif
1957c478bd9Sstevel@tonic-gate if ( ret <= 0 )
1967c478bd9Sstevel@tonic-gate return( ret );
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate cp += ret;
1997c478bd9Sstevel@tonic-gate dlen += ret;
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate blen = 4;
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate ret = nsldapi_sasl_pktlen( sb->sb_sasl_ibuf, sb->sb_sasl_bfsz );
2057c478bd9Sstevel@tonic-gate if (ret < 0) {
2067c478bd9Sstevel@tonic-gate LDAP_SET_ERRNO(ld, EIO);
2077c478bd9Sstevel@tonic-gate return( -1 );
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate dlen = ret - dlen;
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate /* read the rest of the encrypted packet */
2127c478bd9Sstevel@tonic-gate while ( dlen > 0 ) {
2137c478bd9Sstevel@tonic-gate if (sb->sb_sasl_fns.lbextiofn_read != NULL) {
2147c478bd9Sstevel@tonic-gate ret = sb->sb_sasl_fns.lbextiofn_read(
2157c478bd9Sstevel@tonic-gate s, cp, dlen,
2167c478bd9Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg);
2177c478bd9Sstevel@tonic-gate } else {
2187c478bd9Sstevel@tonic-gate ret = read( sb->sb_sd, cp, dlen );
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate #ifdef EINTR
2227c478bd9Sstevel@tonic-gate if ( ( ret < 0 ) && ( LDAP_GET_ERRNO(ld) == EINTR ) )
2237c478bd9Sstevel@tonic-gate continue;
2247c478bd9Sstevel@tonic-gate #endif
2257c478bd9Sstevel@tonic-gate if ( ret <= 0 )
2267c478bd9Sstevel@tonic-gate return( ret );
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate cp += ret;
2297c478bd9Sstevel@tonic-gate blen += ret;
2307c478bd9Sstevel@tonic-gate dlen -= ret;
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate /* Decode the packet */
2347c478bd9Sstevel@tonic-gate ret = sasl_decode( sb->sb_sasl_ctx,
2357c478bd9Sstevel@tonic-gate sb->sb_sasl_ibuf, blen,
2367c478bd9Sstevel@tonic-gate &dbuf, &dlen);
2377c478bd9Sstevel@tonic-gate if ( ret != SASL_OK ) {
2387c478bd9Sstevel@tonic-gate /* sb_sasl_read: failed to decode packet, drop it, error */
2397c478bd9Sstevel@tonic-gate sb->sb_sasl_iptr = NULL;
2407c478bd9Sstevel@tonic-gate sb->sb_sasl_ilen = 0;
2417c478bd9Sstevel@tonic-gate LDAP_SET_ERRNO(ld, EIO);
2427c478bd9Sstevel@tonic-gate return( -1 );
2437c478bd9Sstevel@tonic-gate }
244*55fea89dSDan Cross
2457c478bd9Sstevel@tonic-gate /* copy decrypted packet to the input buffer */
2467c478bd9Sstevel@tonic-gate SAFEMEMCPY( sb->sb_sasl_ibuf, dbuf, dlen );
2477c478bd9Sstevel@tonic-gate sb->sb_sasl_iptr = sb->sb_sasl_ibuf;
2487c478bd9Sstevel@tonic-gate sb->sb_sasl_ilen = dlen;
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate ret = (dlen > (unsigned) len ? len : dlen);
2517c478bd9Sstevel@tonic-gate SAFEMEMCPY( buf, sb->sb_sasl_iptr, ret );
2527c478bd9Sstevel@tonic-gate if (ret == sb->sb_sasl_ilen) {
2537c478bd9Sstevel@tonic-gate sb->sb_sasl_ilen = 0;
2547c478bd9Sstevel@tonic-gate sb->sb_sasl_iptr = NULL;
2557c478bd9Sstevel@tonic-gate } else {
2567c478bd9Sstevel@tonic-gate sb->sb_sasl_ilen -= ret;
2577c478bd9Sstevel@tonic-gate sb->sb_sasl_iptr += ret;
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate return( ret );
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_write(int s,const void * buf,int len,struct lextiof_socket_private * arg)2637c478bd9Sstevel@tonic-gate nsldapi_sasl_write( int s, const void *buf, int len,
2647c478bd9Sstevel@tonic-gate struct lextiof_socket_private *arg)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
267e6a862fbSDouglas Leavitt int ret = 0;
268e6a862fbSDouglas Leavitt const char *obuf, *optr, *cbuf = (const char *)buf;
269e6a862fbSDouglas Leavitt unsigned olen, clen, tlen = 0;
270e6a862fbSDouglas Leavitt unsigned *maxbuf;
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate if (sb == NULL) {
2737c478bd9Sstevel@tonic-gate return( -1 );
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate
276e6a862fbSDouglas Leavitt ret = sasl_getprop(sb->sb_sasl_ctx, SASL_MAXOUTBUF,
277e6a862fbSDouglas Leavitt (const void **)&maxbuf);
2787c478bd9Sstevel@tonic-gate if ( ret != SASL_OK ) {
279e6a862fbSDouglas Leavitt /* just a sanity check, should never happen */
2807c478bd9Sstevel@tonic-gate return( -1 );
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate
283e6a862fbSDouglas Leavitt while (len > 0) {
284e6a862fbSDouglas Leavitt clen = (len > *maxbuf) ? *maxbuf : len;
285e6a862fbSDouglas Leavitt /* encode the next packet. */
286e6a862fbSDouglas Leavitt ret = sasl_encode( sb->sb_sasl_ctx, cbuf, clen, &obuf, &olen);
287e6a862fbSDouglas Leavitt if ( ret != SASL_OK ) {
288e6a862fbSDouglas Leavitt /* XXX Log error? "sb_sasl_write: failed to encode packet..." */
289e6a862fbSDouglas Leavitt return( -1 );
2907c478bd9Sstevel@tonic-gate }
291e6a862fbSDouglas Leavitt /* Write everything now, buffer is only good until next sasl_encode */
292e6a862fbSDouglas Leavitt optr = obuf;
293e6a862fbSDouglas Leavitt while (olen > 0) {
294e6a862fbSDouglas Leavitt if (sb->sb_sasl_fns.lbextiofn_write != NULL) {
295e6a862fbSDouglas Leavitt ret = sb->sb_sasl_fns.lbextiofn_write(
296e6a862fbSDouglas Leavitt s, optr, olen,
297e6a862fbSDouglas Leavitt sb->sb_sasl_fns.lbextiofn_socket_arg);
298e6a862fbSDouglas Leavitt } else {
299e6a862fbSDouglas Leavitt ret = write( sb->sb_sd, optr, olen);
300e6a862fbSDouglas Leavitt }
301e6a862fbSDouglas Leavitt if ( ret < 0 )
302e6a862fbSDouglas Leavitt return( ret );
303e6a862fbSDouglas Leavitt optr += ret;
304e6a862fbSDouglas Leavitt olen -= ret;
305e6a862fbSDouglas Leavitt }
306e6a862fbSDouglas Leavitt len -= clen;
307e6a862fbSDouglas Leavitt cbuf += clen;
308e6a862fbSDouglas Leavitt tlen += clen;
3097c478bd9Sstevel@tonic-gate }
310e6a862fbSDouglas Leavitt return( tlen );
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_poll(LDAP_X_PollFD fds[],int nfds,int timeout,struct lextiof_session_private * arg)3147c478bd9Sstevel@tonic-gate nsldapi_sasl_poll(
3157c478bd9Sstevel@tonic-gate LDAP_X_PollFD fds[], int nfds, int timeout,
316*55fea89dSDan Cross struct lextiof_session_private *arg )
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
3197c478bd9Sstevel@tonic-gate LDAP *ld;
3207c478bd9Sstevel@tonic-gate int i;
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate if (sb == NULL) {
3237c478bd9Sstevel@tonic-gate return( -1 );
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate ld = (LDAP *)sb->sb_sasl_prld;
3267c478bd9Sstevel@tonic-gate if (ld == NULL) {
3277c478bd9Sstevel@tonic-gate return( -1 );
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate if (fds && nfds > 0) {
3317c478bd9Sstevel@tonic-gate for(i = 0; i < nfds; i++) {
3327c478bd9Sstevel@tonic-gate if (fds[i].lpoll_socketarg ==
3337c478bd9Sstevel@tonic-gate (struct lextiof_socket_private *)sb) {
3347c478bd9Sstevel@tonic-gate fds[i].lpoll_socketarg =
3357c478bd9Sstevel@tonic-gate (struct lextiof_socket_private *)
3367c478bd9Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg;
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate return ( ld->ld_sasl_io_fns.lextiof_poll( fds, nfds, timeout,
3427c478bd9Sstevel@tonic-gate (void *)ld->ld_sasl_io_fns.lextiof_session_arg) );
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate /* no encryption indirect routines */
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_ne_read(int s,void * buf,int len,struct lextiof_socket_private * arg)3487c478bd9Sstevel@tonic-gate nsldapi_sasl_ne_read( int s, void *buf, int len,
3497c478bd9Sstevel@tonic-gate struct lextiof_socket_private *arg)
3507c478bd9Sstevel@tonic-gate {
3517c478bd9Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
352*55fea89dSDan Cross
3537c478bd9Sstevel@tonic-gate if (sb == NULL) {
3547c478bd9Sstevel@tonic-gate return( -1 );
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate return( sb->sb_sasl_fns.lbextiofn_read( s, buf, len,
3587c478bd9Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg) );
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_ne_write(int s,const void * buf,int len,struct lextiof_socket_private * arg)3627c478bd9Sstevel@tonic-gate nsldapi_sasl_ne_write( int s, const void *buf, int len,
3637c478bd9Sstevel@tonic-gate struct lextiof_socket_private *arg)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate if (sb == NULL) {
3687c478bd9Sstevel@tonic-gate return( -1 );
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate return( sb->sb_sasl_fns.lbextiofn_write( s, buf, len,
3727c478bd9Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg) );
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_close_socket(int s,struct lextiof_socket_private * arg)376*55fea89dSDan Cross nsldapi_sasl_close_socket(int s, struct lextiof_socket_private *arg )
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
3797c478bd9Sstevel@tonic-gate LDAP *ld;
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate if (sb == NULL) {
3827c478bd9Sstevel@tonic-gate return( -1 );
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate ld = (LDAP *)sb->sb_sasl_prld;
3857c478bd9Sstevel@tonic-gate if (ld == NULL) {
3867c478bd9Sstevel@tonic-gate return( -1 );
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate /* undo function pointer interposing */
3897c478bd9Sstevel@tonic-gate ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &ld->ld_sasl_io_fns );
3907c478bd9Sstevel@tonic-gate ber_sockbuf_set_option( sb,
3917c478bd9Sstevel@tonic-gate LBER_SOCKBUF_OPT_EXT_IO_FNS,
3927c478bd9Sstevel@tonic-gate (void *)&sb->sb_sasl_fns);
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate /* undo SASL */
3957c478bd9Sstevel@tonic-gate nsldapi_sasl_close( ld, sb );
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate return ( ld->ld_sasl_io_fns.lextiof_close( s,
3987c478bd9Sstevel@tonic-gate (struct lextiof_socket_private *)
3997c478bd9Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg ) );
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate /*
4037c478bd9Sstevel@tonic-gate * install encryption routines if security has been negotiated
4047c478bd9Sstevel@tonic-gate */
4057c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_install(LDAP * ld,Sockbuf * sb,void * ctx_arg,sasl_ssf_t * ssf)4067c478bd9Sstevel@tonic-gate nsldapi_sasl_install( LDAP *ld, Sockbuf *sb, void *ctx_arg, sasl_ssf_t *ssf)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate struct lber_x_ext_io_fns fns;
4097c478bd9Sstevel@tonic-gate struct ldap_x_ext_io_fns iofns;
4107c478bd9Sstevel@tonic-gate sasl_security_properties_t *secprops;
4117c478bd9Sstevel@tonic-gate int rc, value;
4127c478bd9Sstevel@tonic-gate int bufsiz;
4137c478bd9Sstevel@tonic-gate int encrypt = 0;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate if (ssf && *ssf) {
4167c478bd9Sstevel@tonic-gate encrypt = 1;
4177c478bd9Sstevel@tonic-gate }
418e6a862fbSDouglas Leavitt if ( sb == NULL ) {
419e6a862fbSDouglas Leavitt return( LDAP_LOCAL_ERROR );
420e6a862fbSDouglas Leavitt }
4217c478bd9Sstevel@tonic-gate rc = ber_sockbuf_get_option( sb,
4227c478bd9Sstevel@tonic-gate LBER_SOCKBUF_OPT_TO_FILE_ONLY,
4237c478bd9Sstevel@tonic-gate (void *) &value);
4247c478bd9Sstevel@tonic-gate if (rc != 0 || value != 0)
4257c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate if (encrypt) {
4287c478bd9Sstevel@tonic-gate /* initialize input buffer - use MAX SIZE to avoid reallocs */
4297c478bd9Sstevel@tonic-gate sb->sb_sasl_ctx = (sasl_conn_t *)ctx_arg;
4307c478bd9Sstevel@tonic-gate rc = sasl_getprop( sb->sb_sasl_ctx, SASL_SEC_PROPS,
4317c478bd9Sstevel@tonic-gate (const void **)&secprops );
4327c478bd9Sstevel@tonic-gate if (rc != SASL_OK)
4337c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
4347c478bd9Sstevel@tonic-gate bufsiz = secprops->maxbufsize;
4357c478bd9Sstevel@tonic-gate if (bufsiz <= 0) {
4367c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate if ((sb->sb_sasl_ibuf = NSLDAPI_MALLOC(bufsiz)) == NULL) {
4397c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate sb->sb_sasl_iptr = NULL;
4427c478bd9Sstevel@tonic-gate sb->sb_sasl_bfsz = bufsiz;
4437c478bd9Sstevel@tonic-gate sb->sb_sasl_ilen = 0;
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate /* Reset Session then Socket Args */
4477c478bd9Sstevel@tonic-gate /* Get old values */
4487c478bd9Sstevel@tonic-gate (void) memset( &sb->sb_sasl_fns, 0, LBER_X_EXTIO_FNS_SIZE);
4497c478bd9Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
4507c478bd9Sstevel@tonic-gate rc = ber_sockbuf_get_option( sb,
4517c478bd9Sstevel@tonic-gate LBER_SOCKBUF_OPT_EXT_IO_FNS,
4527c478bd9Sstevel@tonic-gate (void *)&sb->sb_sasl_fns);
453e6a862fbSDouglas Leavitt if (rc != 0) {
454e6a862fbSDouglas Leavitt destroy_sasliobuf(sb);
455e6a862fbSDouglas Leavitt return( LDAP_LOCAL_ERROR );
456e6a862fbSDouglas Leavitt }
4577c478bd9Sstevel@tonic-gate memset( &ld->ld_sasl_io_fns, 0, sizeof(iofns));
4587c478bd9Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
4597c478bd9Sstevel@tonic-gate rc = ldap_get_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS,
4607c478bd9Sstevel@tonic-gate &ld->ld_sasl_io_fns );
461e6a862fbSDouglas Leavitt if (rc != 0 ) {
462e6a862fbSDouglas Leavitt destroy_sasliobuf(sb);
4637c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
464e6a862fbSDouglas Leavitt }
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate /* Set new values */
4677c478bd9Sstevel@tonic-gate if ( ld->ld_sasl_io_fns.lextiof_read != NULL ||
4687c478bd9Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_write != NULL ||
4697c478bd9Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_poll != NULL ||
4707c478bd9Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_connect != NULL ||
4717c478bd9Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_close != NULL ) {
4727c478bd9Sstevel@tonic-gate memset( &iofns, 0, sizeof(iofns));
4737c478bd9Sstevel@tonic-gate iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
4747c478bd9Sstevel@tonic-gate if (encrypt) {
4757c478bd9Sstevel@tonic-gate iofns.lextiof_read = nsldapi_sasl_read;
4767c478bd9Sstevel@tonic-gate iofns.lextiof_write = nsldapi_sasl_write;
4777c478bd9Sstevel@tonic-gate iofns.lextiof_poll = nsldapi_sasl_poll;
4787c478bd9Sstevel@tonic-gate } else {
4797c478bd9Sstevel@tonic-gate iofns.lextiof_read = nsldapi_sasl_ne_read;
4807c478bd9Sstevel@tonic-gate iofns.lextiof_write = nsldapi_sasl_ne_write;
4817c478bd9Sstevel@tonic-gate iofns.lextiof_poll = nsldapi_sasl_poll;
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate iofns.lextiof_connect = ld->ld_sasl_io_fns.lextiof_connect;
4847c478bd9Sstevel@tonic-gate iofns.lextiof_close = nsldapi_sasl_close_socket;
4857c478bd9Sstevel@tonic-gate iofns.lextiof_newhandle = ld->ld_sasl_io_fns.lextiof_newhandle;
4867c478bd9Sstevel@tonic-gate iofns.lextiof_disposehandle =
4877c478bd9Sstevel@tonic-gate ld->ld_sasl_io_fns.lextiof_disposehandle;
4887c478bd9Sstevel@tonic-gate iofns.lextiof_session_arg =
4897c478bd9Sstevel@tonic-gate (void *) sb;
4907c478bd9Sstevel@tonic-gate /* ld->ld_sasl_io_fns.lextiof_session_arg; */
4917c478bd9Sstevel@tonic-gate rc = ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS,
4927c478bd9Sstevel@tonic-gate &iofns );
493e6a862fbSDouglas Leavitt if (rc != 0 ) {
494e6a862fbSDouglas Leavitt destroy_sasliobuf(sb);
4957c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
496e6a862fbSDouglas Leavitt }
4977c478bd9Sstevel@tonic-gate sb->sb_sasl_prld = (void *)ld;
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate if (encrypt) {
5017c478bd9Sstevel@tonic-gate (void) memset( &fns, 0, LBER_X_EXTIO_FNS_SIZE);
5027c478bd9Sstevel@tonic-gate fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
5037c478bd9Sstevel@tonic-gate fns.lbextiofn_read = nsldapi_sasl_read;
5047c478bd9Sstevel@tonic-gate fns.lbextiofn_write = nsldapi_sasl_write;
5057c478bd9Sstevel@tonic-gate fns.lbextiofn_socket_arg =
5067c478bd9Sstevel@tonic-gate (void *) sb;
5077c478bd9Sstevel@tonic-gate /* (void *)sb->sb_sasl_fns.lbextiofn_socket_arg; */
5087c478bd9Sstevel@tonic-gate rc = ber_sockbuf_set_option( sb,
5097c478bd9Sstevel@tonic-gate LBER_SOCKBUF_OPT_EXT_IO_FNS,
5107c478bd9Sstevel@tonic-gate (void *)&fns);
511e6a862fbSDouglas Leavitt if (rc != 0) {
512e6a862fbSDouglas Leavitt destroy_sasliobuf(sb);
5137c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
514e6a862fbSDouglas Leavitt }
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS );
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_cvterrno(LDAP * ld,int err,char * msg)521e6a862fbSDouglas Leavitt nsldapi_sasl_cvterrno( LDAP *ld, int err, char *msg )
5227c478bd9Sstevel@tonic-gate {
5237c478bd9Sstevel@tonic-gate int rc = LDAP_LOCAL_ERROR;
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate switch (err) {
5267c478bd9Sstevel@tonic-gate case SASL_OK:
5277c478bd9Sstevel@tonic-gate rc = LDAP_SUCCESS;
5287c478bd9Sstevel@tonic-gate break;
5297c478bd9Sstevel@tonic-gate case SASL_NOMECH:
5307c478bd9Sstevel@tonic-gate rc = LDAP_AUTH_UNKNOWN;
5317c478bd9Sstevel@tonic-gate break;
5327c478bd9Sstevel@tonic-gate case SASL_BADSERV:
5337c478bd9Sstevel@tonic-gate rc = LDAP_CONNECT_ERROR;
5347c478bd9Sstevel@tonic-gate break;
5357c478bd9Sstevel@tonic-gate case SASL_DISABLED:
5367c478bd9Sstevel@tonic-gate case SASL_ENCRYPT:
5377c478bd9Sstevel@tonic-gate case SASL_EXPIRED:
5387c478bd9Sstevel@tonic-gate case SASL_NOUSERPASS:
5397c478bd9Sstevel@tonic-gate case SASL_NOVERIFY:
5407c478bd9Sstevel@tonic-gate case SASL_PWLOCK:
5417c478bd9Sstevel@tonic-gate case SASL_TOOWEAK:
5427c478bd9Sstevel@tonic-gate case SASL_UNAVAIL:
5437c478bd9Sstevel@tonic-gate case SASL_WEAKPASS:
5447c478bd9Sstevel@tonic-gate rc = LDAP_INAPPROPRIATE_AUTH;
5457c478bd9Sstevel@tonic-gate break;
5467c478bd9Sstevel@tonic-gate case SASL_BADAUTH:
5477c478bd9Sstevel@tonic-gate case SASL_NOAUTHZ:
5487c478bd9Sstevel@tonic-gate rc = LDAP_INVALID_CREDENTIALS;
5497c478bd9Sstevel@tonic-gate break;
5507c478bd9Sstevel@tonic-gate case SASL_NOMEM:
5517c478bd9Sstevel@tonic-gate rc = LDAP_NO_MEMORY;
5527c478bd9Sstevel@tonic-gate break;
5537c478bd9Sstevel@tonic-gate case SASL_NOUSER:
5547c478bd9Sstevel@tonic-gate rc = LDAP_NO_SUCH_OBJECT;
5557c478bd9Sstevel@tonic-gate break;
5567c478bd9Sstevel@tonic-gate case SASL_CONTINUE:
5577c478bd9Sstevel@tonic-gate case SASL_FAIL:
5587c478bd9Sstevel@tonic-gate case SASL_INTERACT:
5597c478bd9Sstevel@tonic-gate default:
5607c478bd9Sstevel@tonic-gate rc = LDAP_LOCAL_ERROR;
5617c478bd9Sstevel@tonic-gate break;
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate
564e6a862fbSDouglas Leavitt LDAP_SET_LDERRNO( ld, rc, NULL, msg );
5657c478bd9Sstevel@tonic-gate return( rc );
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate int
nsldapi_sasl_open(LDAP * ld)5697c478bd9Sstevel@tonic-gate nsldapi_sasl_open(LDAP *ld)
5707c478bd9Sstevel@tonic-gate {
5717c478bd9Sstevel@tonic-gate Sockbuf *sb;
5727c478bd9Sstevel@tonic-gate char * host;
5737c478bd9Sstevel@tonic-gate int saslrc;
574e6a862fbSDouglas Leavitt sasl_conn_t *ctx = NULL;
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate if (ld == NULL) {
5777c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate if (ld->ld_defconn == NULL) {
5817c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
5827c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate sb = ld->ld_defconn->lconn_sb;
5857c478bd9Sstevel@tonic-gate host = ld->ld_defhost;
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate if ( sb == NULL || host == NULL ) {
5887c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
5897c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate
592e6a862fbSDouglas Leavitt if (sb->sb_sasl_ctx) {
593e6a862fbSDouglas Leavitt sasl_dispose(&sb->sb_sasl_ctx);
594e6a862fbSDouglas Leavitt sb->sb_sasl_ctx = NULL;
595e6a862fbSDouglas Leavitt }
596e6a862fbSDouglas Leavitt
5977c478bd9Sstevel@tonic-gate /* SASL is not properly initialized */
5987c478bd9Sstevel@tonic-gate mutex_lock(&sasl_mutex);
5997c478bd9Sstevel@tonic-gate if (gctx == NULL) {
6007c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
6017c478bd9Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
6027c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate saslrc = _sasl_client_new(gctx, "ldap", host,
6067c478bd9Sstevel@tonic-gate NULL, NULL, /* iplocal ipremote strings currently unused */
6077c478bd9Sstevel@tonic-gate NULL, 0, &ctx );
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate if ( saslrc != SASL_OK ) {
6107c478bd9Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
611e6a862fbSDouglas Leavitt sasl_dispose(&ctx);
612e6a862fbSDouglas Leavitt return( nsldapi_sasl_cvterrno( ld, saslrc, NULL ) );
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate sb->sb_sasl_ctx = (void *)ctx;
6167c478bd9Sstevel@tonic-gate mutex_unlock(&sasl_mutex);
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS );
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate
6210c71ee58SMilan Jurik static void
destroy_sasliobuf(Sockbuf * sb)6220c71ee58SMilan Jurik destroy_sasliobuf(Sockbuf *sb)
6230c71ee58SMilan Jurik {
6240c71ee58SMilan Jurik if (sb != NULL && sb->sb_sasl_ibuf != NULL) {
6250c71ee58SMilan Jurik NSLDAPI_FREE(sb->sb_sasl_ibuf);
6260c71ee58SMilan Jurik sb->sb_sasl_ibuf = NULL;
627e6a862fbSDouglas Leavitt sb->sb_sasl_iptr = NULL;
628e6a862fbSDouglas Leavitt sb->sb_sasl_bfsz = 0;
629e6a862fbSDouglas Leavitt sb->sb_sasl_ilen = 0;
6300c71ee58SMilan Jurik }
6310c71ee58SMilan Jurik }
6320c71ee58SMilan Jurik
6337c478bd9Sstevel@tonic-gate static int
nsldapi_sasl_close(LDAP * ld,Sockbuf * sb)6347c478bd9Sstevel@tonic-gate nsldapi_sasl_close( LDAP *ld, Sockbuf *sb )
6357c478bd9Sstevel@tonic-gate {
6367c478bd9Sstevel@tonic-gate sasl_conn_t *ctx = (sasl_conn_t *)sb->sb_sasl_ctx;
6377c478bd9Sstevel@tonic-gate
6380c71ee58SMilan Jurik destroy_sasliobuf(sb);
6390c71ee58SMilan Jurik
6407c478bd9Sstevel@tonic-gate if( ctx != NULL ) {
6417c478bd9Sstevel@tonic-gate sasl_dispose( &ctx );
6427c478bd9Sstevel@tonic-gate sb->sb_sasl_ctx = NULL;
6437c478bd9Sstevel@tonic-gate }
6447c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS );
6457c478bd9Sstevel@tonic-gate }
6467c478bd9Sstevel@tonic-gate
6477c478bd9Sstevel@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)6487c478bd9Sstevel@tonic-gate nsldapi_sasl_do_bind( LDAP *ld, const char *dn,
6497c478bd9Sstevel@tonic-gate const char *mechs, unsigned flags,
6507c478bd9Sstevel@tonic-gate LDAP_SASL_INTERACT_PROC *callback, void *defaults,
6517c478bd9Sstevel@tonic-gate LDAPControl **sctrl, LDAPControl **cctrl )
6527c478bd9Sstevel@tonic-gate {
6537c478bd9Sstevel@tonic-gate sasl_interact_t *prompts = NULL;
6547c478bd9Sstevel@tonic-gate sasl_conn_t *ctx;
6557c478bd9Sstevel@tonic-gate sasl_ssf_t *ssf = NULL;
6567c478bd9Sstevel@tonic-gate const char *mech = NULL;
6577c478bd9Sstevel@tonic-gate int saslrc, rc;
6587c478bd9Sstevel@tonic-gate struct berval ccred;
6597c478bd9Sstevel@tonic-gate unsigned credlen;
660e6a862fbSDouglas Leavitt int stepnum = 1;
661e6a862fbSDouglas Leavitt char *sasl_username = NULL;
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate if (NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3) {
6647c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
6657c478bd9Sstevel@tonic-gate return( LDAP_NOT_SUPPORTED );
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate /* shouldn't happen */
6697c478bd9Sstevel@tonic-gate if (callback == NULL) {
6707c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate if ( ld->ld_defconn == NULL ||
6747c478bd9Sstevel@tonic-gate ld->ld_defconn->lconn_status != LDAP_CONNST_CONNECTED) {
6757c478bd9Sstevel@tonic-gate rc = nsldapi_open_ldap_defconn( ld );
6767c478bd9Sstevel@tonic-gate if( rc < 0 ) {
6777c478bd9Sstevel@tonic-gate return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
6787c478bd9Sstevel@tonic-gate }
679*55fea89dSDan Cross }
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate /* should have a valid ld connection - now create sasl connection */
6827c478bd9Sstevel@tonic-gate if ((rc = nsldapi_sasl_open(ld)) != LDAP_SUCCESS) {
6837c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
6847c478bd9Sstevel@tonic-gate return( rc );
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate /* expect context to be initialized when connection is open */
6887c478bd9Sstevel@tonic-gate ctx = (sasl_conn_t *)ld->ld_defconn->lconn_sb->sb_sasl_ctx;
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate if( ctx == NULL ) {
6917c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
6927c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate /* (re)set security properties */
6967c478bd9Sstevel@tonic-gate sasl_setprop( ctx, SASL_SEC_PROPS, &ld->ld_sasl_secprops );
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate ccred.bv_val = NULL;
6997c478bd9Sstevel@tonic-gate ccred.bv_len = 0;
7007c478bd9Sstevel@tonic-gate
701e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "Starting SASL/%s authentication\n",
702e6a862fbSDouglas Leavitt (mech ? mech : ""), 0, 0 );
703e6a862fbSDouglas Leavitt
7047c478bd9Sstevel@tonic-gate do {
7057c478bd9Sstevel@tonic-gate saslrc = sasl_client_start( ctx,
7067c478bd9Sstevel@tonic-gate mechs,
7077c478bd9Sstevel@tonic-gate &prompts,
7087c478bd9Sstevel@tonic-gate (const char **)&ccred.bv_val,
7097c478bd9Sstevel@tonic-gate &credlen,
7107c478bd9Sstevel@tonic-gate &mech );
7117c478bd9Sstevel@tonic-gate
712e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of client start for SASL/%s authentication\n",
713e6a862fbSDouglas Leavitt stepnum, (mech ? mech : ""), 0 );
714e6a862fbSDouglas Leavitt stepnum++;
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate if( saslrc == SASL_INTERACT &&
7177c478bd9Sstevel@tonic-gate (callback)(ld, flags, defaults, prompts) != LDAP_SUCCESS ) {
7187c478bd9Sstevel@tonic-gate break;
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate } while ( saslrc == SASL_INTERACT );
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate ccred.bv_len = credlen;
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
725e6a862fbSDouglas Leavitt return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) );
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate
728e6a862fbSDouglas Leavitt stepnum = 1;
729e6a862fbSDouglas Leavitt
7307c478bd9Sstevel@tonic-gate do {
7317c478bd9Sstevel@tonic-gate struct berval *scred;
732e6a862fbSDouglas Leavitt int clientstepnum = 1;
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate scred = NULL;
7357c478bd9Sstevel@tonic-gate
736e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of bind for SASL/%s authentication\n",
737e6a862fbSDouglas Leavitt stepnum, (mech ? mech : ""), 0 );
738e6a862fbSDouglas Leavitt stepnum++;
739e6a862fbSDouglas Leavitt
7407c478bd9Sstevel@tonic-gate /* notify server of a sasl bind step */
7417c478bd9Sstevel@tonic-gate rc = ldap_sasl_bind_s(ld, dn, mech, &ccred,
7427c478bd9Sstevel@tonic-gate sctrl, cctrl, &scred);
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate if ( ccred.bv_val != NULL ) {
7457c478bd9Sstevel@tonic-gate ccred.bv_val = NULL;
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) {
749e6a862fbSDouglas Leavitt ber_bvfree( scred );
7507c478bd9Sstevel@tonic-gate return( rc );
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate
7537c478bd9Sstevel@tonic-gate if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) {
7547c478bd9Sstevel@tonic-gate /* we're done, no need to step */
755e6a862fbSDouglas Leavitt if( scred ) {
756e6a862fbSDouglas Leavitt if (scred->bv_len == 0 ) { /* MS AD sends back empty screds */
757e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_ANY,
758e6a862fbSDouglas Leavitt "SASL BIND complete - ignoring empty credential response\n",
759e6a862fbSDouglas Leavitt 0, 0, 0);
760e6a862fbSDouglas Leavitt ber_bvfree( scred );
761e6a862fbSDouglas Leavitt } else {
7627c478bd9Sstevel@tonic-gate /* but server provided us with data! */
763e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE,
764e6a862fbSDouglas Leavitt "SASL BIND complete but invalid because server responded with credentials - length [%u]\n",
765e6a862fbSDouglas Leavitt scred->bv_len, 0, 0);
7667c478bd9Sstevel@tonic-gate ber_bvfree( scred );
7677c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR,
768e6a862fbSDouglas Leavitt NULL, nsldapi_strdup( dgettext(TEXT_DOMAIN,
769e6a862fbSDouglas Leavitt "Error during SASL handshake - "
770e6a862fbSDouglas Leavitt "invalid server credential response") ));
7717c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR );
772e6a862fbSDouglas Leavitt }
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate break;
7757c478bd9Sstevel@tonic-gate }
7767c478bd9Sstevel@tonic-gate
7777c478bd9Sstevel@tonic-gate /* perform the next step of the sasl bind */
7787c478bd9Sstevel@tonic-gate do {
779e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "Doing client step %d of bind step %d for SASL/%s authentication\n",
780e6a862fbSDouglas Leavitt clientstepnum, stepnum, (mech ? mech : "") );
781e6a862fbSDouglas Leavitt clientstepnum++;
7827c478bd9Sstevel@tonic-gate saslrc = sasl_client_step( ctx,
7837c478bd9Sstevel@tonic-gate (scred == NULL) ? NULL : scred->bv_val,
7847c478bd9Sstevel@tonic-gate (scred == NULL) ? 0 : scred->bv_len,
7857c478bd9Sstevel@tonic-gate &prompts,
7867c478bd9Sstevel@tonic-gate (const char **)&ccred.bv_val,
7877c478bd9Sstevel@tonic-gate &credlen );
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate if( saslrc == SASL_INTERACT &&
7907c478bd9Sstevel@tonic-gate (callback)(ld, flags, defaults, prompts)
7917c478bd9Sstevel@tonic-gate != LDAP_SUCCESS ) {
7927c478bd9Sstevel@tonic-gate break;
7937c478bd9Sstevel@tonic-gate }
7947c478bd9Sstevel@tonic-gate } while ( saslrc == SASL_INTERACT );
7957c478bd9Sstevel@tonic-gate
7967c478bd9Sstevel@tonic-gate ccred.bv_len = credlen;
7977c478bd9Sstevel@tonic-gate ber_bvfree( scred );
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
800e6a862fbSDouglas Leavitt return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) );
8017c478bd9Sstevel@tonic-gate }
8027c478bd9Sstevel@tonic-gate } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate if ( rc != LDAP_SUCCESS ) {
8057c478bd9Sstevel@tonic-gate return( rc );
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate if ( saslrc != SASL_OK ) {
809e6a862fbSDouglas Leavitt return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) );
810e6a862fbSDouglas Leavitt }
811e6a862fbSDouglas Leavitt
812e6a862fbSDouglas Leavitt saslrc = sasl_getprop( ctx, SASL_USERNAME, (const void **) &sasl_username );
813e6a862fbSDouglas Leavitt if ( (saslrc == SASL_OK) && sasl_username ) {
814e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "SASL identity: %s\n", sasl_username, 0, 0);
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate
8177c478bd9Sstevel@tonic-gate saslrc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf );
8187c478bd9Sstevel@tonic-gate if( saslrc == SASL_OK ) {
819e6a862fbSDouglas Leavitt if( ssf && *ssf ) {
820e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE,
821e6a862fbSDouglas Leavitt "SASL install encryption, for SSF: %lu\n",
822e6a862fbSDouglas Leavitt (unsigned long) *ssf, 0, 0 );
823e6a862fbSDouglas Leavitt }
8247c478bd9Sstevel@tonic-gate rc = nsldapi_sasl_install(ld, ld->ld_conns->lconn_sb, ctx, ssf);
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate return( rc );
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate #ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER
8317c478bd9Sstevel@tonic-gate /*
8327c478bd9Sstevel@tonic-gate * Get available SASL Mechanisms supported by the server
8337c478bd9Sstevel@tonic-gate */
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate static int
nsldapi_get_sasl_mechs(LDAP * ld,char ** pmech)8367c478bd9Sstevel@tonic-gate nsldapi_get_sasl_mechs ( LDAP *ld, char **pmech )
8377c478bd9Sstevel@tonic-gate {
8387c478bd9Sstevel@tonic-gate char *attr[] = { "supportedSASLMechanisms", NULL };
8397c478bd9Sstevel@tonic-gate char **values, **v, *mech, *m;
8407c478bd9Sstevel@tonic-gate LDAPMessage *res, *e;
8417c478bd9Sstevel@tonic-gate struct timeval timeout;
8427c478bd9Sstevel@tonic-gate int slen, rc;
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
8457c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
8467c478bd9Sstevel@tonic-gate }
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate timeout.tv_sec = SEARCH_TIMEOUT_SECS;
8497c478bd9Sstevel@tonic-gate timeout.tv_usec = 0;
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate rc = ldap_search_st( ld, "", LDAP_SCOPE_BASE,
8527c478bd9Sstevel@tonic-gate "objectclass=*", attr, 0, &timeout, &res );
8537c478bd9Sstevel@tonic-gate
8547c478bd9Sstevel@tonic-gate if ( rc != LDAP_SUCCESS ) {
8557c478bd9Sstevel@tonic-gate return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
8567c478bd9Sstevel@tonic-gate }
857*55fea89dSDan Cross
8587c478bd9Sstevel@tonic-gate e = ldap_first_entry( ld, res );
8597c478bd9Sstevel@tonic-gate if ( e == NULL ) {
8607c478bd9Sstevel@tonic-gate ldap_msgfree( res );
8617c478bd9Sstevel@tonic-gate if ( ld->ld_errno == LDAP_SUCCESS ) {
8627c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_OBJECT, NULL, NULL );
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate values = ldap_get_values( ld, e, "supportedSASLMechanisms" );
8687c478bd9Sstevel@tonic-gate if ( values == NULL ) {
8697c478bd9Sstevel@tonic-gate ldap_msgfree( res );
8707c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL );
8717c478bd9Sstevel@tonic-gate return( LDAP_NO_SUCH_ATTRIBUTE );
8727c478bd9Sstevel@tonic-gate }
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate slen = 0;
8757c478bd9Sstevel@tonic-gate for(v = values; *v != NULL; v++ ) {
8767c478bd9Sstevel@tonic-gate slen += strlen(*v) + 1;
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate if ( (mech = NSLDAPI_CALLOC(1, slen)) == NULL) {
8797c478bd9Sstevel@tonic-gate ldap_value_free( values );
8807c478bd9Sstevel@tonic-gate ldap_msgfree( res );
8817c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
8827c478bd9Sstevel@tonic-gate return( LDAP_NO_MEMORY );
883*55fea89dSDan Cross }
8847c478bd9Sstevel@tonic-gate m = mech;
8857c478bd9Sstevel@tonic-gate for(v = values; *v; v++) {
8867c478bd9Sstevel@tonic-gate if (v != values) {
8877c478bd9Sstevel@tonic-gate *m++ = ' ';
8887c478bd9Sstevel@tonic-gate }
8897c478bd9Sstevel@tonic-gate slen = strlen(*v);
8907c478bd9Sstevel@tonic-gate strncpy(m, *v, slen);
8917c478bd9Sstevel@tonic-gate m += slen;
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate *m = '\0';
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate ldap_value_free( values );
8967c478bd9Sstevel@tonic-gate ldap_msgfree( res );
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate *pmech = mech;
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS );
9017c478bd9Sstevel@tonic-gate }
9027c478bd9Sstevel@tonic-gate #endif
9037c478bd9Sstevel@tonic-gate
nsldapi_sasl_secprops(const char * in,sasl_security_properties_t * secprops)9047c478bd9Sstevel@tonic-gate int nsldapi_sasl_secprops(
9057c478bd9Sstevel@tonic-gate const char *in,
9067c478bd9Sstevel@tonic-gate sasl_security_properties_t *secprops )
9077c478bd9Sstevel@tonic-gate {
9087c478bd9Sstevel@tonic-gate int i;
9097c478bd9Sstevel@tonic-gate char **props = NULL;
9107c478bd9Sstevel@tonic-gate char *inp;
9117c478bd9Sstevel@tonic-gate unsigned sflags = 0;
9127c478bd9Sstevel@tonic-gate sasl_ssf_t max_ssf = 0;
9137c478bd9Sstevel@tonic-gate sasl_ssf_t min_ssf = 0;
9147c478bd9Sstevel@tonic-gate unsigned maxbufsize = 0;
9157c478bd9Sstevel@tonic-gate int got_sflags = 0;
9167c478bd9Sstevel@tonic-gate int got_max_ssf = 0;
9177c478bd9Sstevel@tonic-gate int got_min_ssf = 0;
9187c478bd9Sstevel@tonic-gate int got_maxbufsize = 0;
9197c478bd9Sstevel@tonic-gate
9207c478bd9Sstevel@tonic-gate if (in == NULL) {
9217c478bd9Sstevel@tonic-gate return LDAP_PARAM_ERROR;
9227c478bd9Sstevel@tonic-gate }
9237c478bd9Sstevel@tonic-gate inp = nsldapi_strdup(in);
9247c478bd9Sstevel@tonic-gate if (inp == NULL) {
9257c478bd9Sstevel@tonic-gate return LDAP_PARAM_ERROR;
9267c478bd9Sstevel@tonic-gate }
9277c478bd9Sstevel@tonic-gate props = ldap_str2charray( inp, "," );
9287c478bd9Sstevel@tonic-gate NSLDAPI_FREE( inp );
929*55fea89dSDan Cross
9307c478bd9Sstevel@tonic-gate if( props == NULL || secprops == NULL ) {
9317c478bd9Sstevel@tonic-gate return LDAP_PARAM_ERROR;
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate for( i=0; props[i]; i++ ) {
9357c478bd9Sstevel@tonic-gate if( strcasecmp(props[i], "none") == 0 ) {
9367c478bd9Sstevel@tonic-gate got_sflags++;
9377c478bd9Sstevel@tonic-gate
9387c478bd9Sstevel@tonic-gate } else if( strcasecmp(props[i], "noactive") == 0 ) {
9397c478bd9Sstevel@tonic-gate got_sflags++;
9407c478bd9Sstevel@tonic-gate sflags |= SASL_SEC_NOACTIVE;
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate } else if( strcasecmp(props[i], "noanonymous") == 0 ) {
9437c478bd9Sstevel@tonic-gate got_sflags++;
9447c478bd9Sstevel@tonic-gate sflags |= SASL_SEC_NOANONYMOUS;
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gate } else if( strcasecmp(props[i], "nodict") == 0 ) {
9477c478bd9Sstevel@tonic-gate got_sflags++;
9487c478bd9Sstevel@tonic-gate sflags |= SASL_SEC_NODICTIONARY;
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate } else if( strcasecmp(props[i], "noplain") == 0 ) {
9517c478bd9Sstevel@tonic-gate got_sflags++;
9527c478bd9Sstevel@tonic-gate sflags |= SASL_SEC_NOPLAINTEXT;
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate } else if( strcasecmp(props[i], "forwardsec") == 0 ) {
9557c478bd9Sstevel@tonic-gate got_sflags++;
9567c478bd9Sstevel@tonic-gate sflags |= SASL_SEC_FORWARD_SECRECY;
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate } else if( strcasecmp(props[i], "passcred") == 0 ) {
9597c478bd9Sstevel@tonic-gate got_sflags++;
9607c478bd9Sstevel@tonic-gate sflags |= SASL_SEC_PASS_CREDENTIALS;
9617c478bd9Sstevel@tonic-gate
9627c478bd9Sstevel@tonic-gate } else if( strncasecmp(props[i],
9637c478bd9Sstevel@tonic-gate "minssf=", sizeof("minssf")) == 0 ) {
9647c478bd9Sstevel@tonic-gate if( isdigit( props[i][sizeof("minssf")] ) ) {
9657c478bd9Sstevel@tonic-gate got_min_ssf++;
9667c478bd9Sstevel@tonic-gate min_ssf = atoi( &props[i][sizeof("minssf")] );
9677c478bd9Sstevel@tonic-gate } else {
9687c478bd9Sstevel@tonic-gate return LDAP_NOT_SUPPORTED;
9697c478bd9Sstevel@tonic-gate }
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate } else if( strncasecmp(props[i],
9727c478bd9Sstevel@tonic-gate "maxssf=", sizeof("maxssf")) == 0 ) {
9737c478bd9Sstevel@tonic-gate if( isdigit( props[i][sizeof("maxssf")] ) ) {
9747c478bd9Sstevel@tonic-gate got_max_ssf++;
9757c478bd9Sstevel@tonic-gate max_ssf = atoi( &props[i][sizeof("maxssf")] );
9767c478bd9Sstevel@tonic-gate } else {
9777c478bd9Sstevel@tonic-gate return LDAP_NOT_SUPPORTED;
9787c478bd9Sstevel@tonic-gate }
9797c478bd9Sstevel@tonic-gate
9807c478bd9Sstevel@tonic-gate } else if( strncasecmp(props[i],
9817c478bd9Sstevel@tonic-gate "maxbufsize=", sizeof("maxbufsize")) == 0 ) {
9827c478bd9Sstevel@tonic-gate if( isdigit( props[i][sizeof("maxbufsize")] ) ) {
9837c478bd9Sstevel@tonic-gate got_maxbufsize++;
9847c478bd9Sstevel@tonic-gate maxbufsize = atoi( &props[i][sizeof("maxbufsize")] );
9857c478bd9Sstevel@tonic-gate if( maxbufsize &&
9867c478bd9Sstevel@tonic-gate (( maxbufsize < SASL_MIN_BUFF_SIZE )
9877c478bd9Sstevel@tonic-gate || (maxbufsize > SASL_MAX_BUFF_SIZE ))) {
9887c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate } else {
9917c478bd9Sstevel@tonic-gate return( LDAP_NOT_SUPPORTED );
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate } else {
9947c478bd9Sstevel@tonic-gate return( LDAP_NOT_SUPPORTED );
9957c478bd9Sstevel@tonic-gate }
9967c478bd9Sstevel@tonic-gate }
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate if(got_sflags) {
9997c478bd9Sstevel@tonic-gate secprops->security_flags = sflags;
10007c478bd9Sstevel@tonic-gate }
10017c478bd9Sstevel@tonic-gate if(got_min_ssf) {
10027c478bd9Sstevel@tonic-gate secprops->min_ssf = min_ssf;
10037c478bd9Sstevel@tonic-gate }
10047c478bd9Sstevel@tonic-gate if(got_max_ssf) {
10057c478bd9Sstevel@tonic-gate secprops->max_ssf = max_ssf;
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate if(got_maxbufsize) {
10087c478bd9Sstevel@tonic-gate secprops->maxbufsize = maxbufsize;
10097c478bd9Sstevel@tonic-gate }
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate ldap_charray_free( props );
10127c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS );
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate /*
10167c478bd9Sstevel@tonic-gate * SASL Authentication Interface: ldap_sasl_interactive_bind_s
10177c478bd9Sstevel@tonic-gate *
10187c478bd9Sstevel@tonic-gate * This routine takes a DN, SASL mech list, and a SASL callback
10197c478bd9Sstevel@tonic-gate * and performs the necessary sequencing to complete a SASL bind
10207c478bd9Sstevel@tonic-gate * to the LDAP connection ld. The user provided callback can
10217c478bd9Sstevel@tonic-gate * use an optionally provided set of default values to complete
10227c478bd9Sstevel@tonic-gate * any necessary interactions.
10237c478bd9Sstevel@tonic-gate *
10247c478bd9Sstevel@tonic-gate * Currently inpose the following restrictions:
10257c478bd9Sstevel@tonic-gate * A mech list must be provided, only LDAP_SASL_INTERACTIVE
10267c478bd9Sstevel@tonic-gate * mode is supported
10277c478bd9Sstevel@tonic-gate */
10287c478bd9Sstevel@tonic-gate int
10297c478bd9Sstevel@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)10307c478bd9Sstevel@tonic-gate ldap_sasl_interactive_bind_s( LDAP *ld, const char *dn,
10317c478bd9Sstevel@tonic-gate const char *saslMechanism,
10327c478bd9Sstevel@tonic-gate LDAPControl **sctrl, LDAPControl **cctrl, unsigned flags,
10337c478bd9Sstevel@tonic-gate LDAP_SASL_INTERACT_PROC *callback, void *defaults )
10347c478bd9Sstevel@tonic-gate {
10357c478bd9Sstevel@tonic-gate #ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER
10367c478bd9Sstevel@tonic-gate char *smechs;
10377c478bd9Sstevel@tonic-gate #endif
10387c478bd9Sstevel@tonic-gate int rc;
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate LDAPDebug(LDAP_DEBUG_TRACE, "ldap_sasl_interactive_bind_s\n", 0, 0, 0);
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
10437c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
10447c478bd9Sstevel@tonic-gate }
10457c478bd9Sstevel@tonic-gate
10467c478bd9Sstevel@tonic-gate if (flags != LDAP_SASL_INTERACTIVE || callback == NULL) {
10477c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate LDAP_MUTEX_LOCK(ld, LDAP_SASL_LOCK );
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate if( saslMechanism == NULL || *saslMechanism == '\0' ) {
10537c478bd9Sstevel@tonic-gate #ifdef LDAP_SASLIO_GET_MECHS_FROM_SERVER
10547c478bd9Sstevel@tonic-gate rc = nsldapi_get_sasl_mechs( ld, &smechs );
10557c478bd9Sstevel@tonic-gate if( rc != LDAP_SUCCESS ) {
10567c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK );
10577c478bd9Sstevel@tonic-gate return( rc );
10587c478bd9Sstevel@tonic-gate }
10597c478bd9Sstevel@tonic-gate saslMechanism = smechs;
10607c478bd9Sstevel@tonic-gate #else
10617c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK );
10627c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
10637c478bd9Sstevel@tonic-gate #endif
10647c478bd9Sstevel@tonic-gate }
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate /* initialize SASL library */
10677c478bd9Sstevel@tonic-gate if ( nsldapi_sasl_init() < 0 ) {
10687c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate rc = nsldapi_sasl_do_bind( ld, dn, saslMechanism,
10727c478bd9Sstevel@tonic-gate flags, callback, defaults, sctrl, cctrl);
10737c478bd9Sstevel@tonic-gate
10747c478bd9Sstevel@tonic-gate LDAP_MUTEX_UNLOCK(ld, LDAP_SASL_LOCK );
10757c478bd9Sstevel@tonic-gate return( rc );
10767c478bd9Sstevel@tonic-gate }
10777c478bd9Sstevel@tonic-gate
10787c478bd9Sstevel@tonic-gate #endif
1079