1/* 2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "krb5_locl.h" 35#include <err.h> 36 37#undef HEIMDAL_PRINTF_ATTRIBUTE 38#define HEIMDAL_PRINTF_ATTRIBUTE(x) 39#undef HEIMDAL_NORETURN_ATTRIBUTE 40#define HEIMDAL_NORETURN_ATTRIBUTE 41 42static krb5_error_code _warnerr(krb5_context context, int do_errtext, 43 krb5_error_code code, int level, 44 void (*logfunc)(const char *fmt, ...) __attribute__((__format__(__printf__, 1, 2))), 45 const char *fmt, va_list ap) 46 __attribute__((__format__(__printf__, 6, 0))); 47 48static krb5_error_code 49_warnerr(krb5_context context, int do_errtext, 50 krb5_error_code code, int level, 51 void (*logfunc)(const char *fmt, ...), 52 const char *fmt, va_list ap) 53{ 54 char xfmt[7] = ""; 55 const char *args[2], **arg; 56 char *msg = NULL; 57 const char *err_str = NULL; 58 krb5_error_code ret; 59 60 args[0] = args[1] = NULL; 61 arg = args; 62 if(fmt){ 63 strlcat(xfmt, "%s", sizeof(xfmt)); 64 if(do_errtext) 65 strlcat(xfmt, ": ", sizeof(xfmt)); 66 ret = vasprintf(&msg, fmt, ap); 67 if(ret < 0 || msg == NULL) 68 return ENOMEM; 69 *arg++ = msg; 70 } 71 if(context && do_errtext){ 72 strlcat(xfmt, "%s", sizeof(xfmt)); 73 74 err_str = krb5_get_error_message(context, code); 75 if (err_str != NULL) { 76 *arg = err_str; 77 } else { 78 *arg= "<unknown error>"; 79 } 80 } 81 82#ifdef __clang__ 83#pragma clang diagnostic push 84#pragma clang diagnostic ignored "-Wformat-nonliteral" 85#endif 86 87 if (logfunc) 88 logfunc(xfmt, args[0], args[1]); 89 else if(context && context->warn_dest) 90 krb5_log(context, context->warn_dest, level, xfmt, args[0], args[1]); 91 else 92 warnx(xfmt, args[0], args[1]); 93 94#ifdef __clang__ 95#pragma clang diagnostic pop 96#endif 97 98 free(msg); 99 krb5_free_error_message(context, err_str); 100 return 0; 101} 102 103#define FUNC(ETEXT, CODE, LEVEL) \ 104 krb5_error_code ret; \ 105 va_list ap; \ 106 va_start(ap, fmt); \ 107 ret = _warnerr(context, ETEXT, CODE, LEVEL, NULL, fmt, ap); \ 108 va_end(ap); 109 110/** 111 * Log a warning to the log, default stderr, include the error from 112 * the last failure. 113 * 114 * @param context A Kerberos 5 context. 115 * @param code error code of the last error 116 * @param fmt message to print 117 * @param ap arguments 118 * 119 * @ingroup krb5_error 120 */ 121 122KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 123krb5_vwarn(krb5_context context, krb5_error_code code, 124 const char *fmt, va_list ap) 125 HEIMDAL_PRINTF_ATTRIBUTE((printf, 3, 0)) 126{ 127 return _warnerr(context, 1, code, 1, NULL, fmt, ap); 128} 129 130/** 131 * Log a warning to the log, default stderr, include the error from 132 * the last failure. 133 * 134 * @param context A Kerberos 5 context. 135 * @param code error code of the last error 136 * @param fmt message to print 137 * 138 * @ingroup krb5_error 139 */ 140 141KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 142krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...) 143 HEIMDAL_PRINTF_ATTRIBUTE((printf, 3, 4)) 144{ 145 FUNC(1, code, 1); 146 return ret; 147} 148 149/** 150 * Log a warning to the log, default stderr. 151 * 152 * @param context A Kerberos 5 context. 153 * @param fmt message to print 154 * @param ap arguments 155 * 156 * @ingroup krb5_error 157 */ 158 159KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 160krb5_vwarnx(krb5_context context, const char *fmt, va_list ap) 161 HEIMDAL_PRINTF_ATTRIBUTE((printf, 2, 0)) 162{ 163 return _warnerr(context, 0, 0, 1, NULL, fmt, ap); 164} 165 166/** 167 * Log a warning to the log, default stderr. 168 * 169 * @param context A Kerberos 5 context. 170 * @param fmt message to print 171 * 172 * @ingroup krb5_error 173 */ 174 175KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 176krb5_warnx(krb5_context context, const char *fmt, ...) 177 HEIMDAL_PRINTF_ATTRIBUTE((printf, 2, 3)) 178{ 179 FUNC(0, 0, 1); 180 return ret; 181} 182 183/** 184 * Log a warning to the log, default stderr, include bthe error from 185 * the last failure and then exit. 186 * 187 * @param context A Kerberos 5 context 188 * @param eval the exit code to exit with 189 * @param code error code of the last error 190 * @param fmt message to print 191 * @param ap arguments 192 * 193 * @ingroup krb5_error 194 */ 195 196KRB5_LIB_FUNCTION void KRB5_LIB_CALL 197krb5_verr(krb5_context context, int eval, krb5_error_code code, 198 const char *fmt, va_list ap) 199 HEIMDAL_PRINTF_ATTRIBUTE((printf, 4, 0)) 200 HEIMDAL_NORETURN_ATTRIBUTE 201{ 202 _warnerr(context, 1, code, 0, NULL, fmt, ap); 203 exit(eval); 204 UNREACHABLE(return 0); 205} 206 207/** 208 * Log a warning to the log, default stderr, include bthe error from 209 * the last failure and then exit. 210 * 211 * @param context A Kerberos 5 context 212 * @param eval the exit code to exit with 213 * @param code error code of the last error 214 * @param fmt message to print 215 * 216 * @ingroup krb5_error 217 */ 218 219KRB5_LIB_FUNCTION void KRB5_LIB_CALL 220krb5_err(krb5_context context, int eval, krb5_error_code code, 221 const char *fmt, ...) 222 HEIMDAL_PRINTF_ATTRIBUTE((printf, 4, 5)) 223 HEIMDAL_NORETURN_ATTRIBUTE 224{ 225 FUNC(1, code, 0); 226 exit(eval); 227 UNREACHABLE(return 0); 228} 229 230/** 231 * Log a warning to the log, default stderr, and then exit. 232 * 233 * @param context A Kerberos 5 context 234 * @param eval the exit code to exit with 235 * @param fmt message to print 236 * @param ap arguments 237 * 238 * @ingroup krb5_error 239 */ 240 241KRB5_LIB_FUNCTION void KRB5_LIB_CALL 242krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap) 243 HEIMDAL_PRINTF_ATTRIBUTE((printf, 3, 0)) 244 HEIMDAL_NORETURN_ATTRIBUTE 245{ 246 _warnerr(context, 0, 0, 0, NULL, fmt, ap); 247 exit(eval); 248 UNREACHABLE(return 0); 249} 250 251/** 252 * Log a warning to the log, default stderr, and then exit. 253 * 254 * @param context A Kerberos 5 context 255 * @param eval the exit code to exit with 256 * @param fmt message to print 257 * 258 * @ingroup krb5_error 259 */ 260 261KRB5_LIB_FUNCTION void KRB5_LIB_CALL 262krb5_errx(krb5_context context, int eval, const char *fmt, ...) 263 HEIMDAL_PRINTF_ATTRIBUTE((printf, 3, 4)) 264 HEIMDAL_NORETURN_ATTRIBUTE 265{ 266 FUNC(0, 0, 0); 267 exit(eval); 268 UNREACHABLE(return 0); 269} 270 271/** 272 * Log a warning to the log, default stderr, include bthe error from 273 * the last failure and then abort. 274 * 275 * @param context A Kerberos 5 context 276 * @param code error code of the last error 277 * @param fmt message to print 278 * @param ap arguments 279 * 280 * @ingroup krb5_error 281 */ 282 283KRB5_LIB_FUNCTION void KRB5_LIB_CALL 284krb5_vabort(krb5_context context, krb5_error_code code, 285 const char *fmt, va_list ap) 286 HEIMDAL_PRINTF_ATTRIBUTE((printf, 3, 0)) 287 HEIMDAL_NORETURN_ATTRIBUTE 288{ 289 _warnerr(context, 1, code, 0, NULL, fmt, ap); 290 abort(); 291 UNREACHABLE(return 0); 292} 293 294/** 295 * Log a warning to the log, default stderr, include the error from 296 * the last failure and then abort. 297 * 298 * @param context A Kerberos 5 context 299 * @param code error code of the last error 300 * @param fmt message to print 301 * 302 * @ingroup krb5_error 303 */ 304 305KRB5_LIB_FUNCTION void KRB5_LIB_CALL 306krb5_abort(krb5_context context, krb5_error_code code, const char *fmt, ...) 307 HEIMDAL_PRINTF_ATTRIBUTE((printf, 3, 4)) 308 HEIMDAL_NORETURN_ATTRIBUTE 309{ 310 va_list ap; 311 va_start(ap, fmt); 312 _warnerr(context, 1, code, 0, heim_abort, fmt, ap); 313 va_end(ap); 314 abort(); 315 UNREACHABLE(return 0); 316} 317 318KRB5_LIB_FUNCTION void KRB5_LIB_CALL 319krb5_vabortx(krb5_context context, const char *fmt, va_list ap) 320 HEIMDAL_PRINTF_ATTRIBUTE((printf, 2, 0)) 321 HEIMDAL_NORETURN_ATTRIBUTE 322{ 323 _warnerr(context, 0, 0, 0, heim_abort, fmt, ap); 324 abort(); 325 UNREACHABLE(return 0); 326} 327 328/** 329 * Log a warning to the log, default stderr, and then abort. 330 * 331 * @param context A Kerberos 5 context 332 * @param fmt message to print 333 * 334 * @ingroup krb5_error 335 */ 336 337KRB5_LIB_FUNCTION void KRB5_LIB_CALL 338krb5_abortx(krb5_context context, const char *fmt, ...) 339 HEIMDAL_PRINTF_ATTRIBUTE((printf, 2, 3)) 340 HEIMDAL_NORETURN_ATTRIBUTE 341{ 342 FUNC(0, 0, 0); 343 abort(); 344 UNREACHABLE(return 0); 345} 346 347/** 348 * Set the default logging facility. 349 * 350 * @param context A Kerberos 5 context 351 * @param fac Facility to use for logging. 352 * 353 * @ingroup krb5_error 354 */ 355 356KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 357krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac) 358{ 359 if (context->warn_dest) 360 krb5_closelog(context, context->warn_dest); 361 context->warn_dest = fac; 362 return 0; 363} 364 365/** 366 * Get the default logging facility. 367 * 368 * @param context A Kerberos 5 context 369 * 370 * @ingroup krb5_error 371 */ 372 373KRB5_LIB_FUNCTION krb5_log_facility * KRB5_LIB_CALL 374krb5_get_warn_dest(krb5_context context) 375{ 376 return context->warn_dest; 377} 378 379/** 380 * Set the default debug logging facility. 381 * 382 * @param context A Kerberos 5 context 383 * @param fac Facility to use for logging. 384 * 385 * @ingroup krb5_error 386 */ 387 388KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 389krb5_set_debug_dest(krb5_context context, krb5_log_facility *fac) 390{ 391 if (context->debug_dest) 392 krb5_closelog(context, context->debug_dest); 393 context->debug_dest = fac; 394 return 0; 395} 396 397/** 398 * Get the default debug logging facility. 399 * 400 * @param context A Kerberos 5 context 401 * 402 * @ingroup krb5_error 403 */ 404 405KRB5_LIB_FUNCTION krb5_log_facility * KRB5_LIB_CALL 406krb5_get_debug_dest(krb5_context context) 407{ 408 return context->debug_dest; 409} 410