Home | History | Annotate | Line # | Download | only in krb5
      1 /*	$NetBSD: error_string.c,v 1.3 2019/12/15 22:50:50 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2001, 2003, 2005 - 2006 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the Institute nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include "krb5_locl.h"
     37 
     38 #undef __attribute__
     39 #define __attribute__(x)
     40 
     41 /**
     42  * Clears the error message from the Kerberos 5 context.
     43  *
     44  * @param context The Kerberos 5 context to clear
     45  *
     46  * @ingroup krb5_error
     47  */
     48 
     49 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
     50 krb5_clear_error_message(krb5_context context)
     51 {
     52     HEIMDAL_MUTEX_lock(&context->mutex);
     53     if (context->error_string)
     54 	free(context->error_string);
     55     context->error_code = 0;
     56     context->error_string = NULL;
     57     HEIMDAL_MUTEX_unlock(&context->mutex);
     58 }
     59 
     60 /**
     61  * Set the context full error string for a specific error code.
     62  * The error that is stored should be internationalized.
     63  *
     64  * The if context is NULL, no error string is stored.
     65  *
     66  * @param context Kerberos 5 context
     67  * @param ret The error code
     68  * @param fmt Error string for the error code
     69  * @param ... printf(3) style parameters.
     70  *
     71  * @ingroup krb5_error
     72  */
     73 
     74 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
     75 krb5_set_error_message(krb5_context context, krb5_error_code ret,
     76 		       const char *fmt, ...)
     77     __attribute__ ((__format__ (__printf__, 3, 4)))
     78 {
     79     va_list ap;
     80 
     81     va_start(ap, fmt);
     82     krb5_vset_error_message (context, ret, fmt, ap);
     83     va_end(ap);
     84 }
     85 
     86 /**
     87  * Set the context full error string for a specific error code.
     88  *
     89  * The if context is NULL, no error string is stored.
     90  *
     91  * @param context Kerberos 5 context
     92  * @param ret The error code
     93  * @param fmt Error string for the error code
     94  * @param args printf(3) style parameters.
     95  *
     96  * @ingroup krb5_error
     97  */
     98 
     99 
    100 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
    101 krb5_vset_error_message (krb5_context context, krb5_error_code ret,
    102 			 const char *fmt, va_list args)
    103     __attribute__ ((__format__ (__printf__, 3, 0)))
    104 {
    105     int r;
    106 
    107     if (context == NULL)
    108 	return;
    109 
    110     HEIMDAL_MUTEX_lock(&context->mutex);
    111     if (context->error_string) {
    112 	free(context->error_string);
    113 	context->error_string = NULL;
    114     }
    115     context->error_code = ret;
    116     r = vasprintf(&context->error_string, fmt, args);
    117     if (r < 0)
    118 	context->error_string = NULL;
    119     HEIMDAL_MUTEX_unlock(&context->mutex);
    120     if (context->error_string)
    121 	_krb5_debug(context, 100, "error message: %s: %d", context->error_string, ret);
    122 }
    123 
    124 /**
    125  * Prepend the context full error string for a specific error code.
    126  * The error that is stored should be internationalized.
    127  *
    128  * The if context is NULL, no error string is stored.
    129  *
    130  * @param context Kerberos 5 context
    131  * @param ret The error code
    132  * @param fmt Error string for the error code
    133  * @param ... printf(3) style parameters.
    134  *
    135  * @ingroup krb5_error
    136  */
    137 
    138 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
    139 krb5_prepend_error_message(krb5_context context, krb5_error_code ret,
    140 			   const char *fmt, ...)
    141     __attribute__ ((__format__ (__printf__, 3, 4)))
    142 {
    143     va_list ap;
    144 
    145     va_start(ap, fmt);
    146     krb5_vprepend_error_message(context, ret, fmt, ap);
    147     va_end(ap);
    148 }
    149 
    150 /**
    151  * Prepend the contexts's full error string for a specific error code.
    152  *
    153  * The if context is NULL, no error string is stored.
    154  *
    155  * @param context Kerberos 5 context
    156  * @param ret The error code
    157  * @param fmt Error string for the error code
    158  * @param args printf(3) style parameters.
    159  *
    160  * @ingroup krb5_error
    161  */
    162 
    163 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
    164 krb5_vprepend_error_message(krb5_context context, krb5_error_code ret,
    165 			    const char *fmt, va_list args)
    166     __attribute__ ((__format__ (__printf__, 3, 0)))
    167 {
    168     char *str = NULL, *str2 = NULL;
    169 
    170     if (context == NULL)
    171 	return;
    172 
    173     HEIMDAL_MUTEX_lock(&context->mutex);
    174     if (context->error_code != ret) {
    175 	HEIMDAL_MUTEX_unlock(&context->mutex);
    176 	return;
    177     }
    178     if (vasprintf(&str, fmt, args) < 0 || str == NULL) {
    179 	HEIMDAL_MUTEX_unlock(&context->mutex);
    180 	return;
    181     }
    182     if (context->error_string) {
    183 	int e;
    184 
    185 	e = asprintf(&str2, "%s: %s", str, context->error_string);
    186 	free(context->error_string);
    187 	if (e < 0 || str2 == NULL)
    188 	    context->error_string = NULL;
    189 	else
    190 	    context->error_string = str2;
    191 	free(str);
    192     } else
    193 	context->error_string = str;
    194     HEIMDAL_MUTEX_unlock(&context->mutex);
    195 }
    196 
    197 /**
    198  * Return the error message for `code' in context. On memory
    199  * allocation error the function returns NULL.
    200  *
    201  * @param context Kerberos 5 context
    202  * @param code Error code related to the error
    203  *
    204  * @return an error string, needs to be freed with
    205  * krb5_free_error_message(). The functions return NULL on error.
    206  *
    207  * @ingroup krb5_error
    208  */
    209 
    210 KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
    211 krb5_get_error_message(krb5_context context, krb5_error_code code)
    212 {
    213     char *str = NULL;
    214     const char *cstr = NULL;
    215     char buf[128];
    216     int free_context = 0;
    217 
    218     if (code == 0)
    219 	return strdup("Success");
    220 
    221     /*
    222      * The MIT version of this function ignores the krb5_context
    223      * and several widely deployed applications call krb5_get_error_message()
    224      * with a NULL context in order to translate an error code as a
    225      * replacement for error_message().  Another reason a NULL context
    226      * might be provided is if the krb5_init_context() call itself
    227      * failed.
    228      */
    229     if (context)
    230     {
    231 	HEIMDAL_MUTEX_lock(&context->mutex);
    232         if (context->error_string &&
    233             (code == context->error_code || context->error_code == 0))
    234         {
    235             str = strdup(context->error_string);
    236         }
    237 	HEIMDAL_MUTEX_unlock(&context->mutex);
    238 
    239         if (str)
    240             return str;
    241     }
    242     else
    243     {
    244         if (krb5_init_context(&context) == 0)
    245             free_context = 1;
    246     }
    247 
    248     if (context)
    249         cstr = com_right_r(context->et_list, code, buf, sizeof(buf));
    250 
    251     if (free_context)
    252         krb5_free_context(context);
    253 
    254     if (cstr)
    255         return strdup(cstr);
    256 
    257     cstr = error_message(code);
    258     if (cstr)
    259         return strdup(cstr);
    260 
    261     if (asprintf(&str, "<unknown error: %d>", (int)code) == -1 || str == NULL)
    262 	return NULL;
    263 
    264     return str;
    265 }
    266 
    267 
    268 /**
    269  * Free the error message returned by krb5_get_error_message().
    270  *
    271  * @param context Kerberos context
    272  * @param msg error message to free, returned byg
    273  *        krb5_get_error_message().
    274  *
    275  * @ingroup krb5_error
    276  */
    277 
    278 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
    279 krb5_free_error_message(krb5_context context, const char *msg)
    280 {
    281     free(rk_UNCONST(msg));
    282 }
    283 
    284 
    285 /**
    286  * Return the error string for the error code. The caller must not
    287  * free the string.
    288  *
    289  * This function is deprecated since its not threadsafe.
    290  *
    291  * @param context Kerberos 5 context.
    292  * @param code Kerberos error code.
    293  *
    294  * @return the error message matching code
    295  *
    296  * @ingroup krb5
    297  */
    298 
    299 KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
    300 krb5_get_err_text(krb5_context context, krb5_error_code code)
    301     KRB5_DEPRECATED_FUNCTION("Use krb5_get_error_message instead")
    302 {
    303     const char *p = NULL;
    304     if(context != NULL)
    305 	p = com_right(context->et_list, code);
    306     if(p == NULL)
    307 	p = strerror(code);
    308     if (p == NULL)
    309 	p = "Unknown error";
    310     return p;
    311 }
    312 
    313