1 /* $NetBSD: error_string.c,v 1.1.1.1 2011/04/13 18:15:33 elric Exp $ */ 2 3 /* 4 * Copyright (c) 2001, 2003, 2005 - 2006 Kungliga Tekniska Högskolan 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 * @param context Kerberos 5 context 65 * @param ret The error code 66 * @param fmt Error string for the error code 67 * @param ... printf(3) style parameters. 68 * 69 * @ingroup krb5_error 70 */ 71 72 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 73 krb5_set_error_message(krb5_context context, krb5_error_code ret, 74 const char *fmt, ...) 75 __attribute__ ((format (printf, 3, 4))) 76 { 77 va_list ap; 78 79 va_start(ap, fmt); 80 krb5_vset_error_message (context, ret, fmt, ap); 81 va_end(ap); 82 } 83 84 /** 85 * Set the context full error string for a specific error code. 86 * 87 * @param context Kerberos 5 context 88 * @param ret The error code 89 * @param fmt Error string for the error code 90 * @param args printf(3) style parameters. 91 * 92 * @ingroup krb5_error 93 */ 94 95 96 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 97 krb5_vset_error_message (krb5_context context, krb5_error_code ret, 98 const char *fmt, va_list args) 99 __attribute__ ((format (printf, 3, 0))) 100 { 101 int r; 102 103 HEIMDAL_MUTEX_lock(context->mutex); 104 if (context->error_string) { 105 free(context->error_string); 106 context->error_string = NULL; 107 } 108 context->error_code = ret; 109 r = vasprintf(&context->error_string, fmt, args); 110 if (r < 0) 111 context->error_string = NULL; 112 HEIMDAL_MUTEX_unlock(context->mutex); 113 } 114 115 /** 116 * Prepend the context full error string for a specific error code. 117 * The error that is stored should be internationalized. 118 * 119 * @param context Kerberos 5 context 120 * @param ret The error code 121 * @param fmt Error string for the error code 122 * @param ... printf(3) style parameters. 123 * 124 * @ingroup krb5_error 125 */ 126 127 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 128 krb5_prepend_error_message(krb5_context context, krb5_error_code ret, 129 const char *fmt, ...) 130 __attribute__ ((format (printf, 3, 4))) 131 { 132 va_list ap; 133 134 va_start(ap, fmt); 135 krb5_vprepend_error_message(context, ret, fmt, ap); 136 va_end(ap); 137 } 138 139 /** 140 * Prepend the contexts's full error string for a specific error code. 141 * 142 * @param context Kerberos 5 context 143 * @param ret The error code 144 * @param fmt Error string for the error code 145 * @param args printf(3) style parameters. 146 * 147 * @ingroup krb5_error 148 */ 149 150 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 151 krb5_vprepend_error_message(krb5_context context, krb5_error_code ret, 152 const char *fmt, va_list args) 153 __attribute__ ((format (printf, 3, 0))) 154 { 155 char *str = NULL, *str2 = NULL; 156 HEIMDAL_MUTEX_lock(context->mutex); 157 if (context->error_code != ret) { 158 HEIMDAL_MUTEX_unlock(context->mutex); 159 return; 160 } 161 if (vasprintf(&str, fmt, args) < 0 || str == NULL) { 162 HEIMDAL_MUTEX_unlock(context->mutex); 163 return; 164 } 165 if (context->error_string) { 166 int e; 167 168 e = asprintf(&str2, "%s: %s", str, context->error_string); 169 free(context->error_string); 170 if (e < 0 || str2 == NULL) 171 context->error_string = NULL; 172 else 173 context->error_string = str2; 174 free(str); 175 } else 176 context->error_string = str; 177 HEIMDAL_MUTEX_unlock(context->mutex); 178 } 179 180 181 /** 182 * Return the error message in context. On error or no error string, 183 * the function returns NULL. 184 * 185 * @param context Kerberos 5 context 186 * 187 * @return an error string, needs to be freed with 188 * krb5_free_error_message(). The functions return NULL on error. 189 * 190 * @ingroup krb5_error 191 */ 192 193 KRB5_LIB_FUNCTION char * KRB5_LIB_CALL 194 krb5_get_error_string(krb5_context context) 195 { 196 char *ret = NULL; 197 198 HEIMDAL_MUTEX_lock(context->mutex); 199 if (context->error_string) 200 ret = strdup(context->error_string); 201 HEIMDAL_MUTEX_unlock(context->mutex); 202 return ret; 203 } 204 205 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 206 krb5_have_error_string(krb5_context context) 207 { 208 char *str; 209 HEIMDAL_MUTEX_lock(context->mutex); 210 str = context->error_string; 211 HEIMDAL_MUTEX_unlock(context->mutex); 212 return str != NULL; 213 } 214 215 /** 216 * Return the error message for `code' in context. On memory 217 * allocation error the function returns NULL. 218 * 219 * @param context Kerberos 5 context 220 * @param code Error code related to the error 221 * 222 * @return an error string, needs to be freed with 223 * krb5_free_error_message(). The functions return NULL on error. 224 * 225 * @ingroup krb5_error 226 */ 227 228 KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL 229 krb5_get_error_message(krb5_context context, krb5_error_code code) 230 { 231 char *str; 232 233 HEIMDAL_MUTEX_lock(context->mutex); 234 if (context->error_string && 235 (code == context->error_code || context->error_code == 0)) 236 { 237 str = strdup(context->error_string); 238 if (str) { 239 HEIMDAL_MUTEX_unlock(context->mutex); 240 return str; 241 } 242 } 243 HEIMDAL_MUTEX_unlock(context->mutex); 244 245 if (code == 0) 246 return strdup("Success"); 247 { 248 const char *msg; 249 char buf[128]; 250 msg = com_right_r(context->et_list, code, buf, sizeof(buf)); 251 if (msg) 252 return strdup(msg); 253 } 254 255 if (asprintf(&str, "<unknown error: %d>", (int)code) == -1 || str == NULL) 256 return NULL; 257 258 return str; 259 } 260 261 262 /** 263 * Free the error message returned by krb5_get_error_message(). 264 * 265 * @param context Kerberos context 266 * @param msg error message to free, returned byg 267 * krb5_get_error_message(). 268 * 269 * @ingroup krb5_error 270 */ 271 272 KRB5_LIB_FUNCTION void KRB5_LIB_CALL 273 krb5_free_error_message(krb5_context context, const char *msg) 274 { 275 free(rk_UNCONST(msg)); 276 } 277 278 279 /** 280 * Return the error string for the error code. The caller must not 281 * free the string. 282 * 283 * This function is deprecated since its not threadsafe. 284 * 285 * @param context Kerberos 5 context. 286 * @param code Kerberos error code. 287 * 288 * @return the error message matching code 289 * 290 * @ingroup krb5 291 */ 292 293 KRB5_DEPRECATED 294 KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 295 krb5_get_err_text(krb5_context context, krb5_error_code code) 296 { 297 const char *p = NULL; 298 if(context != NULL) 299 p = com_right(context->et_list, code); 300 if(p == NULL) 301 p = strerror(code); 302 if (p == NULL) 303 p = "Unknown error"; 304 return p; 305 } 306