common.c revision cb6207858a9fcc2feaee22e626912fba281ac969
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* common.c - Functions that are common to server and clinet
* Rob Siemborski
* Tim Martin
* $Id: common.c,v 1.92 2003/04/16 19:36:00 rjs3 Exp $
*/
/*
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#ifdef HAVE_SYSLOG
#include <syslog.h>
#endif
#include <stdarg.h>
#include <ctype.h>
#include <sasl.h>
#include <saslutil.h>
#include <saslplug.h>
#include "saslint.h"
#ifdef _SUN_SDK_
#include "md5_private.h"
#include "hmac-md5.h"
#include "plugin_common.h"
#endif
#ifdef WIN32
/* need to handle the fact that errno has been defined as a function
in a dll, not an extern int */
# ifdef errno
# endif /* errno */
#endif /* WIN32 */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _SUN_SDK_
#ifdef _INTEGRATED_SOLARIS_
#endif /* _INTEGRATED_SOLARIS_ */
#else
/* It turns out to be conveinent to have a shared sasl_utils_t */
/* Should be a null-terminated array that lists the available mechanisms */
static char **global_mech_list = NULL;
void *free_mutex = NULL;
int (*_sasl_client_cleanup_hook)(void) = NULL;
int (*_sasl_server_cleanup_hook)(void) = NULL;
(sasl_malloc_t *) &malloc,
(sasl_calloc_t *) &calloc,
(sasl_realloc_t *) &realloc,
(sasl_free_t *) &free
};
#endif /* _SUN_SDK_ */
#ifdef USE_PTHREADS
static void *sasl_mutex_alloc(void)
{
}
}
return (mutex);
}
static int sasl_mutex_lock(void *mutex)
{
int ret = SASL_BADPARAM;
return ret;
}
static int sasl_mutex_unlock(void *mutex)
{
int ret = SASL_BADPARAM;
return ret;
}
{
}
}
#else
/* Intenal mutex functions do as little as possible (no thread protection) */
static void *sasl_mutex_alloc(void)
{
return (void *)0x1;
}
{
return SASL_OK;
}
{
return SASL_OK;
}
{
return;
}
#endif /* USE_PTHREADS */
#ifndef _SUN_SDK_
};
#endif /* !_SUN_SDK_ */
sasl_mutex_unlock_t *u, sasl_mutex_free_t *d)
{
#ifdef _SUN_SDK_
#else
#endif
}
/* copy a string to malloced memory */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
{
if (! *out) return SASL_NOMEM;
return SASL_OK;
}
/* adds a string to the buffer; reallocing if need be */
#ifdef _SUN_SDK_
const char *add)
#else
#endif /* _SUN_SDK_ */
{
return SASL_NOMEM;
return SASL_OK;
}
/* return the version of the cyrus sasl library as compiled,
* using 32 bits: high byte is major version, second byte is minor version,
* low 16 bits are step # */
{
#ifdef _SUN_SDK_
const char *implementation_string = "Sun SASL";
#else
const char *implementation_string = "Cyrus SASL";
#endif /* _SUN_SDK_ */
(SASL_VERSION_MINOR << 16) |
}
/* security-encode a regular string. Mostly a wrapper for sasl_encodev */
/* output is only valid until next call to sasl_encode or sasl_encodev */
unsigned inputlen,
{
int result;
if(!conn) return SASL_BADPARAM;
/* maxoutbuf checking is done in sasl_encodev */
/* Note: We are casting a const pointer here, but it's okay
* because we believe people downstream of us are well-behaved, and the
* alternative is an absolute mess, performance-wise. */
}
/* security-encode an iovec */
/* output is only valid until next call to sasl_encode or sasl_encodev */
{
#ifdef _SUN_SDK_
#else
int result;
#endif /* _SUN_SDK_ */
unsigned i;
size_t total_size = 0;
/* EXPORT DELETE START */
if (!conn) return SASL_BADPARAM;
#ifdef _SUN_SDK_
"called sasl_encode[v] with application that does not support security layers");
#else
sasl_seterror(conn, 0,
"called sasl_encode[v] with application that does not support security layers");
#endif /* _SUN_SDK_ */
return SASL_TOOWEAK;
}
/* This might be better to check on a per-plugin basis, but I think
* it's cleaner and more effective here. It also encourages plugins
* to be honest about what they accept */
for(i=0; i<numiov;i++) {
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
}
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
/* CRYPT DELETE START */
#ifdef _INTEGRATED_SOLARIS_
#endif /* _INTEGRATED_SOLARIS_ */
/* CRYPT DELETE END */
} else {
}
/* EXPORT DELETE END */
}
/* output is only valid until next call to sasl_decode */
{
int result;
/* EXPORT DELETE START */
#ifdef _SUN_SDK_
const _sasl_global_context_t *gctx;
#endif /* _SUN_SDK_ */
if(!conn) return SASL_BADPARAM;
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
"called sasl_decode with application that does not support security layers");
#else
sasl_seterror(conn, 0,
"called sasl_decode with application that does not support security layers");
#endif /* _SUN_SDK_ */
}
{
/* Since we know how long the output is maximally, we can
* just allocate it to begin with, and never need another
* allocation! */
/* However, if they pass us more than they actually can take,
* we cannot help them... */
#ifdef _SUN_SDK_
"input too large for default sasl_decode");
#else
sasl_seterror(conn, 0,
"input too large for default sasl_decode");
#endif /* _SUN_SDK_ */
}
if(!conn->decode_buf)
if(!conn->decode_buf)
return SASL_OK;
/* CRYPT DELETE START */
#ifdef _INTEGRATED_SOLARIS_
#endif /* _INTEGRATED_SOLARIS_ */
/* CRYPT DELETE END */
} else {
/* NULL an empty buffer (for misbehaved applications) */
}
/* EXPORT DELETE END */
#ifdef _SUN_SDK_
return SASL_FAIL;
#else
#endif /* _SUN_SDK_ */
}
void
sasl_calloc_t *c,
sasl_realloc_t *r,
sasl_free_t *f)
{
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
}
void sasl_done(void)
{
#ifdef _SUN_SDK_
#else
}
}
return;
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
free_mutex = NULL;
#endif /* _SUN_SDK_ */
}
/* fills in the base sasl_conn_t info */
const char *service,
unsigned int flags,
enum Sasl_conn_type type,
const char *serverFQDN,
const char *iplocalport,
const char *ipremoteport,
const sasl_callback_t *callbacks,
const sasl_global_callbacks_t *global_callbacks) {
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
#ifndef _SUN_SDK_
#endif /* !_SUN_SDK_ */
/* Start this buffer out as an empty string */
if(serverFQDN) {
/* We can fake it because we *are* the server */
char name[MAXHOSTNAMELEN];
} else {
}
#ifdef _SUN_SDK_
return (SASL_OK);
#else
#endif /* _SUN_SDK_ */
}
#ifdef _SUN_SDK_
int server)
{
int result;
if(!sasl_global_utils) {
}
if (server) {
if(!sasl_global_utils) {
}
}
/* Init the canon_user plugin */
if (!gctx->free_mutex)
return SASL_OK;
}
#else
{
int result;
/* Setup the global utilities */
if(!sasl_global_utils) {
}
/* Init the canon_user plugin */
if (!free_mutex)
if (!free_mutex) return SASL_FAIL;
return SASL_OK;
}
#endif /* _SUN_SDK_ */
/* dispose connection state, sets it to NULL
* checks for pointer to NULL
*/
{
int result;
#ifdef _SUN_SDK_
void *free_mutex;
#endif /* _SUN_SDK_ */
if (! pconn) return;
if (! *pconn) return;
/* serialize disposes. this is necessary because we can't
dispose of conn->mutex if someone else is locked on it */
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
/* *pconn might have become NULL by now */
#ifdef _SUN_SDK_
if (! (*pconn)) {
return;
}
#else
if (! (*pconn)) return;
#endif /* _SUN_SDK_ */
}
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
if (conn->serverFQDN)
if(conn->encode_buf) {
}
if(conn->errdetail_buf)
if(conn->decode_buf)
if(conn->mechlist_buf)
/* oparams sub-members should be freed by the plugin, in so much
* as they were allocated by the plugin */
}
/* get property from SASL connection state
* propnum -- property number
* pvalue -- pointer to value
* returns:
* SASL_OK -- no error
* SASL_NOTDONE -- property not available yet
* SASL_BADPARAM -- bad property number
*/
{
void *context;
if (! conn) return SASL_BADPARAM;
switch(propnum)
{
case SASL_SSF:
/* EXPORT DELETE START */
/* CRYPT DELETE START */
#ifdef _INTEGRATED_SOLARIS_
#endif /* _INTEGRATED_SOLARIS_ */
/* CRYPT DELETE END */
/* EXPORT DELETE END */
break;
case SASL_MAXOUTBUF:
break;
case SASL_GETOPTCTX:
break;
case SASL_CALLBACK:
break;
case SASL_IPLOCALPORT:
if(conn->got_ip_local)
else {
}
break;
case SASL_IPREMOTEPORT:
if(conn->got_ip_remote)
else {
}
break;
case SASL_USERNAME:
else
break;
case SASL_AUTHUSER:
else
break;
case SASL_SERVERFQDN:
break;
case SASL_DEFUSERREALM:
else
break;
case SASL_SERVICE:
break;
case SASL_AUTHSOURCE: /* name of plugin (not name of mech) */
break;
}
*((const char **)pvalue) =
break;
}
*((const char **)pvalue) =
} else {
}
break;
case SASL_MECHNAME: /* name of mech */
break;
}
*((const char **)pvalue) =
break;
}
*((const char **)pvalue) =
} else {
}
break;
case SASL_PLUGERR:
break;
case SASL_SSF_EXTERNAL:
break;
case SASL_AUTH_EXTERNAL:
break;
case SASL_SEC_PROPS:
break;
default:
}
if(result == SASL_BADPARAM) {
} else if(result == SASL_NOTDONE) {
#ifdef _SUN_SDK_
"Information that was requested is not yet available.");
#else
"Information that was requested is not yet available.");
#endif /* _SUN_SDK_ */
} else
#ifdef _SUN_SDK_
return SASL_OK;
#endif /* _SUN_SDK_ */
}
/* set property in SASL connection state
* returns:
* SASL_OK -- value set
* SASL_BADPARAM -- invalid property or value
*/
{
char *str;
#ifdef _SUN_SDK_
const _sasl_global_context_t *gctx;
#endif /* _SUN_SDK_ */
/* make sure the sasl context is valid */
if (!conn)
return SASL_BADPARAM;
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
switch(propnum)
{
case SASL_SSF_EXTERNAL:
} else {
}
break;
case SASL_AUTH_EXTERNAL:
} else {
}
break;
case SASL_DEFUSERREALM:
#ifdef _SUN_SDK_
"Tried to set realm on non-server connection");
#else
#endif /* _SUN_SDK_ */
break;
}
} else {
}
break;
case SASL_SEC_PROPS:
{
#ifdef _SUN_SDK_
"Attempt to disable security layers (maxoutbuf == 0) with min_ssf > 0");
#else
sasl_seterror(conn, 0,
"Attempt to disable security layers (maxoutbuf == 0) with min_ssf > 0");
#endif /* _SUN_SDK_ */
}
} else {
}
break;
}
case SASL_IPREMOTEPORT:
{
const char *ipremoteport = (const char *)value;
if(!value) {
conn->got_ip_remote = 0;
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
!= SASL_OK) {
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
} else {
}
if(conn->got_ip_remote) {
= conn->ipremoteport;
= conn->ipremoteport;
}
} else {
= NULL;
= NULL;
}
}
break;
}
case SASL_IPLOCALPORT:
{
const char *iplocalport = (const char *)value;
if(!value) {
conn->got_ip_local = 0;
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
!= SASL_OK) {
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
} else {
}
if(conn->got_ip_local) {
= conn->iplocalport;
= conn->iplocalport;
}
} else {
= NULL;
= NULL;
}
}
break;
}
default:
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
}
}
/* this is apparently no longer a user function */
static int sasl_usererr(int saslerr)
{
/* Hide the difference in a username failure and a password failure */
if (saslerr == SASL_NOUSER)
return SASL_BADAUTH;
/* otherwise return the error given; no transform necessary */
return saslerr;
}
#ifdef _INTEGRATED_SOLARIS_
static void free_err_tsd(void *key)
{
}
#endif /* _INTEGRATED_SOLARIS_ */
const char *sasl_errstring(int saslerr,
#ifdef _SUN_SDK_
const char *langlist,
#else
#endif /* _SUN_SDK_ */
const char **outlang)
{
#ifdef _INTEGRATED_SOLARIS_
const char *s;
const char *s_locale;
char *s_utf8;
void *tsd;
#else
#endif /* _INTEGRATED_SOLARIS_ */
#ifdef _INTEGRATED_SOLARIS_
switch(saslerr)
{
break;
break;
break;
break;
break;
break;
break;
break;
break;
break;
break;
break;
/* -- client only codes -- */
break;
break;
break;
/* -- server only codes -- */
break;
break;
break;
break;
case SASL_TRANS: s = gettext("One time use of a plaintext password will enable requested mechanism for user");
break;
break;
break;
break;
break;
break;
break;
break;
break;
break;
break;
default: s = gettext("undefined error!");
break;
}
if (use_locale(langlist, 0))
else
s_locale = s;
if (s == s_locale)
return s;
return s;
return s;
}
return s_utf8;
#else
switch(saslerr)
{
case SASL_CONTINUE: return "another step is needed in authentication";
case SASL_OK: return "successful result";
case SASL_FAIL: return "generic failure";
case SASL_NOMEM: return "no memory available";
case SASL_BUFOVER: return "overflowed buffer";
case SASL_NOMECH: return "no mechanism available";
case SASL_BADPROT: return "bad protocol / cancel";
case SASL_NOTDONE: return "can't request info until later in exchange";
case SASL_BADPARAM: return "invalid parameter supplied";
case SASL_TRYAGAIN: return "transient failure (e.g., weak key)";
case SASL_BADMAC: return "integrity check failed";
case SASL_NOTINIT: return "SASL library not initialized";
/* -- client only codes -- */
case SASL_INTERACT: return "needs user interaction";
case SASL_BADSERV: return "server failed mutual authentication step";
case SASL_WRONGMECH: return "mechanism doesn't support requested feature";
/* -- server only codes -- */
case SASL_BADAUTH: return "authentication failure";
case SASL_NOAUTHZ: return "authorization failure";
case SASL_TOOWEAK: return "mechanism too weak for this user";
case SASL_ENCRYPT: return "encryption needed to use mechanism";
case SASL_TRANS: return "One time use of a plaintext password will enable requested mechanism for user";
case SASL_EXPIRED: return "passphrase expired, has to be reset";
case SASL_DISABLED: return "account disabled";
case SASL_NOUSER: return "user not found";
case SASL_BADVERS: return "version mismatch with plug-in";
case SASL_UNAVAIL: return "remote authentication server unavailable";
case SASL_NOVERIFY: return "user exists, but no verifier for user";
case SASL_PWLOCK: return "passphrase locked";
case SASL_NOCHANGE: return "requested change was not needed";
case SASL_WEAKPASS: return "passphrase is too weak for security policy";
case SASL_NOUSERPASS: return "user supplied passwords are not permitted";
default: return "undefined error!";
}
#endif /* _INTEGRATED_SOLARIS_ */
}
/* Return the sanitized error detail about the last error that occured for
* a connection */
{
unsigned need_len;
const char *errstr;
char leader[128];
#ifdef _SUN_SDK_
int ret;
const _sasl_global_context_t *gctx;
if(!conn) return "invalid parameter supplied";
#else
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
return "no memory available";
#else
#endif /* _SUN_SDK_ */
return conn->errdetail_buf;
}
/* EXPORT DELETE START */
/* CRYPT DELETE START */
#ifdef _INTEGRATED_SOLARIS_
typedef struct reg_list {
void *mech;
} reg_list_t;
int _is_sun_reg(void *mech)
{
reg_list_t *r, *prev;
int is_reg = 0;
prev = r;
continue;
}
is_reg = 1;
if (r == reg_list_base) {
} else {
}
free(r);
break;
}
return (is_reg);
}
static void
_register_plugin(void *arg)
{
if (r != NULL) {
r->next = reg_list_base;
reg_list_base = r;
}
}
#endif /* _INTEGRATED_SOLARIS_ */
/* CRYPT DELETE END */
/* EXPORT DELETE END */
/* Note that this needs the global callbacks, so if you don't give getcallbacks
* a sasl_conn_t, you're going to need to pass it yourself (or else we couldn't
* have client and server at the same time */
static int _sasl_global_getopt(void *context,
const char *plugin_name,
const char *option,
const char ** result,
unsigned *len)
{
const sasl_global_callbacks_t * global_callbacks;
const sasl_callback_t *callback;
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
/* EXPORT DELETE START */
/* CRYPT DELETE START */
#ifdef _INTEGRATED_SOLARIS_
*result = (const char *)_register_plugin;
*len = 0;
return (SASL_OK);
}
#endif /* _INTEGRATED_SOLARIS_ */
/* CRYPT DELETE END */
/* EXPORT DELETE END */
if (global_callbacks)
else
gctx = _sasl_gbl_ctx();
#endif /* _SUN_SDK_ */
callback++) {
len)
== SASL_OK)
return SASL_OK;
}
}
}
/* look it up in our configuration file */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
return SASL_OK;
}
return SASL_FAIL;
}
static int
_sasl_conn_getopt(void *context,
const char *plugin_name,
const char *option,
const char ** result,
unsigned *len)
{
sasl_conn_t * conn;
const sasl_callback_t *callback;
if (! context)
return SASL_BADPARAM;
callback++)
len)
== SASL_OK))
return SASL_OK;
/* If we made it here, we didn't find an appropriate callback
* in the connection's callback list, or the callback we did
* find didn't return SASL_OK. So we attempt to use the
* global callback for this connection... */
len);
}
#ifdef HAVE_SYSLOG
/* this is the default logging */
int priority,
const char *message)
{
int syslog_priority;
/* set syslog priority */
switch(priority) {
case SASL_LOG_NONE:
return SASL_OK;
break;
case SASL_LOG_ERR:
break;
case SASL_LOG_WARN:
break;
case SASL_LOG_NOTE:
case SASL_LOG_FAIL:
break;
case SASL_LOG_PASS:
case SASL_LOG_TRACE:
case SASL_LOG_DEBUG:
default:
break;
}
/* do the syslog call. do not need to call openlog */
return SASL_OK;
}
#endif /* HAVE_SYSLOG */
static int
_sasl_getsimple(void *context,
int id,
const char ** result,
{
const char *userid;
#ifndef _SUN_SDK_
#endif /* _SUN_SDK_ */
#ifndef _SUN_SDK_
#endif /* _SUN_SDK_ */
switch(id) {
case SASL_CB_AUTHNAME:
#ifdef _INTEGRATED_SOLARIS_
return SASL_OK;
}
#else
return SASL_OK;
}
return SASL_OK;
}
#endif /* _INTEGRATED_SOLARIS_ */
#ifdef WIN32
/* for win32, try using the GetUserName standard call */
{
DWORD i;
static char sender[128];
i = sizeof(sender);
if ( rval) { /* got a userid */
return SASL_OK;
}
}
#endif /* WIN32 */
return SASL_FAIL;
default:
return SASL_BADPARAM;
}
}
static int
{
/* always say ok */
return SASL_OK;
}
static int
const char *requested_user, unsigned rlen,
const char *auth_identity, unsigned alen,
{
if (!conn)
return SASL_BADPARAM;
return SASL_OK;
#ifdef _INTEGRATED_SOLARIS_
sasl_seterror(conn, 0,
gettext("Requested identity not authenticated identity"));
#else
sasl_seterror(conn, 0,
"Requested identity not authenticated identity");
#endif /* _INTEGRATED_SOLARIS_ */
}
return SASL_OK;
}
unsigned long callbackid,
int (**pproc)(),
void **pcontext)
{
const sasl_callback_t *callback;
/* Some callbacks are always provided by the library */
switch (callbackid) {
case SASL_CB_LIST_END:
/* Nothing ever gets to provide this */
#ifdef _SUN_SDK_
break;
#endif /* _SUN_SDK_ */
case SASL_CB_GETOPT:
if (conn) {
*pproc = &_sasl_conn_getopt;
} else {
*pproc = &_sasl_global_getopt;
}
return SASL_OK;
}
/* If it's not always provided by the library, see if there's
* a version provided by the application for this connection... */
callback++) {
return SASL_OK;
} else {
return SASL_INTERACT;
}
}
}
}
/* And, if not for this connection, see if there's one
* for all {server,client} connections... */
callback++) {
return SASL_OK;
} else {
return SASL_INTERACT;
}
}
}
}
/* Otherwise, see if the library provides a default callback. */
switch (callbackid) {
#ifdef HAVE_SYSLOG
case SASL_CB_LOG:
*pproc = (int (*)()) &_sasl_syslog;
return SASL_OK;
#endif /* HAVE_SYSLOG */
case SASL_CB_GETPATH:
*pproc = (int (*)()) &_sasl_getpath;
return SASL_OK;
case SASL_CB_AUTHNAME:
*pproc = (int (*)()) &_sasl_getsimple;
return SASL_OK;
case SASL_CB_VERIFYFILE:
*pproc = & _sasl_verifyfile;
return SASL_OK;
case SASL_CB_PROXY_POLICY:
*pproc = (int (*)()) &_sasl_proxy_policy;
return SASL_OK;
}
/* Unable to find a callback... */
#ifdef _SUN_SDK_
if (callbackid != SASL_CB_LANGUAGE)
#else
#endif /* _SUN_SDK_ */
}
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
/*
* This function is typically called from a plugin.
* It creates a string from the formatting and varargs given
* and calls the logging callback (syslog by default)
*
* %m will parse the value in the next argument as an errno string
* %z will parse the next argument as a SASL error code.
*/
void
int level,
const char *fmt,
...)
#ifdef _SUN_SDK_
{
void *log_ctx;
int result;
/* See if we have a logging callback... */
return;
}
void
const sasl_callback_t *callbacks,
int level,
const char *fmt,
...)
{
int result;
if (callbacks)
break;
}
++callbacks;
}
return;
}
gctx = _sasl_gbl_ctx();
}
static void
void *log_ctx,
int level,
const char *fmt,
#endif /* _SUN_SDK_ */
{
int result;
#ifndef _SUN_SDK_
void *log_ctx;
#endif /* !_SUN_SDK_ */
int ival;
char *cval;
#ifndef _SUN_SDK_
#endif /* !_SUN_SDK_ */
if(!out) return;
#ifndef _SUN_SDK_
/* See if we have a logging callback... */
#endif /* !_SUN_SDK_ */
{
{
outlen++;
pos++;
} else { /* formating thing */
int done=0;
char frmt[10];
int frmtpos=1;
char tempbuf[21];
frmt[0]='%';
pos++;
while (done==0)
{
{
case 's': /* need to handle this */
goto done;
done=1;
break;
case '%': /* double % output the '%' character */
goto done;
outlen++;
done=1;
break;
case 'm': /* insert the errno string */
goto done;
done=1;
break;
case 'z': /* insert the sasl error string */
goto done;
done=1;
break;
case 'c':
#ifndef _SUN_SDK_
#endif /* !_SUN_SDK_ */
/* now add the character */
goto done;
done=1;
break;
case 'd':
case 'i':
/* now add the string */
goto done;
done=1;
break;
default:
#ifdef _SUN_SDK_
#else
if (frmtpos>9)
#endif /* _SUN_SDK_ */
done=1;
}
pos++;
done=1;
}
}
}
/* put 0 at end */
/* send log message */
done:
}
/* Allocate and Init a sasl_utils_t structure */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
{
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
/* set util functions - need to do rest*/
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
return NULL;
if (conn) {
} else {
}
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
#ifndef macintosh
/* Aux Property Utilities */
#endif
/* Spares */
return utils;
}
int
{
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
if(!utils) return SASL_BADPARAM;
/* I wish we could avoid this cast, it's pretty gratuitous but it
* does make life easier to have it const everywhere else. */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
return SASL_OK;
}
{
if (! conn) {
#ifdef _SUN_SDK_
return 1;
return 1;
#else
return 1;
return 1;
#endif /* _SUN_SDK_ */
return 0;
}
return 0;
}
const sasl_callback_t *
{
static const sasl_callback_t default_getpath_cb = {
};
if (callbacks)
{
{
return callbacks;
} else {
++callbacks;
}
}
return &default_getpath_cb;
}
#ifdef _SUN_SDK_
extern const sasl_callback_t *
{
static const sasl_callback_t default_getconf_cb = {
};
if (callbacks)
{
{
return callbacks;
} else {
++callbacks;
}
}
return &default_getconf_cb;
}
#endif /* _SUN_SDK_ */
const sasl_callback_t *
{
static const sasl_callback_t default_verifyfile_cb = {
};
if (callbacks)
{
{
return callbacks;
} else {
++callbacks;
}
}
return &default_verifyfile_cb;
}
/* Basically a conditional call to realloc(), if we need more */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
{
if(!(*rwbuf)) {
*curlen = 0;
return SASL_NOMEM;
}
needed *= 2;
*curlen = 0;
return SASL_NOMEM;
}
}
return SASL_OK;
}
/* for the mac os x cfm glue: this lets the calling function
get pointers to the error buffer without having to touch the sasl_conn_t struct */
{
}
/* convert an iovec to a single buffer */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
{
unsigned i;
int ret;
char *pos;
if(!(*output)) {
if(!*output) return SASL_NOMEM;
}
for(i=0; i<numiov; i++)
for(i=0; i<numiov; i++) {
}
return SASL_OK;
}
/* This code might be useful in the future, but it isn't now, so.... */
#if 0
return SASL_BUFOVER;
return SASL_OK;
}
#endif
#ifdef _SUN_SDK_
/* An ipv6 address will contain at least two colons */
static int can_be_ipv6(const char *addr)
{
const char *p;
return (0);
return (p != NULL);
}
#endif /* _SUN_SDK_ */
int _sasl_ipfromstring(const char *addr,
{
int i, j;
char hbuf[NI_MAXHOST];
#ifdef _SUN_SDK_
int addr_only = 1;
#endif /* _SUN_SDK_ */
/* A NULL out pointer just implies we don't do a copy, just verify it */
if(!addr) return SASL_BADPARAM;
#ifdef _SUN_SDK_
/* This an rfc 2732 ipv6 address */
return SASL_BADPARAM;
hbuf[i++] = *p;
if (i >= NI_MAXHOST)
return SASL_BADPARAM;
}
if (p == NULL)
p = end + 1;
else
p = p + 1;
} else if (can_be_ipv6(addr) != 0) {
/* Parse the address */
if (++i >= NI_MAXHOST)
return SASL_BADPARAM;
}
if (addr[i] == ';')
p = &addr[i+1];
else
p = &addr[i];
} else {
addr_only = 0;
if (++i >= NI_MAXHOST)
return SASL_BADPARAM;
}
p = &addr[i+1];
else
p = &addr[i];
}
hbuf[i] = '\0';
for (j = 0; p[j] != '\0'; j++)
if (!isdigit((int)(p[j])))
return SASL_BADPARAM;
if (atoi(p) == 0)
p = NULL;
#else
/* Parse the address */
if (i >= NI_MAXHOST)
return SASL_BADPARAM;
}
hbuf[i] = '\0';
if (addr[i] == ';')
i++;
/* XXX: Do we need this check? */
for (j = i; addr[j] != '\0'; j++)
return SASL_BADPARAM;
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
return SASL_BADPARAM;
if (out) {
return SASL_BUFOVER;
}
}
return SASL_OK;
}
#ifdef _SUN_SDK_
#else
int _sasl_build_mechlist(void)
#endif /* _SUN_SDK_ */
{
int count = 0;
#ifdef _SUN_SDK_
char **global_mech_list;
#else
clist = _sasl_client_mechs();
slist = _sasl_server_mechs();
#endif /* _SUN_SDK_ */
if(!clist) {
} else {
int flag;
/* append slist to clist, and set olist to clist */
flag = 0;
if(!strcmp(q->d, p->d)) {
/* They match, set the flag */
flag = 1;
break;
}
}
if(!flag) {
*last = p;
} else {
sasl_FREE(p);
}
}
}
if(!olist) {
#ifdef _SUN_SDK_
#else
printf ("no olist");
#endif /* _SUN_SDK_ */
return SASL_FAIL;
}
if(global_mech_list) {
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
}
if(!global_mech_list) return SASL_NOMEM;
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
count = 0;
global_mech_list[count++] = (char *) p->d;
sasl_FREE(p);
}
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
return SASL_OK;
}
const char ** sasl_global_listmech(void)
{
#ifdef _SUN_SDK_
return (const char **)gctx->global_mech_list;
#else
return (const char **)global_mech_list;
#endif /* _SUN_SDK_ */
}
const char *user,
const char *prefix,
const char *sep,
const char *suffix,
const char **result,
unsigned *plen,
int *pcount)
{
if(!conn) {
return SASL_BADPARAM;
}
}
#ifdef _SUN_SDK_
/*
* Creates a context so that libraries may use libsasl independently
* of applications using libsasl.
* Returns NULL on failure.
*
* sasl_free_context frees the context
* To use libsasl independently of the default context, use
* _sasl_server_init() instead of sasl_server_init()
* _sasl_server_new() instead of sasl_server_new()
* _sasl_client_init() instead of sasl_client_init()
* _sasl_client_new() instead of sasl_client_new()
* _sasl_client_add_plugin() instead of sasl_client_add_plugin()
* _sasl_server_add_plugin() instead of sasl_server_add_plugin()
* _sasl_canonuser_add_plugin() instead of sasl_canonuser_add_plugin()
* _sasl_auxprop_add_plugin() instead of sasl_auxprop_add_plugin()
*/
void *sasl_create_context(void)
{
gctx = (_sasl_global_context_t *)
sasl_sun_ALLOC(sizeof(_sasl_global_context_t));
}
return gctx;
}
/* Frees the context created by sasl_create_context() */
void sasl_free_context(void *context)
{
}
}
/* Used by both sasl_done() and sasl_free_context() to free context */
{
return;
if (gctx->sasl_server_cleanup_hook &&
}
if (gctx->sasl_client_cleanup_hook &&
}
return;
}
{
static _sasl_global_context_t gbl_ctx = {
0, /* sasl_server_active */
NULL, /* mechlist */
NULL, /* splug_path_info */
NULL, /* sasl_server_cleanup_hook */
NULL, /* sasl_server_idle_hook */
NULL, /* cmechlist */
NULL, /* cplug_path_info */
0, /* sasl_client_active */
NULL, /* sasl_client_cleanup_hook */
NULL, /* sasl_client_idle_hook */
NULL, /* sasl_server_global_utils */
NULL, /* sasl_client_global_utils */
NULL, /* configlist */
0, /* nconfiglist */
NULL, /* config_path */
0, /* config_last_read */
NULL, /* auxprop_head */
NULL, /* canonuser_head */
NULL, /* global_mech_list */
NULL, /* free_mutex */
/* sasl_allocation_utils */
&sasl_mutex_free}, /* sasl_mutex_utils */
NULL /* lib_list_head */
};
return (&gbl_ctx);
}
static int
{
if (! conf)
return SASL_BADPARAM;
*conf = SASL_CONFDIR;
return SASL_OK;
}
/* EXPORT DELETE START */
/* CRYPT DELETE START */
#ifdef _INTEGRATED_SOLARIS_
int
sasl_fini(void)
{
while (reg_list_base != NULL) {
}
return (0);
}
#endif /* _INTEGRATED_SOLARIS_ */
/* CRYPT DELETE END */
/* EXPORT DELETE END */
#endif /* _SUN_SDK_ */
#ifndef WIN32
static int
const char **path)
{
if (! path)
return SASL_BADPARAM;
#ifdef _SUN_SDK_
/* SASL_PATH is not allowed for SUN SDK */
#else
if (! *path)
#endif /* _SUN_SDK_ */
return SASL_OK;
}
#else
/* Return NULL on failure */
static int
{
/* Open registry entry, and find all registered SASL libraries.
*
* Registry location:
*
* SOFTWARE\\Carnegie Mellon\\Project Cyrus\\SASL Library
*
* Key - value:
*
* "SearchPath" - value: PATH like (';' delimited) list
* of directories where to search for plugins
* The list may contain references to environment
* variables (e.g. %PATH%).
*
*/
char * return_value; /* function return value */
char * tmp;
/* Initialization */
return_value = NULL;
/* Open the registry */
0,
&hKey);
if (ret != ERROR_SUCCESS) {
/* no registry entry */
return SASL_OK;
}
/* figure out value type and required buffer size */
/* the size will include space for terminating NUL if required */
NULL, /* reserved */
NULL,
&cbData);
/* Only accept string related types */
if (ValueType != REG_EXPAND_SZ &&
ValueType != REG_MULTI_SZ &&
return_value = NULL;
goto CLEANUP;
}
/* Any high water mark? */
return_value = NULL;
goto CLEANUP;
};
NULL, /* reserved */
&cbData);
switch (ValueType) {
case REG_EXPAND_SZ:
/* : A random starting guess */
if (ExpandedValueData == NULL) {
return_value = NULL;
goto CLEANUP;
};
if (cbExpandedData == 0) {
/* : GetLastError() contains the reason for failure */
return_value = NULL;
goto CLEANUP;
}
/* : Must retry expansion with the bigger buffer */
/* : Memory leak here if can't realloc */
if (ExpandedValueData == NULL) {
return_value = NULL;
goto CLEANUP;
};
/* : This should not happen */
if (cbExpandedData == 0) {
/* : GetLastError() contains the reason for failure */
return_value = NULL;
goto CLEANUP;
}
}
/* : This is to prevent automatical freeing of this block on cleanup */
break;
case REG_MULTI_SZ:
/* : We shouldn't overflow here, as the buffer is guarantied
: to contain at least two consequent NULs */
while (1) {
if (tmp[0] == '\0') {
/* : Stop the process if we found the end of the string (two consequent NULs) */
break;
}
/* : Replace delimiting NUL with our delimiter characted */
tmp[0] = PATHS_DELIMITER;
}
}
break;
case REG_SZ:
/* Do nothing, it is good as is */
break;
default:
return_value = NULL;
goto CLEANUP;
}
if (return_value == NULL) {
}
*path = return_value;
#ifdef _SUN_SDK_
/* SASL_PATH is not allowed for SUN SDK */
if (! *path)
#endif /* _SUN_SDK_ */
return SASL_OK;
}
#endif