xref: /illumos-gate/usr/src/lib/libsasl/lib/seterror.c (revision 1da57d551424de5a9d469760be7c4b4d4f10a755)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /* seterror.c - sasl_seterror split out because glue libraries
7*7c478bd9Sstevel@tonic-gate  *              can't pass varargs lists
8*7c478bd9Sstevel@tonic-gate  * Rob Siemborski
9*7c478bd9Sstevel@tonic-gate  * Tim Martin
10*7c478bd9Sstevel@tonic-gate  * split from common.c by Rolf Braun
11*7c478bd9Sstevel@tonic-gate  * $Id: seterror.c,v 1.7 2003/02/13 19:55:55 rjs3 Exp $
12*7c478bd9Sstevel@tonic-gate  */
13*7c478bd9Sstevel@tonic-gate 
14*7c478bd9Sstevel@tonic-gate /*
15*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
16*7c478bd9Sstevel@tonic-gate  *
17*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
18*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
19*7c478bd9Sstevel@tonic-gate  * are met:
20*7c478bd9Sstevel@tonic-gate  *
21*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
22*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
23*7c478bd9Sstevel@tonic-gate  *
24*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
25*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
26*7c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
27*7c478bd9Sstevel@tonic-gate  *    distribution.
28*7c478bd9Sstevel@tonic-gate  *
29*7c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
30*7c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
31*7c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
32*7c478bd9Sstevel@tonic-gate  *    details, please contact
33*7c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
34*7c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
35*7c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
36*7c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
37*7c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
38*7c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
39*7c478bd9Sstevel@tonic-gate  *
40*7c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
41*7c478bd9Sstevel@tonic-gate  *    acknowledgment:
42*7c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
43*7c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
44*7c478bd9Sstevel@tonic-gate  *
45*7c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
46*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
47*7c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
48*7c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
49*7c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
50*7c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
51*7c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
52*7c478bd9Sstevel@tonic-gate  */
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #include <config.h>
55*7c478bd9Sstevel@tonic-gate #include <stdio.h>
56*7c478bd9Sstevel@tonic-gate #include <string.h>
57*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
58*7c478bd9Sstevel@tonic-gate #include <limits.h>
59*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SYSLOG
60*7c478bd9Sstevel@tonic-gate #include <syslog.h>
61*7c478bd9Sstevel@tonic-gate #endif
62*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
63*7c478bd9Sstevel@tonic-gate #include <ctype.h>
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #include <sasl.h>
66*7c478bd9Sstevel@tonic-gate #include <saslutil.h>
67*7c478bd9Sstevel@tonic-gate #include <saslplug.h>
68*7c478bd9Sstevel@tonic-gate #include "saslint.h"
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate #ifdef WIN32
71*7c478bd9Sstevel@tonic-gate /* need to handle the fact that errno has been defined as a function
72*7c478bd9Sstevel@tonic-gate    in a dll, not an extern int */
73*7c478bd9Sstevel@tonic-gate # ifdef errno
74*7c478bd9Sstevel@tonic-gate #  undef errno
75*7c478bd9Sstevel@tonic-gate # endif /* errno */
76*7c478bd9Sstevel@tonic-gate #endif /* WIN32 */
77*7c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H
78*7c478bd9Sstevel@tonic-gate #include <unistd.h>
79*7c478bd9Sstevel@tonic-gate #endif
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
82*7c478bd9Sstevel@tonic-gate #include "plugin_common.h"
83*7c478bd9Sstevel@tonic-gate #include <wchar.h>
84*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate /* this is apparently no longer a user function */
_sasl_seterror_usererr(int saslerr)87*7c478bd9Sstevel@tonic-gate static int _sasl_seterror_usererr(int saslerr)
88*7c478bd9Sstevel@tonic-gate {
89*7c478bd9Sstevel@tonic-gate     /* Hide the difference in a username failure and a password failure */
90*7c478bd9Sstevel@tonic-gate     if (saslerr == SASL_NOUSER)
91*7c478bd9Sstevel@tonic-gate 	return SASL_BADAUTH;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate     /* otherwise return the error given; no transform necessary */
94*7c478bd9Sstevel@tonic-gate     return saslerr;
95*7c478bd9Sstevel@tonic-gate }
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate /* set the error string which will be returned by sasl_errdetail() using
98*7c478bd9Sstevel@tonic-gate  *  syslog()-style formatting (e.g. printf-style with %m as the string form
99*7c478bd9Sstevel@tonic-gate  *  of an errno error)
100*7c478bd9Sstevel@tonic-gate  *
101*7c478bd9Sstevel@tonic-gate  *  primarily for use by server callbacks such as the sasl_authorize_t
102*7c478bd9Sstevel@tonic-gate  *  callback and internally to plug-ins
103*7c478bd9Sstevel@tonic-gate  *
104*7c478bd9Sstevel@tonic-gate  * This will also trigger a call to the SASL logging callback (if any)
105*7c478bd9Sstevel@tonic-gate  * with a level of SASL_LOG_FAIL unless the SASL_NOLOG flag is set.
106*7c478bd9Sstevel@tonic-gate  *
107*7c478bd9Sstevel@tonic-gate  * Messages should be sensitive to the current language setting.  If there
108*7c478bd9Sstevel@tonic-gate  * is no SASL_CB_LANGUAGE callback messages MUST be US-ASCII otherwise UTF-8
109*7c478bd9Sstevel@tonic-gate  * is used and use of RFC 2482 for mixed-language text is encouraged.
110*7c478bd9Sstevel@tonic-gate  *
111*7c478bd9Sstevel@tonic-gate  * if conn is NULL, function does nothing
112*7c478bd9Sstevel@tonic-gate  */
sasl_seterror(sasl_conn_t * conn,unsigned flags,const char * fmt,...)113*7c478bd9Sstevel@tonic-gate void sasl_seterror(sasl_conn_t *conn,
114*7c478bd9Sstevel@tonic-gate 		   unsigned flags,
115*7c478bd9Sstevel@tonic-gate 		   const char *fmt, ...)
116*7c478bd9Sstevel@tonic-gate {
117*7c478bd9Sstevel@tonic-gate   size_t outlen=0; /* current length of output buffer */
118*7c478bd9Sstevel@tonic-gate   int pos=0; /* current position in format string */
119*7c478bd9Sstevel@tonic-gate   int formatlen;
120*7c478bd9Sstevel@tonic-gate   int result;
121*7c478bd9Sstevel@tonic-gate   sasl_log_t *log_cb;
122*7c478bd9Sstevel@tonic-gate   void *log_ctx;
123*7c478bd9Sstevel@tonic-gate   int ival;
124*7c478bd9Sstevel@tonic-gate   char *cval;
125*7c478bd9Sstevel@tonic-gate   va_list ap; /* varargs thing */
126*7c478bd9Sstevel@tonic-gate   char **error_buf;
127*7c478bd9Sstevel@tonic-gate   size_t *error_buf_len;
128*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
129*7c478bd9Sstevel@tonic-gate   _sasl_global_context_t *gctx;
130*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
131*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
132*7c478bd9Sstevel@tonic-gate   sasl_getsimple_t *simple_cb;
133*7c478bd9Sstevel@tonic-gate   void *simple_context;
134*7c478bd9Sstevel@tonic-gate   const char *lang = NULL;
135*7c478bd9Sstevel@tonic-gate   int ret;
136*7c478bd9Sstevel@tonic-gate   const sasl_utils_t *utils;
137*7c478bd9Sstevel@tonic-gate   int char_len;
138*7c478bd9Sstevel@tonic-gate   char *utf8_buf;
139*7c478bd9Sstevel@tonic-gate   const char *orig_fmt = fmt;
140*7c478bd9Sstevel@tonic-gate   int is_client;
141*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate   if(!conn) {
144*7c478bd9Sstevel@tonic-gate #ifndef SASL_OSX_CFMGLUE
145*7c478bd9Sstevel@tonic-gate       if(!(flags & SASL_NOLOG)) {
146*7c478bd9Sstevel@tonic-gate 	  /* See if we have a logging callback... */
147*7c478bd9Sstevel@tonic-gate 	  result = _sasl_getcallback(NULL, SASL_CB_LOG, &log_cb, &log_ctx);
148*7c478bd9Sstevel@tonic-gate 	  if (result == SASL_OK && ! log_cb)
149*7c478bd9Sstevel@tonic-gate 	      result = SASL_FAIL;
150*7c478bd9Sstevel@tonic-gate 	  if (result != SASL_OK)
151*7c478bd9Sstevel@tonic-gate 	      return;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	  log_cb(log_ctx, SASL_LOG_FAIL,
154*7c478bd9Sstevel@tonic-gate 		 "No sasl_conn_t passed to sasl_seterror");
155*7c478bd9Sstevel@tonic-gate       }
156*7c478bd9Sstevel@tonic-gate #endif /* SASL_OSX_CFMGLUE */
157*7c478bd9Sstevel@tonic-gate       return;
158*7c478bd9Sstevel@tonic-gate   } else if(!fmt) return;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
161*7c478bd9Sstevel@tonic-gate   gctx = conn->gctx;
162*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
165*7c478bd9Sstevel@tonic-gate   if (conn->type == SASL_CONN_SERVER) {
166*7c478bd9Sstevel@tonic-gate     utils = ((sasl_server_conn_t *)conn)->sparams->utils;
167*7c478bd9Sstevel@tonic-gate     is_client = 0;
168*7c478bd9Sstevel@tonic-gate   } else if (conn->type == SASL_CONN_CLIENT) {
169*7c478bd9Sstevel@tonic-gate     utils = ((sasl_client_conn_t *)conn)->cparams->utils;
170*7c478bd9Sstevel@tonic-gate     is_client = 1;
171*7c478bd9Sstevel@tonic-gate   } else
172*7c478bd9Sstevel@tonic-gate     utils = NULL;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate   if (utils != NULL) {
175*7c478bd9Sstevel@tonic-gate     ret = utils->getcallback(conn, SASL_CB_LANGUAGE, &simple_cb,
176*7c478bd9Sstevel@tonic-gate 	&simple_context);
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate     if (ret == SASL_OK && simple_cb)
179*7c478bd9Sstevel@tonic-gate 	(void) simple_cb(simple_context, SASL_CB_LANGUAGE, &lang, NULL);
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate     if (use_locale(lang, is_client))
182*7c478bd9Sstevel@tonic-gate 	fmt = dgettext(TEXT_DOMAIN, fmt);
183*7c478bd9Sstevel@tonic-gate   }
184*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate /* we need to use a back end function to get the buffer because the
187*7c478bd9Sstevel@tonic-gate    cfm glue can't be rooting around in the internal structs */
188*7c478bd9Sstevel@tonic-gate   _sasl_get_errorbuf(conn, &error_buf, &error_buf_len);
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate   formatlen = strlen(fmt);
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate   va_start(ap, fmt); /* start varargs */
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate   while(pos<formatlen)
195*7c478bd9Sstevel@tonic-gate   {
196*7c478bd9Sstevel@tonic-gate     if (fmt[pos]!='%') /* regular character */
197*7c478bd9Sstevel@tonic-gate     {
198*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
199*7c478bd9Sstevel@tonic-gate       char_len =  mbrlen(fmt + pos, formatlen - pos, NULL);
200*7c478bd9Sstevel@tonic-gate       result = _buf_alloc(error_buf, error_buf_len, outlen + char_len);
201*7c478bd9Sstevel@tonic-gate       if (result != SASL_OK)
202*7c478bd9Sstevel@tonic-gate 	return;
203*7c478bd9Sstevel@tonic-gate       while (char_len-- > 0) {
204*7c478bd9Sstevel@tonic-gate 	(*error_buf)[outlen]=fmt[pos];
205*7c478bd9Sstevel@tonic-gate 	outlen++;
206*7c478bd9Sstevel@tonic-gate 	pos++;
207*7c478bd9Sstevel@tonic-gate       }
208*7c478bd9Sstevel@tonic-gate #else
209*7c478bd9Sstevel@tonic-gate       result = _buf_alloc(error_buf, error_buf_len, outlen+1);
210*7c478bd9Sstevel@tonic-gate       if (result != SASL_OK)
211*7c478bd9Sstevel@tonic-gate 	return;
212*7c478bd9Sstevel@tonic-gate       (*error_buf)[outlen]=fmt[pos];
213*7c478bd9Sstevel@tonic-gate       outlen++;
214*7c478bd9Sstevel@tonic-gate       pos++;
215*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
216*7c478bd9Sstevel@tonic-gate     } else { /* formating thing */
217*7c478bd9Sstevel@tonic-gate       int done=0;
218*7c478bd9Sstevel@tonic-gate       char frmt[10];
219*7c478bd9Sstevel@tonic-gate       int frmtpos=1;
220*7c478bd9Sstevel@tonic-gate       char tempbuf[21];
221*7c478bd9Sstevel@tonic-gate       frmt[0]='%';
222*7c478bd9Sstevel@tonic-gate       pos++;
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate       while (done==0)
225*7c478bd9Sstevel@tonic-gate       {
226*7c478bd9Sstevel@tonic-gate 	switch(fmt[pos])
227*7c478bd9Sstevel@tonic-gate 	  {
228*7c478bd9Sstevel@tonic-gate 	  case 's': /* need to handle this */
229*7c478bd9Sstevel@tonic-gate 	    cval = va_arg(ap, char *); /* get the next arg */
230*7c478bd9Sstevel@tonic-gate 	    result = _sasl_add_string(error_buf, error_buf_len,
231*7c478bd9Sstevel@tonic-gate 				      &outlen, cval);
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	    if (result != SASL_OK) /* add the string */
234*7c478bd9Sstevel@tonic-gate 	      return;
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 	    done=1;
237*7c478bd9Sstevel@tonic-gate 	    break;
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 	  case '%': /* double % output the '%' character */
240*7c478bd9Sstevel@tonic-gate 	    result = _buf_alloc(error_buf, error_buf_len, outlen+1);
241*7c478bd9Sstevel@tonic-gate 	    if (result != SASL_OK)
242*7c478bd9Sstevel@tonic-gate 	      return;
243*7c478bd9Sstevel@tonic-gate 	    (*error_buf)[outlen]='%';
244*7c478bd9Sstevel@tonic-gate 	    outlen++;
245*7c478bd9Sstevel@tonic-gate 	    done=1;
246*7c478bd9Sstevel@tonic-gate 	    break;
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	  case 'm': /* insert the errno string */
249*7c478bd9Sstevel@tonic-gate 	    result = _sasl_add_string(error_buf, error_buf_len,
250*7c478bd9Sstevel@tonic-gate 				      &outlen,
251*7c478bd9Sstevel@tonic-gate 				      strerror(va_arg(ap, int)));
252*7c478bd9Sstevel@tonic-gate 	    if (result != SASL_OK)
253*7c478bd9Sstevel@tonic-gate 	      return;
254*7c478bd9Sstevel@tonic-gate 	    done=1;
255*7c478bd9Sstevel@tonic-gate 	    break;
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	  case 'z': /* insert the sasl error string */
258*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
259*7c478bd9Sstevel@tonic-gate 	    result = _sasl_add_string(error_buf, error_buf_len,	&outlen,
260*7c478bd9Sstevel@tonic-gate 			 (char *)sasl_errstring(_sasl_seterror_usererr(
261*7c478bd9Sstevel@tonic-gate 					        va_arg(ap, int)), lang, NULL));
262*7c478bd9Sstevel@tonic-gate #else
263*7c478bd9Sstevel@tonic-gate 	    result = _sasl_add_string(error_buf, error_buf_len,	&outlen,
264*7c478bd9Sstevel@tonic-gate 			 (char *)sasl_errstring(_sasl_seterror_usererr(
265*7c478bd9Sstevel@tonic-gate 					        va_arg(ap, int)),NULL,NULL));
266*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
267*7c478bd9Sstevel@tonic-gate 	    if (result != SASL_OK)
268*7c478bd9Sstevel@tonic-gate 	      return;
269*7c478bd9Sstevel@tonic-gate 	    done=1;
270*7c478bd9Sstevel@tonic-gate 	    break;
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	  case 'c':
273*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
274*7c478bd9Sstevel@tonic-gate 	    frmt[frmtpos++]=fmt[pos];
275*7c478bd9Sstevel@tonic-gate 	    frmt[frmtpos]=0;
276*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
277*7c478bd9Sstevel@tonic-gate 	    tempbuf[0] = (char) va_arg(ap, int); /* get the next arg */
278*7c478bd9Sstevel@tonic-gate 	    tempbuf[1]='\0';
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	    /* now add the character */
281*7c478bd9Sstevel@tonic-gate 	    result = _sasl_add_string(error_buf, error_buf_len,
282*7c478bd9Sstevel@tonic-gate 				      &outlen, tempbuf);
283*7c478bd9Sstevel@tonic-gate 	    if (result != SASL_OK)
284*7c478bd9Sstevel@tonic-gate 	      return;
285*7c478bd9Sstevel@tonic-gate 	    done=1;
286*7c478bd9Sstevel@tonic-gate 	    break;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	  case 'd':
289*7c478bd9Sstevel@tonic-gate 	  case 'i':
290*7c478bd9Sstevel@tonic-gate 	    frmt[frmtpos++]=fmt[pos];
291*7c478bd9Sstevel@tonic-gate 	    frmt[frmtpos]=0;
292*7c478bd9Sstevel@tonic-gate 	    ival = va_arg(ap, int); /* get the next arg */
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	    snprintf(tempbuf,20,frmt,ival); /* have snprintf do the work */
295*7c478bd9Sstevel@tonic-gate 	    /* now add the string */
296*7c478bd9Sstevel@tonic-gate 	    result = _sasl_add_string(error_buf, error_buf_len,
297*7c478bd9Sstevel@tonic-gate 				      &outlen, tempbuf);
298*7c478bd9Sstevel@tonic-gate 	    if (result != SASL_OK)
299*7c478bd9Sstevel@tonic-gate 	      return;
300*7c478bd9Sstevel@tonic-gate 	    done=1;
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	    break;
303*7c478bd9Sstevel@tonic-gate 	  default:
304*7c478bd9Sstevel@tonic-gate 	    frmt[frmtpos++]=fmt[pos]; /* add to the formating */
305*7c478bd9Sstevel@tonic-gate 	    frmt[frmtpos]=0;
306*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
307*7c478bd9Sstevel@tonic-gate 	    if (frmtpos > sizeof (frmt) - 2)
308*7c478bd9Sstevel@tonic-gate #else
309*7c478bd9Sstevel@tonic-gate 	    if (frmtpos>9)
310*7c478bd9Sstevel@tonic-gate #endif	/* _SUN_SDK_ */
311*7c478bd9Sstevel@tonic-gate 	      done=1;
312*7c478bd9Sstevel@tonic-gate 	  }
313*7c478bd9Sstevel@tonic-gate 	pos++;
314*7c478bd9Sstevel@tonic-gate 	if (pos>formatlen)
315*7c478bd9Sstevel@tonic-gate 	  done=1;
316*7c478bd9Sstevel@tonic-gate       }
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate     }
319*7c478bd9Sstevel@tonic-gate   }
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate   (*error_buf)[outlen]='\0'; /* put 0 at end */
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate   va_end(ap);
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_
326*7c478bd9Sstevel@tonic-gate   if (orig_fmt != fmt) {
327*7c478bd9Sstevel@tonic-gate     utf8_buf = local_to_utf(utils, *error_buf);
328*7c478bd9Sstevel@tonic-gate     if (utf8_buf != NULL) {
329*7c478bd9Sstevel@tonic-gate       outlen = strlen(utf8_buf);
330*7c478bd9Sstevel@tonic-gate       result = SASL_OK;
331*7c478bd9Sstevel@tonic-gate       if (outlen >= *error_buf_len)
332*7c478bd9Sstevel@tonic-gate       result = _buf_alloc(error_buf, error_buf_len, outlen+1);
333*7c478bd9Sstevel@tonic-gate       if (result != SASL_OK) {
334*7c478bd9Sstevel@tonic-gate 	utils->free(utf8_buf);
335*7c478bd9Sstevel@tonic-gate 	return;
336*7c478bd9Sstevel@tonic-gate       }
337*7c478bd9Sstevel@tonic-gate       strcpy(*error_buf, utf8_buf);
338*7c478bd9Sstevel@tonic-gate       utils->free(utf8_buf);
339*7c478bd9Sstevel@tonic-gate     }
340*7c478bd9Sstevel@tonic-gate   }
341*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate #ifndef SASL_OSX_CFMGLUE
344*7c478bd9Sstevel@tonic-gate   if(!(flags & SASL_NOLOG)) {
345*7c478bd9Sstevel@tonic-gate       /* See if we have a logging callback... */
346*7c478bd9Sstevel@tonic-gate       result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx);
347*7c478bd9Sstevel@tonic-gate       if (result == SASL_OK && ! log_cb)
348*7c478bd9Sstevel@tonic-gate 	  result = SASL_FAIL;
349*7c478bd9Sstevel@tonic-gate       if (result != SASL_OK)
350*7c478bd9Sstevel@tonic-gate 	  return;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate       result = log_cb(log_ctx, SASL_LOG_FAIL, conn->error_buf);
353*7c478bd9Sstevel@tonic-gate   }
354*7c478bd9Sstevel@tonic-gate #endif /* SASL_OSX_CFMGLUE */
355*7c478bd9Sstevel@tonic-gate }
356