sasl.c revision 0c71ee58938636c3d3ad26d13891ca5d84934f03
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifdef LDAP_SASLIO_HOOKS
#include <assert.h>
#include "ldap-int.h"
#include "../ber/lber-int.h"
#include <thread.h>
#include <synch.h>
#define SEARCH_TIMEOUT_SECS 120
#define NSLDAPI_SM_BUF 128
extern void *sasl_create_context(void);
extern void sasl_free_context(void *ctx);
const char *serverFQDN, const char *iplocalport,
const char *ipremoteport,
const sasl_callback_t *prompt_supp,
extern int _sasl_server_init(void *ctx,
const char *serverFQDN, const char *user_realm,
const char *iplocalport, const char *ipremoteport,
const sasl_callback_t *callbacks,
/*
* SASL Dependent routines
*
* SASL security and integrity options are supported through the
* use of the extended I/O functionality. Because the extended
* I/O functions may already be in use prior to enabling encryption,
* when SASL encryption is enabled, these routine interpose themselves
* over the existng extended I/O routines and add an additional level
* of indirection.
* IE: Before SASL: client->libldap->lber->extio
* After SASL: client->libldap->lber->saslio->extio
* Any extio functions are still used for the raw i/O [IE prldap]
* but SASL will decrypt before passing to lber.
* SASL cannot decrypt a stream so full packets must be read
* before proceeding.
*/
static int nsldapi_sasl_fail()
{
return( SASL_FAIL );
}
/*
* Global SASL Init data
*/
static sasl_callback_t client_callbacks[] = {
};
static int nsldapi_sasl_inited = 0;
static void *gctx; /* intentially not freed - avoid libsasl re-inits */
int nsldapi_sasl_init( void )
{
int saslrc;
if ( nsldapi_sasl_inited ) {
return( 0 );
}
nsldapi_sasl_inited = 1;
return( 0 );
}
}
return( -1 );
}
/*
* SASL encryption routines
*/
/*
* Get the 4 octet header [size] for a sasl encrypted buffer.
* See RFC222 [section 3].
*/
static int
{
int size;
#else
#endif
return (-1 );
}
}
static int
struct lextiof_socket_private *arg)
{
const char *dbuf;
char *cp;
int ret;
return( -1 );
}
return( -1 );
}
/* Is there anything left in the existing buffer? */
sb->sb_sasl_ilen = 0;
} else {
}
return( ret );
}
/* buffer is empty - fill it */
dlen = 0;
/* Read the length of the packet */
while ( dlen < 4 ) {
} else {
}
#ifdef EINTR
continue;
#endif
if ( ret <= 0 )
return( ret );
}
blen = 4;
if (ret < 0) {
return( -1 );
}
/* read the rest of the encrypted packet */
while ( dlen > 0 ) {
} else {
}
#ifdef EINTR
continue;
#endif
if ( ret <= 0 )
return( ret );
}
/* Decode the packet */
/* sb_sasl_read: failed to decode packet, drop it, error */
sb->sb_sasl_ilen = 0;
return( -1 );
}
/* copy decrypted packet to the input buffer */
sb->sb_sasl_ilen = 0;
} else {
}
return( ret );
}
static int
struct lextiof_socket_private *arg)
{
int ret;
unsigned olen;
return( -1 );
}
/* encode the next packet. */
/* XXX Log error? "sb_sasl_write: failed to encode packet..." */
return( -1 );
}
/* Write everything now, buffer is only good until next sasl_encode */
while (olen > 0) {
} else {
}
if ( ret < 0 )
return( ret );
}
return( len );
}
static int
struct lextiof_session_private *arg )
{
int i;
return( -1 );
}
return( -1 );
}
for(i = 0; i < nfds; i++) {
if (fds[i].lpoll_socketarg ==
(struct lextiof_socket_private *)sb) {
fds[i].lpoll_socketarg =
(struct lextiof_socket_private *)
}
}
}
}
/* no encryption indirect routines */
static int
struct lextiof_socket_private *arg)
{
return( -1 );
}
}
static int
struct lextiof_socket_private *arg)
{
return( -1 );
}
}
static int
{
return( -1 );
}
return( -1 );
}
/* undo function pointer interposing */
(void *)&sb->sb_sasl_fns);
/* undo SASL */
(struct lextiof_socket_private *)
}
/*
* install encryption routines if security has been negotiated
*/
static int
{
struct lber_x_ext_io_fns fns;
struct ldap_x_ext_io_fns iofns;
int bufsiz;
int encrypt = 0;
encrypt = 1;
}
(void *) &value);
return( LDAP_LOCAL_ERROR );
if (encrypt) {
/* initialize input buffer - use MAX SIZE to avoid reallocs */
(const void **)&secprops );
return( LDAP_LOCAL_ERROR );
if (bufsiz <= 0) {
return( LDAP_LOCAL_ERROR );
}
return( LDAP_LOCAL_ERROR );
}
sb->sb_sasl_ilen = 0;
}
/* Reset Session then Socket Args */
/* Get old values */
(void *)&sb->sb_sasl_fns);
&ld->ld_sasl_io_fns );
if (rc != 0 )
return( LDAP_LOCAL_ERROR );
/* Set new values */
if (encrypt) {
} else {
}
(void *) sb;
/* ld->ld_sasl_io_fns.lextiof_session_arg; */
&iofns );
if (rc != 0 )
return( LDAP_LOCAL_ERROR );
}
if (encrypt) {
(void *) sb;
/* (void *)sb->sb_sasl_fns.lbextiofn_socket_arg; */
(void *)&fns);
if (rc != 0)
return( LDAP_LOCAL_ERROR );
}
return( LDAP_SUCCESS );
}
static int
{
int rc = LDAP_LOCAL_ERROR;
switch (err) {
case SASL_OK:
rc = LDAP_SUCCESS;
break;
case SASL_NOMECH:
break;
case SASL_BADSERV:
break;
case SASL_DISABLED:
case SASL_ENCRYPT:
case SASL_EXPIRED:
case SASL_NOUSERPASS:
case SASL_NOVERIFY:
case SASL_PWLOCK:
case SASL_TOOWEAK:
case SASL_UNAVAIL:
case SASL_WEAKPASS:
break;
case SASL_BADAUTH:
case SASL_NOAUTHZ:
break;
case SASL_NOMEM:
rc = LDAP_NO_MEMORY;
break;
case SASL_NOUSER:
break;
case SASL_CONTINUE:
case SASL_FAIL:
case SASL_INTERACT:
default:
break;
}
return( rc );
}
int
{
char * host;
int saslrc;
return( LDAP_LOCAL_ERROR );
}
return( LDAP_LOCAL_ERROR );
}
return( LDAP_LOCAL_ERROR );
}
/* SASL is not properly initialized */
return( LDAP_LOCAL_ERROR );
}
}
return( LDAP_SUCCESS );
}
static void
{
}
}
static int
{
sasl_dispose( &ctx );
}
return( LDAP_SUCCESS );
}
static int
{
unsigned credlen;
return( LDAP_NOT_SUPPORTED );
}
/* shouldn't happen */
return( LDAP_LOCAL_ERROR );
}
if( rc < 0 ) {
}
}
/* should have a valid ld connection - now create sasl connection */
return( rc );
}
/* expect context to be initialized when connection is open */
return( LDAP_LOCAL_ERROR );
}
/* (re)set security properties */
do {
&prompts,
&credlen,
&mech );
if( saslrc == SASL_INTERACT &&
break;
}
} while ( saslrc == SASL_INTERACT );
}
do {
/* notify server of a sasl bind step */
}
/* and server provided us with data? */
ber_bvfree( scred );
}
return( rc );
}
/* we're done, no need to step */
/* but server provided us with data! */
ber_bvfree( scred );
return( LDAP_LOCAL_ERROR );
}
break;
}
/* perform the next step of the sasl bind */
do {
&prompts,
&credlen );
if( saslrc == SASL_INTERACT &&
!= LDAP_SUCCESS ) {
break;
}
} while ( saslrc == SASL_INTERACT );
ber_bvfree( scred );
}
} while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
if ( rc != LDAP_SUCCESS ) {
return( rc );
}
}
}
return( rc );
}
/*
* Get available SASL Mechanisms supported by the server
*/
static int
{
LDAPMessage *res, *e;
if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
return( LDAP_PARAM_ERROR );
}
if ( rc != LDAP_SUCCESS ) {
}
if ( e == NULL ) {
ldap_msgfree( res );
}
}
ldap_msgfree( res );
return( LDAP_NO_SUCH_ATTRIBUTE );
}
slen = 0;
}
ldap_msgfree( res );
return( LDAP_NO_MEMORY );
}
m = mech;
for(v = values; *v; v++) {
if (v != values) {
*m++ = ' ';
}
m += slen;
}
*m = '\0';
ldap_msgfree( res );
return( LDAP_SUCCESS );
}
#endif
const char *in,
{
int i;
char *inp;
unsigned sflags = 0;
sasl_ssf_t max_ssf = 0;
sasl_ssf_t min_ssf = 0;
unsigned maxbufsize = 0;
int got_sflags = 0;
int got_max_ssf = 0;
int got_min_ssf = 0;
int got_maxbufsize = 0;
return LDAP_PARAM_ERROR;
}
return LDAP_PARAM_ERROR;
}
NSLDAPI_FREE( inp );
return LDAP_PARAM_ERROR;
}
for( i=0; props[i]; i++ ) {
got_sflags++;
got_sflags++;
got_sflags++;
got_sflags++;
got_sflags++;
got_sflags++;
got_sflags++;
} else if( strncasecmp(props[i],
"minssf=", sizeof("minssf")) == 0 ) {
got_min_ssf++;
} else {
return LDAP_NOT_SUPPORTED;
}
} else if( strncasecmp(props[i],
"maxssf=", sizeof("maxssf")) == 0 ) {
got_max_ssf++;
} else {
return LDAP_NOT_SUPPORTED;
}
} else if( strncasecmp(props[i],
"maxbufsize=", sizeof("maxbufsize")) == 0 ) {
if( maxbufsize &&
(( maxbufsize < SASL_MIN_BUFF_SIZE )
|| (maxbufsize > SASL_MAX_BUFF_SIZE ))) {
return( LDAP_PARAM_ERROR );
}
} else {
return( LDAP_NOT_SUPPORTED );
}
} else {
return( LDAP_NOT_SUPPORTED );
}
}
if(got_sflags) {
}
if(got_min_ssf) {
}
if(got_max_ssf) {
}
if(got_maxbufsize) {
}
return( LDAP_SUCCESS );
}
/*
* SASL Authentication Interface: ldap_sasl_interactive_bind_s
*
* This routine takes a DN, SASL mech list, and a SASL callback
* and performs the necessary sequencing to complete a SASL bind
* to the LDAP connection ld. The user provided callback can
* use an optionally provided set of default values to complete
* any necessary interactions.
*
* Currently inpose the following restrictions:
* A mech list must be provided, only LDAP_SASL_INTERACTIVE
* mode is supported
*/
int
const char *saslMechanism,
{
char *smechs;
#endif
int rc;
if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
return( LDAP_PARAM_ERROR );
}
return( LDAP_PARAM_ERROR );
}
if( rc != LDAP_SUCCESS ) {
return( rc );
}
#else
return( LDAP_PARAM_ERROR );
#endif
}
/* initialize SASL library */
if ( nsldapi_sasl_init() < 0 ) {
return( LDAP_PARAM_ERROR );
}
return( rc );
}
#endif