123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- /* seterror.c - sasl_seterror split out because glue libraries
- * can't pass varargs lists
- * Rob Siemborski
- * Tim Martin
- * split from common.c by Rolf Braun
- */
- /*
- * Copyright (c) 1998-2016 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
- * the documentation and/or other materials provided with the
- * 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
- * Carnegie Mellon University
- * Center for Technology Transfer and Enterprise Creation
- * 4615 Forbes Avenue
- * Suite 302
- * Pittsburgh, PA 15213
- * (412) 268-7393, fax: (412) 268-7395
- * innovation@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 WIN32
- /* need to handle the fact that errno has been defined as a function
- in a dll, not an extern int */
- # ifdef errno
- # undef errno
- # endif /* errno */
- #endif /* WIN32 */
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- /* this is apparently no longer a user function */
- static int _sasl_seterror_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;
- }
- /* set the error string which will be returned by sasl_errdetail() using
- * syslog()-style formatting (e.g. printf-style with %m as the string form
- * of an errno error)
- *
- * primarily for use by server callbacks such as the sasl_authorize_t
- * callback and internally to plug-ins
- *
- * This will also trigger a call to the SASL logging callback (if any)
- * with a level of SASL_LOG_FAIL unless the SASL_NOLOG flag is set.
- *
- * Messages should be sensitive to the current language setting. If there
- * is no SASL_CB_LANGUAGE callback messages MUST be US-ASCII otherwise UTF-8
- * is used and use of RFC 2482 for mixed-language text is encouraged.
- *
- * if conn is NULL, function does nothing
- */
- void sasl_seterror(sasl_conn_t *conn,
- unsigned flags,
- const char *fmt, ...)
- {
- size_t outlen=0; /* current length of output buffer */
- size_t pos = 0; /* current position in format string */
- size_t formatlen;
- int result;
- sasl_log_t *log_cb = NULL;
- void *log_ctx;
- int ival;
- char *cval;
- va_list ap; /* varargs thing */
- char **error_buf;
- size_t *error_buf_len;
- if(!conn) {
- #ifndef SASL_OSX_CFMGLUE
- if(!(flags & SASL_NOLOG)) {
- /* See if we have a logging callback... */
- result = _sasl_getcallback(NULL, SASL_CB_LOG, (sasl_callback_ft *)&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 /* SASL_OSX_CFMGLUE */
- return;
- } else if(!fmt) return;
- /* we need to use a back end function to get the buffer because the
- cfm glue can't be rooting around in the internal structs */
- _sasl_get_errorbuf(conn, &error_buf, &error_buf_len);
- formatlen = strlen(fmt);
- va_start(ap, fmt); /* start varargs */
- while(pos<formatlen)
- {
- if (fmt[pos]!='%') /* regular character */
- {
- result = _buf_alloc(error_buf, error_buf_len, outlen+1);
- if (result != SASL_OK)
- goto done;
- (*error_buf)[outlen]=fmt[pos];
- outlen++;
- pos++;
- } else { /* formating thing */
- int done=0;
- char frmt[10];
- int frmtpos=1;
- char tempbuf[21];
- frmt[0]='%';
- pos++;
- while (done==0)
- {
- switch(fmt[pos])
- {
- case 's': /* need to handle this */
- cval = va_arg(ap, char *); /* get the next arg */
- result = _sasl_add_string(error_buf, error_buf_len,
- &outlen, cval);
-
- if (result != SASL_OK) /* add the string */
- goto done;
- done=1;
- break;
- case '%': /* double % output the '%' character */
- result = _buf_alloc(error_buf, error_buf_len, outlen+1);
- if (result != SASL_OK)
- goto done;
- (*error_buf)[outlen]='%';
- outlen++;
- done=1;
- break;
- case 'm': /* insert the errno string */
- result = _sasl_add_string(error_buf, error_buf_len,
- &outlen,
- strerror(va_arg(ap, int)));
- if (result != SASL_OK)
- goto done;
- done=1;
- break;
- case 'z': /* insert the sasl error string */
- result = _sasl_add_string(error_buf, error_buf_len, &outlen,
- (char *)sasl_errstring(_sasl_seterror_usererr(
- va_arg(ap, int)),NULL,NULL));
- if (result != SASL_OK)
- goto done;
- done=1;
- break;
- case 'c':
- frmt[frmtpos++]=fmt[pos];
- frmt[frmtpos]=0;
- tempbuf[0] = (char) va_arg(ap, int); /* get the next arg */
- tempbuf[1]='\0';
-
- /* now add the character */
- result = _sasl_add_string(error_buf, error_buf_len,
- &outlen, tempbuf);
- if (result != SASL_OK)
- goto done;
- done=1;
- break;
- case 'd':
- case 'i':
- frmt[frmtpos++]=fmt[pos];
- frmt[frmtpos]=0;
- ival = va_arg(ap, int); /* get the next arg */
- snprintf(tempbuf,20,frmt,ival); /* have snprintf do the work */
- /* now add the string */
- result = _sasl_add_string(error_buf, error_buf_len,
- &outlen, tempbuf);
- if (result != SASL_OK)
- goto done;
- done=1;
- break;
- default:
- frmt[frmtpos++]=fmt[pos]; /* add to the formating */
- frmt[frmtpos]=0;
- if (frmtpos>9)
- done=1;
- }
- pos++;
- if (pos>formatlen)
- done=1;
- }
- }
- }
- (*error_buf)[outlen]='\0'; /* put 0 at end */
- #ifndef SASL_OSX_CFMGLUE
- if(!(flags & SASL_NOLOG)) {
- /* See if we have a logging callback... */
- result = _sasl_getcallback(conn, SASL_CB_LOG, (sasl_callback_ft *)&log_cb, &log_ctx);
- if (result == SASL_OK && ! log_cb)
- result = SASL_FAIL;
- if (result != SASL_OK)
- goto done;
-
- result = log_cb(log_ctx, SASL_LOG_FAIL, conn->error_buf);
- }
- #endif /* SASL_OSX_CFMGLUE */
- done:
- va_end(ap);
- }
|