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 /* 22*e6a862fbSDouglas 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 ); 54*e6a862fbSDouglas 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 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 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 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 1367c478bd9Sstevel@tonic-gate 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 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; 1547c478bd9Sstevel@tonic-gate 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; 1817c478bd9Sstevel@tonic-gate 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 } 2447c478bd9Sstevel@tonic-gate 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 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; 267*e6a862fbSDouglas Leavitt int ret = 0; 268*e6a862fbSDouglas Leavitt const char *obuf, *optr, *cbuf = (const char *)buf; 269*e6a862fbSDouglas Leavitt unsigned olen, clen, tlen = 0; 270*e6a862fbSDouglas Leavitt unsigned *maxbuf; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (sb == NULL) { 2737c478bd9Sstevel@tonic-gate return( -1 ); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 276*e6a862fbSDouglas Leavitt ret = sasl_getprop(sb->sb_sasl_ctx, SASL_MAXOUTBUF, 277*e6a862fbSDouglas Leavitt (const void **)&maxbuf); 278*e6a862fbSDouglas Leavitt if ( ret != SASL_OK ) { 279*e6a862fbSDouglas Leavitt /* just a sanity check, should never happen */ 280*e6a862fbSDouglas Leavitt return( -1 ); 281*e6a862fbSDouglas Leavitt } 282*e6a862fbSDouglas Leavitt 283*e6a862fbSDouglas Leavitt while (len > 0) { 284*e6a862fbSDouglas Leavitt clen = (len > *maxbuf) ? *maxbuf : len; 2857c478bd9Sstevel@tonic-gate /* encode the next packet. */ 286*e6a862fbSDouglas Leavitt ret = sasl_encode( sb->sb_sasl_ctx, cbuf, clen, &obuf, &olen); 2877c478bd9Sstevel@tonic-gate if ( ret != SASL_OK ) { 2887c478bd9Sstevel@tonic-gate /* XXX Log error? "sb_sasl_write: failed to encode packet..." */ 2897c478bd9Sstevel@tonic-gate return( -1 ); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate /* Write everything now, buffer is only good until next sasl_encode */ 2927c478bd9Sstevel@tonic-gate optr = obuf; 2937c478bd9Sstevel@tonic-gate while (olen > 0) { 2947c478bd9Sstevel@tonic-gate if (sb->sb_sasl_fns.lbextiofn_write != NULL) { 2957c478bd9Sstevel@tonic-gate ret = sb->sb_sasl_fns.lbextiofn_write( 2967c478bd9Sstevel@tonic-gate s, optr, olen, 2977c478bd9Sstevel@tonic-gate sb->sb_sasl_fns.lbextiofn_socket_arg); 2987c478bd9Sstevel@tonic-gate } else { 2997c478bd9Sstevel@tonic-gate ret = write( sb->sb_sd, optr, olen); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate if ( ret < 0 ) 3027c478bd9Sstevel@tonic-gate return( ret ); 3037c478bd9Sstevel@tonic-gate optr += ret; 3047c478bd9Sstevel@tonic-gate olen -= ret; 3057c478bd9Sstevel@tonic-gate } 306*e6a862fbSDouglas Leavitt len -= clen; 307*e6a862fbSDouglas Leavitt cbuf += clen; 308*e6a862fbSDouglas Leavitt tlen += clen; 309*e6a862fbSDouglas Leavitt } 310*e6a862fbSDouglas Leavitt return( tlen ); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate static int 3147c478bd9Sstevel@tonic-gate nsldapi_sasl_poll( 3157c478bd9Sstevel@tonic-gate LDAP_X_PollFD fds[], int nfds, int timeout, 3167c478bd9Sstevel@tonic-gate 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 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; 3527c478bd9Sstevel@tonic-gate 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 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 3767c478bd9Sstevel@tonic-gate 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 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 } 418*e6a862fbSDouglas Leavitt if ( sb == NULL ) { 419*e6a862fbSDouglas Leavitt return( LDAP_LOCAL_ERROR ); 420*e6a862fbSDouglas 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); 453*e6a862fbSDouglas Leavitt if (rc != 0) { 454*e6a862fbSDouglas Leavitt destroy_sasliobuf(sb); 455*e6a862fbSDouglas Leavitt return( LDAP_LOCAL_ERROR ); 456*e6a862fbSDouglas 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 ); 461*e6a862fbSDouglas Leavitt if (rc != 0 ) { 462*e6a862fbSDouglas Leavitt destroy_sasliobuf(sb); 4637c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); 464*e6a862fbSDouglas 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 ); 493*e6a862fbSDouglas Leavitt if (rc != 0 ) { 494*e6a862fbSDouglas Leavitt destroy_sasliobuf(sb); 4957c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); 496*e6a862fbSDouglas 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); 511*e6a862fbSDouglas Leavitt if (rc != 0) { 512*e6a862fbSDouglas Leavitt destroy_sasliobuf(sb); 5137c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); 5147c478bd9Sstevel@tonic-gate } 515*e6a862fbSDouglas Leavitt } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS ); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate static int 521*e6a862fbSDouglas 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 564*e6a862fbSDouglas Leavitt LDAP_SET_LDERRNO( ld, rc, NULL, msg ); 5657c478bd9Sstevel@tonic-gate return( rc ); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate int 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; 574*e6a862fbSDouglas 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 592*e6a862fbSDouglas Leavitt if (sb->sb_sasl_ctx) { 593*e6a862fbSDouglas Leavitt sasl_dispose(&sb->sb_sasl_ctx); 594*e6a862fbSDouglas Leavitt sb->sb_sasl_ctx = NULL; 595*e6a862fbSDouglas Leavitt } 596*e6a862fbSDouglas 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); 611*e6a862fbSDouglas Leavitt sasl_dispose(&ctx); 612*e6a862fbSDouglas 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 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; 627*e6a862fbSDouglas Leavitt sb->sb_sasl_iptr = NULL; 628*e6a862fbSDouglas Leavitt sb->sb_sasl_bfsz = 0; 629*e6a862fbSDouglas Leavitt sb->sb_sasl_ilen = 0; 6300c71ee58SMilan Jurik } 6310c71ee58SMilan Jurik } 6320c71ee58SMilan Jurik 6337c478bd9Sstevel@tonic-gate static int 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 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; 660*e6a862fbSDouglas Leavitt int stepnum = 1; 661*e6a862fbSDouglas 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 } 6797c478bd9Sstevel@tonic-gate } 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 701*e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "Starting SASL/%s authentication\n", 702*e6a862fbSDouglas Leavitt (mech ? mech : ""), 0, 0 ); 703*e6a862fbSDouglas 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 712*e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of client start for SASL/%s authentication\n", 713*e6a862fbSDouglas Leavitt stepnum, (mech ? mech : ""), 0 ); 714*e6a862fbSDouglas 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) ) { 725*e6a862fbSDouglas Leavitt return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 728*e6a862fbSDouglas Leavitt stepnum = 1; 729*e6a862fbSDouglas Leavitt 7307c478bd9Sstevel@tonic-gate do { 7317c478bd9Sstevel@tonic-gate struct berval *scred; 732*e6a862fbSDouglas Leavitt int clientstepnum = 1; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate scred = NULL; 7357c478bd9Sstevel@tonic-gate 736*e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "Doing step %d of bind for SASL/%s authentication\n", 737*e6a862fbSDouglas Leavitt stepnum, (mech ? mech : ""), 0 ); 738*e6a862fbSDouglas Leavitt stepnum++; 739*e6a862fbSDouglas 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 ) { 7497c478bd9Sstevel@tonic-gate 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 */ 755*e6a862fbSDouglas Leavitt if( scred ) { 756*e6a862fbSDouglas Leavitt if (scred->bv_len == 0 ) { /* MS AD sends back empty screds */ 757*e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_ANY, 758*e6a862fbSDouglas Leavitt "SASL BIND complete - ignoring empty credential response\n", 759*e6a862fbSDouglas Leavitt 0, 0, 0); 760*e6a862fbSDouglas Leavitt ber_bvfree( scred ); 761*e6a862fbSDouglas Leavitt } else { 7627c478bd9Sstevel@tonic-gate /* but server provided us with data! */ 763*e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, 764*e6a862fbSDouglas Leavitt "SASL BIND complete but invalid because server responded with credentials - length [%u]\n", 765*e6a862fbSDouglas Leavitt scred->bv_len, 0, 0); 7667c478bd9Sstevel@tonic-gate ber_bvfree( scred ); 7677c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, 768*e6a862fbSDouglas Leavitt NULL, nsldapi_strdup( dgettext(TEXT_DOMAIN, 769*e6a862fbSDouglas Leavitt "Error during SASL handshake - " 770*e6a862fbSDouglas Leavitt "invalid server credential response") )); 7717c478bd9Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); 7727c478bd9Sstevel@tonic-gate } 773*e6a862fbSDouglas Leavitt } 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 { 779*e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, "Doing client step %d of bind step %d for SASL/%s authentication\n", 780*e6a862fbSDouglas Leavitt clientstepnum, stepnum, (mech ? mech : "") ); 781*e6a862fbSDouglas 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) ) { 800*e6a862fbSDouglas 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 ) { 809*e6a862fbSDouglas Leavitt return( nsldapi_sasl_cvterrno( ld, saslrc, nsldapi_strdup( sasl_errdetail( ctx ) ) ) ); 810*e6a862fbSDouglas Leavitt } 811*e6a862fbSDouglas Leavitt 812*e6a862fbSDouglas Leavitt saslrc = sasl_getprop( ctx, SASL_USERNAME, (const void **) &sasl_username ); 813*e6a862fbSDouglas Leavitt if ( (saslrc == SASL_OK) && sasl_username ) { 814*e6a862fbSDouglas 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 ) { 819*e6a862fbSDouglas Leavitt if( ssf && *ssf ) { 820*e6a862fbSDouglas Leavitt LDAPDebug(LDAP_DEBUG_TRACE, 821*e6a862fbSDouglas Leavitt "SASL install encryption, for SSF: %lu\n", 822*e6a862fbSDouglas Leavitt (unsigned long) *ssf, 0, 0 ); 823*e6a862fbSDouglas 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 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 } 8577c478bd9Sstevel@tonic-gate 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 ); 8837c478bd9Sstevel@tonic-gate } 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 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 ); 9297c478bd9Sstevel@tonic-gate 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 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