#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 WIN32
# ifdef errno
# undef errno
# endif
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _SUN_SDK_
#include "plugin_common.h"
#include <wchar.h>
#endif
static int _sasl_seterror_usererr(int saslerr)
{
if (saslerr == SASL_NOUSER)
return SASL_BADAUTH;
return saslerr;
}
void sasl_seterror(sasl_conn_t *conn,
unsigned flags,
const char *fmt, ...)
{
size_t outlen=0;
int pos=0;
int formatlen;
int result;
sasl_log_t *log_cb;
void *log_ctx;
int ival;
char *cval;
va_list ap;
char **error_buf;
size_t *error_buf_len;
#ifdef _SUN_SDK_
_sasl_global_context_t *gctx;
#endif
#ifdef _INTEGRATED_SOLARIS_
sasl_getsimple_t *simple_cb;
void *simple_context;
const char *lang = NULL;
int ret;
const sasl_utils_t *utils;
int char_len;
char *utf8_buf;
const char *orig_fmt = fmt;
int is_client;
#endif
if(!conn) {
#ifndef SASL_OSX_CFMGLUE
if(!(flags & SASL_NOLOG)) {
result = _sasl_getcallback(NULL, SASL_CB_LOG, &log_cb, &log_ctx);
if (result == SASL_OK && ! log_cb)
result = SASL_FAIL;
if (result != SASL_OK)
return;
log_cb(log_ctx, SASL_LOG_FAIL,
"No sasl_conn_t passed to sasl_seterror");
}
#endif
return;
} else if(!fmt) return;
#ifdef _SUN_SDK_
gctx = conn->gctx;
#endif
#ifdef _INTEGRATED_SOLARIS_
if (conn->type == SASL_CONN_SERVER) {
utils = ((sasl_server_conn_t *)conn)->sparams->utils;
is_client = 0;
} else if (conn->type == SASL_CONN_CLIENT) {
utils = ((sasl_client_conn_t *)conn)->cparams->utils;
is_client = 1;
} else
utils = NULL;
if (utils != NULL) {
ret = utils->getcallback(conn, SASL_CB_LANGUAGE, &simple_cb,
&simple_context);
if (ret == SASL_OK && simple_cb)
(void) simple_cb(simple_context, SASL_CB_LANGUAGE, &lang, NULL);
if (use_locale(lang, is_client))
fmt = dgettext(TEXT_DOMAIN, fmt);
}
#endif
_sasl_get_errorbuf(conn, &error_buf, &error_buf_len);
formatlen = strlen(fmt);
va_start(ap, fmt);
while(pos<formatlen)
{
if (fmt[pos]!='%')
{
#ifdef _INTEGRATED_SOLARIS_
char_len = mbrlen(fmt + pos, formatlen - pos, NULL);
result = _buf_alloc(error_buf, error_buf_len, outlen + char_len);
if (result != SASL_OK)
return;
while (char_len-- > 0) {
(*error_buf)[outlen]=fmt[pos];
outlen++;
pos++;
}
#else
result = _buf_alloc(error_buf, error_buf_len, outlen+1);
if (result != SASL_OK)
return;
(*error_buf)[outlen]=fmt[pos];
outlen++;
pos++;
#endif
} else {
int done=0;
char frmt[10];
int frmtpos=1;
char tempbuf[21];
frmt[0]='%';
pos++;
while (done==0)
{
switch(fmt[pos])
{
case 's':
cval = va_arg(ap, char *);
result = _sasl_add_string(error_buf, error_buf_len,
&outlen, cval);
if (result != SASL_OK)
return;
done=1;
break;
case '%':
result = _buf_alloc(error_buf, error_buf_len, outlen+1);
if (result != SASL_OK)
return;
(*error_buf)[outlen]='%';
outlen++;
done=1;
break;
case 'm':
result = _sasl_add_string(error_buf, error_buf_len,
&outlen,
strerror(va_arg(ap, int)));
if (result != SASL_OK)
return;
done=1;
break;
case 'z':
#ifdef _INTEGRATED_SOLARIS_
result = _sasl_add_string(error_buf, error_buf_len, &outlen,
(char *)sasl_errstring(_sasl_seterror_usererr(
va_arg(ap, int)), lang, NULL));
#else
result = _sasl_add_string(error_buf, error_buf_len, &outlen,
(char *)sasl_errstring(_sasl_seterror_usererr(
va_arg(ap, int)),NULL,NULL));
#endif
if (result != SASL_OK)
return;
done=1;
break;
case 'c':
#ifndef _SUN_SDK_
frmt[frmtpos++]=fmt[pos];
frmt[frmtpos]=0;
#endif
tempbuf[0] = (char) va_arg(ap, int);
tempbuf[1]='\0';
result = _sasl_add_string(error_buf, error_buf_len,
&outlen, tempbuf);
if (result != SASL_OK)
return;
done=1;
break;
case 'd':
case 'i':
frmt[frmtpos++]=fmt[pos];
frmt[frmtpos]=0;
ival = va_arg(ap, int);
snprintf(tempbuf,20,frmt,ival);
result = _sasl_add_string(error_buf, error_buf_len,
&outlen, tempbuf);
if (result != SASL_OK)
return;
done=1;
break;
default:
frmt[frmtpos++]=fmt[pos];
frmt[frmtpos]=0;
#ifdef _SUN_SDK_
if (frmtpos > sizeof (frmt) - 2)
#else
if (frmtpos>9)
#endif
done=1;
}
pos++;
if (pos>formatlen)
done=1;
}
}
}
(*error_buf)[outlen]='\0';
va_end(ap);
#ifdef _INTEGRATED_SOLARIS_
if (orig_fmt != fmt) {
utf8_buf = local_to_utf(utils, *error_buf);
if (utf8_buf != NULL) {
outlen = strlen(utf8_buf);
result = SASL_OK;
if (outlen >= *error_buf_len)
result = _buf_alloc(error_buf, error_buf_len, outlen+1);
if (result != SASL_OK) {
utils->free(utf8_buf);
return;
}
strcpy(*error_buf, utf8_buf);
utils->free(utf8_buf);
}
}
#endif
#ifndef SASL_OSX_CFMGLUE
if(!(flags & SASL_NOLOG)) {
result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx);
if (result == SASL_OK && ! log_cb)
result = SASL_FAIL;
if (result != SASL_OK)
return;
result = log_cb(log_ctx, SASL_LOG_FAIL, conn->error_buf);
}
#endif
}