10Sstevel@tonic-gate /* 26426Smp153739 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate /* 70Sstevel@tonic-gate * lib/kadm/logger.c 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * Copyright 1995 by the Massachusetts Institute of Technology. 100Sstevel@tonic-gate * All Rights Reserved. 110Sstevel@tonic-gate * 120Sstevel@tonic-gate * Export of this software from the United States of America may 130Sstevel@tonic-gate * require a specific license from the United States Government. 140Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 150Sstevel@tonic-gate * export to obtain such a license before exporting. 160Sstevel@tonic-gate * 170Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 180Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 190Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 200Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 210Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 220Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 230Sstevel@tonic-gate * to distribution of the software without specific, written prior 240Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 250Sstevel@tonic-gate * your software as modified software and not distribute it in such a 260Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 270Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 280Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 290Sstevel@tonic-gate * or implied warranty. 300Sstevel@tonic-gate * 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate /* KADM5 wants non-syslog log files to contain syslog-like entries */ 340Sstevel@tonic-gate #define VERBOSE_LOGS 350Sstevel@tonic-gate 360Sstevel@tonic-gate /* 370Sstevel@tonic-gate * logger.c - Handle logging functions for those who want it. 380Sstevel@tonic-gate */ 390Sstevel@tonic-gate #include "k5-int.h" 400Sstevel@tonic-gate #include "adm_proto.h" 410Sstevel@tonic-gate #include "com_err.h" 420Sstevel@tonic-gate #include <stdio.h> 430Sstevel@tonic-gate #include <ctype.h> 440Sstevel@tonic-gate #include <ctype.h> 45*7934SMark.Phalan@Sun.COM #ifdef HAVE_SYSLOG_H 460Sstevel@tonic-gate #include <syslog.h> 47*7934SMark.Phalan@Sun.COM #endif /* HAVE_SYSLOG_H */ 48*7934SMark.Phalan@Sun.COM #ifdef HAVE_STDARG_H 490Sstevel@tonic-gate #include <stdarg.h> 50*7934SMark.Phalan@Sun.COM #else /* HAVE_STDARG_H */ 51*7934SMark.Phalan@Sun.COM #include <varargs.h> 52*7934SMark.Phalan@Sun.COM #endif /* HAVE_STDARG_H */ 530Sstevel@tonic-gate #include <libintl.h> 540Sstevel@tonic-gate #include <sys/types.h> 550Sstevel@tonic-gate #include <sys/stat.h> 560Sstevel@tonic-gate 573998Ssemery #define KRB5_KLOG_MAX_ERRMSG_SIZE 2048 580Sstevel@tonic-gate #ifndef MAXHOSTNAMELEN 590Sstevel@tonic-gate #define MAXHOSTNAMELEN 256 600Sstevel@tonic-gate #endif /* MAXHOSTNAMELEN */ 610Sstevel@tonic-gate 620Sstevel@tonic-gate #define LSPEC_PARSE_ERR_1 1 630Sstevel@tonic-gate #define LSPEC_PARSE_ERR_2 2 640Sstevel@tonic-gate #define LOG_FILE_ERR 3 650Sstevel@tonic-gate #define LOG_DEVICE_ERR 4 660Sstevel@tonic-gate #define LOG_UFO_STRING 5 670Sstevel@tonic-gate #define LOG_EMERG_STRING 6 680Sstevel@tonic-gate #define LOG_ALERT_STRING 7 690Sstevel@tonic-gate #define LOG_CRIT_STRING 8 700Sstevel@tonic-gate #define LOG_ERR_STRING 9 710Sstevel@tonic-gate #define LOG_WARNING_STRING 10 720Sstevel@tonic-gate #define LOG_NOTICE_STRING 11 730Sstevel@tonic-gate #define LOG_INFO_STRING 12 740Sstevel@tonic-gate #define LOG_DEBUG_STRING 13 750Sstevel@tonic-gate /* This is to assure that we have at least one match in the syslog stuff */ 760Sstevel@tonic-gate /* 770Sstevel@tonic-gate static const char LSPEC_PARSE_ERR_1[] = "%s: cannot parse <%s>\n"; 780Sstevel@tonic-gate static const char LSPEC_PARSE_ERR_2[] = "%s: warning - logging entry syntax error\n"; 790Sstevel@tonic-gate static const char LOG_FILE_ERR[] = "%s: error writing to %s\n"; 800Sstevel@tonic-gate static const char LOG_DEVICE_ERR[] = "%s: error writing to %s device\n"; 810Sstevel@tonic-gate static const char LOG_UFO_STRING[] = "???"; 820Sstevel@tonic-gate static const char LOG_EMERG_STRING[] = "EMERGENCY"; 830Sstevel@tonic-gate static const char LOG_ALERT_STRING[] = "ALERT"; 840Sstevel@tonic-gate static const char LOG_CRIT_STRING[] = "CRITICAL"; 850Sstevel@tonic-gate static const char LOG_ERR_STRING[] = "Error"; 860Sstevel@tonic-gate static const char LOG_WARNING_STRING[] = "Warning"; 870Sstevel@tonic-gate static const char LOG_NOTICE_STRING[] = "Notice"; 880Sstevel@tonic-gate static const char LOG_INFO_STRING[] = "info"; 890Sstevel@tonic-gate static const char LOG_DEBUG_STRING[] = "debug"; 900Sstevel@tonic-gate */ 910Sstevel@tonic-gate 920Sstevel@tonic-gate 930Sstevel@tonic-gate const char * 940Sstevel@tonic-gate krb5_log_error_table(long errorno) { 950Sstevel@tonic-gate switch (errorno) { 960Sstevel@tonic-gate case LSPEC_PARSE_ERR_1: 970Sstevel@tonic-gate return(gettext("%s: cannot parse <%s>\n")); 980Sstevel@tonic-gate case LSPEC_PARSE_ERR_2: 990Sstevel@tonic-gate return(gettext("%s: warning - logging entry syntax error\n")); 1000Sstevel@tonic-gate case LOG_FILE_ERR: 1010Sstevel@tonic-gate return(gettext("%s: error writing to %s\n")); 1020Sstevel@tonic-gate case LOG_DEVICE_ERR: 1030Sstevel@tonic-gate return(gettext("%s: error writing to %s device\n")); 1040Sstevel@tonic-gate case LOG_UFO_STRING: 105358Sgtb default: 1060Sstevel@tonic-gate return(gettext("???")); 1070Sstevel@tonic-gate case LOG_EMERG_STRING: 1080Sstevel@tonic-gate return(gettext("EMERGENCY")); 1090Sstevel@tonic-gate case LOG_ALERT_STRING: 1100Sstevel@tonic-gate return(gettext("ALERT")); 1110Sstevel@tonic-gate case LOG_CRIT_STRING: 1120Sstevel@tonic-gate return(gettext("CRITICAL")); 1130Sstevel@tonic-gate case LOG_ERR_STRING: 1140Sstevel@tonic-gate return(gettext("Error")); 1150Sstevel@tonic-gate case LOG_WARNING_STRING: 1160Sstevel@tonic-gate return(gettext("Warning")); 1170Sstevel@tonic-gate case LOG_NOTICE_STRING: 1180Sstevel@tonic-gate return(gettext("Notice")); 1190Sstevel@tonic-gate case LOG_INFO_STRING: 1200Sstevel@tonic-gate return(gettext("info")); 1210Sstevel@tonic-gate case LOG_DEBUG_STRING: 1220Sstevel@tonic-gate return(gettext("info")); 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate /* 1270Sstevel@tonic-gate * Output logging. 1280Sstevel@tonic-gate * 1290Sstevel@tonic-gate * Output logging is now controlled by the configuration file. We can specify 1300Sstevel@tonic-gate * the following syntaxes under the [logging]->entity specification. 1310Sstevel@tonic-gate * FILE<opentype><pathname> 1320Sstevel@tonic-gate * SYSLOG[=<severity>[:<facility>]] 1330Sstevel@tonic-gate * STDERR 1340Sstevel@tonic-gate * CONSOLE 1350Sstevel@tonic-gate * DEVICE=<device-spec> 1360Sstevel@tonic-gate * 1370Sstevel@tonic-gate * Where: 1380Sstevel@tonic-gate * <opentype> is ":" for open/append, "=" for open/create. 1390Sstevel@tonic-gate * <pathname> is a valid path name. 1400Sstevel@tonic-gate * <severity> is one of: (default = ERR) 1410Sstevel@tonic-gate * EMERG 1420Sstevel@tonic-gate * ALERT 1430Sstevel@tonic-gate * CRIT 1440Sstevel@tonic-gate * ERR 1450Sstevel@tonic-gate * WARNING 1460Sstevel@tonic-gate * NOTICE 1470Sstevel@tonic-gate * INFO 1480Sstevel@tonic-gate * DEBUG 1490Sstevel@tonic-gate * <facility> is one of: (default = AUTH) 1500Sstevel@tonic-gate * KERN 1510Sstevel@tonic-gate * USER 1520Sstevel@tonic-gate * MAIL 1530Sstevel@tonic-gate * DAEMON 1540Sstevel@tonic-gate * AUTH 1550Sstevel@tonic-gate * LPR 1560Sstevel@tonic-gate * NEWS 1570Sstevel@tonic-gate * UUCP 1580Sstevel@tonic-gate * CRON 1590Sstevel@tonic-gate * LOCAL0..LOCAL7 1600Sstevel@tonic-gate * <device-spec> is a valid device specification. 1610Sstevel@tonic-gate */ 1620Sstevel@tonic-gate struct log_entry { 1630Sstevel@tonic-gate enum log_type { K_LOG_FILE, 1640Sstevel@tonic-gate K_LOG_SYSLOG, 1650Sstevel@tonic-gate K_LOG_STDERR, 1660Sstevel@tonic-gate K_LOG_CONSOLE, 1670Sstevel@tonic-gate K_LOG_DEVICE, 1680Sstevel@tonic-gate K_LOG_NONE } log_type; 1690Sstevel@tonic-gate krb5_pointer log_2free; 1700Sstevel@tonic-gate union log_union { 1710Sstevel@tonic-gate struct log_file { 1720Sstevel@tonic-gate FILE *lf_filep; 1730Sstevel@tonic-gate char *lf_fname; 1740Sstevel@tonic-gate char *lf_fopen_mode; /* "a+" or "w" */ 1750Sstevel@tonic-gate #define K_LOG_DEF_FILE_ROTATE_PERIOD -1 /* never */ 1760Sstevel@tonic-gate #define K_LOG_DEF_FILE_ROTATE_VERSIONS 0 /* no versions */ 1770Sstevel@tonic-gate time_t lf_rotate_period; 1780Sstevel@tonic-gate time_t lf_last_rotated; 1790Sstevel@tonic-gate int lf_rotate_versions; 1800Sstevel@tonic-gate } log_file; 1810Sstevel@tonic-gate struct log_syslog { 1820Sstevel@tonic-gate int ls_facility; 1830Sstevel@tonic-gate int ls_severity; 1840Sstevel@tonic-gate } log_syslog; 1850Sstevel@tonic-gate struct log_device { 1860Sstevel@tonic-gate FILE *ld_filep; 1870Sstevel@tonic-gate char *ld_devname; 1880Sstevel@tonic-gate } log_device; 1890Sstevel@tonic-gate } log_union; 1900Sstevel@tonic-gate }; 1910Sstevel@tonic-gate #define lfu_filep log_union.log_file.lf_filep 1920Sstevel@tonic-gate #define lfu_fname log_union.log_file.lf_fname 1930Sstevel@tonic-gate #define lfu_fopen_mode log_union.log_file.lf_fopen_mode 1940Sstevel@tonic-gate #define lfu_rotate_period log_union.log_file.lf_rotate_period 1950Sstevel@tonic-gate #define lfu_last_rotated log_union.log_file.lf_last_rotated 1960Sstevel@tonic-gate #define lfu_rotate_versions log_union.log_file.lf_rotate_versions 1970Sstevel@tonic-gate #define lsu_facility log_union.log_syslog.ls_facility 1980Sstevel@tonic-gate #define lsu_severity log_union.log_syslog.ls_severity 1990Sstevel@tonic-gate #define ldu_filep log_union.log_device.ld_filep 2000Sstevel@tonic-gate #define ldu_devname log_union.log_device.ld_devname 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate struct log_control { 2030Sstevel@tonic-gate struct log_entry *log_entries; 2040Sstevel@tonic-gate int log_nentries; 2050Sstevel@tonic-gate char *log_whoami; 2060Sstevel@tonic-gate char *log_hostname; 2070Sstevel@tonic-gate krb5_boolean log_opened; 2080Sstevel@tonic-gate }; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate static struct log_control log_control = { 2110Sstevel@tonic-gate (struct log_entry *) NULL, 2120Sstevel@tonic-gate 0, 2130Sstevel@tonic-gate (char *) NULL, 2140Sstevel@tonic-gate (char *) NULL, 2150Sstevel@tonic-gate 0 2160Sstevel@tonic-gate }; 2170Sstevel@tonic-gate static struct log_entry def_log_entry; 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate /* 2200Sstevel@tonic-gate * These macros define any special processing that needs to happen for 2210Sstevel@tonic-gate * devices. For unix, of course, this is hardly anything. 2220Sstevel@tonic-gate */ 2230Sstevel@tonic-gate #define DEVICE_OPEN(d, m) fopen(d, m) 2240Sstevel@tonic-gate #define CONSOLE_OPEN(m) fopen("/dev/console", m) 2250Sstevel@tonic-gate #define DEVICE_PRINT(f, m) ((fprintf(f, "%s\r\n", m) >= 0) ? \ 2260Sstevel@tonic-gate (fflush(f), 0) : \ 2270Sstevel@tonic-gate -1) 2280Sstevel@tonic-gate #define DEVICE_CLOSE(d) fclose(d) 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate /* 2320Sstevel@tonic-gate * klog_rotate() - roate a log file if we have specified rotation 2330Sstevel@tonic-gate * parameters in krb5.conf. 2340Sstevel@tonic-gate */ 2350Sstevel@tonic-gate static void 2360Sstevel@tonic-gate klog_rotate(struct log_entry *le) 2370Sstevel@tonic-gate { 2380Sstevel@tonic-gate time_t t; 2390Sstevel@tonic-gate int i; 2400Sstevel@tonic-gate char *name_buf1; 2410Sstevel@tonic-gate char *name_buf2; 2420Sstevel@tonic-gate char *old_name; 2430Sstevel@tonic-gate char *new_name; 2440Sstevel@tonic-gate char *tmp; 2450Sstevel@tonic-gate FILE *fp; 2460Sstevel@tonic-gate int num_vers; 2470Sstevel@tonic-gate mode_t old_umask; 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate /* 2510Sstevel@tonic-gate * By default we don't rotate. 2520Sstevel@tonic-gate */ 2530Sstevel@tonic-gate if (le->lfu_rotate_period == K_LOG_DEF_FILE_ROTATE_PERIOD) 2540Sstevel@tonic-gate return; 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate t = time(0); 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate if (t >= le->lfu_last_rotated + le->lfu_rotate_period) { 2590Sstevel@tonic-gate /* 2600Sstevel@tonic-gate * The N log file versions will be renamed X.N-1 X.N-2, ... X.0. 2610Sstevel@tonic-gate * So the allocate file name buffers that can the version 2620Sstevel@tonic-gate * number extensions. 2630Sstevel@tonic-gate * 32 extra bytes is plenty. 2640Sstevel@tonic-gate */ 2650Sstevel@tonic-gate name_buf1 = malloc(strlen(le->lfu_fname) + 32); 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate if (name_buf1 == NULL) 2680Sstevel@tonic-gate return; 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate name_buf2 = malloc(strlen(le->lfu_fname) + 32); 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate if (name_buf2 == NULL) { 2730Sstevel@tonic-gate free(name_buf1); 2740Sstevel@tonic-gate return; 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate old_name = name_buf1; 2780Sstevel@tonic-gate new_name = name_buf2; 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate /* 2810Sstevel@tonic-gate * If there N versions, then the first one has file extension 2820Sstevel@tonic-gate * of N-1. 2830Sstevel@tonic-gate */ 2840Sstevel@tonic-gate (void) sprintf(new_name, "%s.%d", le->lfu_fname, 2850Sstevel@tonic-gate le->lfu_rotate_versions - 1); 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* 2880Sstevel@tonic-gate * Rename file.N-2 to file.N-1, file.N-3 to file.N-2, ... 2890Sstevel@tonic-gate * file.0 to file.1 2900Sstevel@tonic-gate */ 2910Sstevel@tonic-gate for (i = le->lfu_rotate_versions - 1; i > 0; i--) { 2920Sstevel@tonic-gate (void) sprintf(old_name, "%s.%d", le->lfu_fname, i - 1); 2930Sstevel@tonic-gate (void) rename(old_name, new_name); 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate /* 2960Sstevel@tonic-gate * swap old name and new name. This way, 2970Sstevel@tonic-gate * on the next iteration, new_name.X 2980Sstevel@tonic-gate * becomes new_name.X-1. 2990Sstevel@tonic-gate */ 3000Sstevel@tonic-gate tmp = old_name; 3010Sstevel@tonic-gate old_name = new_name; 3020Sstevel@tonic-gate new_name = tmp; 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate old_name = le->lfu_fname; 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate (void) rename(old_name, new_name); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * Even though we don't know yet if the fopen() 3100Sstevel@tonic-gate * of the log file will succeed, we mark the log 3110Sstevel@tonic-gate * as rotated. This is so we don't repeatably 3120Sstevel@tonic-gate * rotate file.N-2 to file.N-1 ... etc without 3130Sstevel@tonic-gate * waiting for the rotate period to elapse. 3140Sstevel@tonic-gate */ 3150Sstevel@tonic-gate le->lfu_last_rotated = t; 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate /* 3180Sstevel@tonic-gate * Default log file creation mode should be read-only 3190Sstevel@tonic-gate * by owner(root), but the admin can override with 3200Sstevel@tonic-gate * chmod(1) if desired. 3210Sstevel@tonic-gate */ 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate old_umask = umask(077); 3240Sstevel@tonic-gate fp = fopen(old_name, le->lfu_fopen_mode); 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate umask(old_umask); 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate if (fp != NULL) { 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate (void) fclose(le->lfu_filep); 3310Sstevel@tonic-gate le->lfu_filep = fp; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate /* 3340Sstevel@tonic-gate * If the version parameter in krb5.conf was 3350Sstevel@tonic-gate * 0, then we take this to mean that rotating the 3360Sstevel@tonic-gate * log file will cause us to dispose of the 3370Sstevel@tonic-gate * old one, and created a new one. We have just 3380Sstevel@tonic-gate * renamed the old one to file.-1, so remove it. 3390Sstevel@tonic-gate */ 3400Sstevel@tonic-gate if (le->lfu_rotate_versions <= 0) 3410Sstevel@tonic-gate (void) unlink(new_name); 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate } else { 3440Sstevel@tonic-gate fprintf(stderr, 3450Sstevel@tonic-gate gettext("During rotate, couldn't open log file %s: %s\n"), 3460Sstevel@tonic-gate old_name, error_message(errno)); 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * Put it back. 3490Sstevel@tonic-gate */ 3500Sstevel@tonic-gate (void) rename(new_name, old_name); 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate free(name_buf1); 3530Sstevel@tonic-gate free(name_buf2); 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate } 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate /* 3580Sstevel@tonic-gate * klog_com_err_proc() - Handle com_err(3) messages as specified by the 3590Sstevel@tonic-gate * profile. 3600Sstevel@tonic-gate */ 3616426Smp153739 static krb5_context err_context; 3620Sstevel@tonic-gate static void 363*7934SMark.Phalan@Sun.COM klog_com_err_proc(const char *whoami, long code, const char *format, va_list ap) 3640Sstevel@tonic-gate { 3650Sstevel@tonic-gate char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE]; 3660Sstevel@tonic-gate int lindex; 367*7934SMark.Phalan@Sun.COM const char *actual_format; 368*7934SMark.Phalan@Sun.COM #ifdef HAVE_SYSLOG 3690Sstevel@tonic-gate int log_pri = -1; 370*7934SMark.Phalan@Sun.COM #endif /* HAVE_SYSLOG */ 3710Sstevel@tonic-gate char *cp; 3720Sstevel@tonic-gate char *syslogp; 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate /* Make the header */ 3750Sstevel@tonic-gate sprintf(outbuf, "%s: ", whoami); 3760Sstevel@tonic-gate /* 3770Sstevel@tonic-gate * Squirrel away address after header for syslog since syslog makes 3780Sstevel@tonic-gate * a header 3790Sstevel@tonic-gate */ 3800Sstevel@tonic-gate syslogp = &outbuf[strlen(outbuf)]; 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate /* If reporting an error message, separate it. */ 3830Sstevel@tonic-gate if (code) { 384*7934SMark.Phalan@Sun.COM /* Solaris Kerberos */ 3856426Smp153739 const char *emsg; 3860Sstevel@tonic-gate outbuf[sizeof(outbuf) - 1] = '\0'; 3873998Ssemery 3886426Smp153739 emsg = krb5_get_error_message (err_context, code); 3896426Smp153739 strncat(outbuf, emsg, sizeof(outbuf) - 1 - strlen(outbuf)); 390*7934SMark.Phalan@Sun.COM strncat(outbuf, " - ", sizeof(outbuf) - 1 - strlen(outbuf)); 3916426Smp153739 krb5_free_error_message(err_context, emsg); 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate cp = &outbuf[strlen(outbuf)]; 3940Sstevel@tonic-gate 395*7934SMark.Phalan@Sun.COM actual_format = format; 396*7934SMark.Phalan@Sun.COM #ifdef HAVE_SYSLOG 3970Sstevel@tonic-gate /* 3980Sstevel@tonic-gate * This is an unpleasant hack. If the first character is less than 3990Sstevel@tonic-gate * 8, then we assume that it is a priority. 4000Sstevel@tonic-gate * 4010Sstevel@tonic-gate * Since it is not guaranteed that there is a direct mapping between 4020Sstevel@tonic-gate * syslog priorities (e.g. Ultrix and old BSD), we resort to this 4030Sstevel@tonic-gate * intermediate representation. 4040Sstevel@tonic-gate */ 4050Sstevel@tonic-gate if ((((unsigned char) *format) > 0) && (((unsigned char) *format) <= 8)) { 406*7934SMark.Phalan@Sun.COM actual_format = (format + 1); 4070Sstevel@tonic-gate switch ((unsigned char) *format) { 408*7934SMark.Phalan@Sun.COM #ifdef LOG_EMERG 4090Sstevel@tonic-gate case 1: 4100Sstevel@tonic-gate log_pri = LOG_EMERG; 4110Sstevel@tonic-gate break; 412*7934SMark.Phalan@Sun.COM #endif /* LOG_EMERG */ 413*7934SMark.Phalan@Sun.COM #ifdef LOG_ALERT 4140Sstevel@tonic-gate case 2: 4150Sstevel@tonic-gate log_pri = LOG_ALERT; 4160Sstevel@tonic-gate break; 417*7934SMark.Phalan@Sun.COM #endif /* LOG_ALERT */ 418*7934SMark.Phalan@Sun.COM #ifdef LOG_CRIT 4190Sstevel@tonic-gate case 3: 4200Sstevel@tonic-gate log_pri = LOG_CRIT; 4210Sstevel@tonic-gate break; 422*7934SMark.Phalan@Sun.COM #endif /* LOG_CRIT */ 4230Sstevel@tonic-gate default: 4240Sstevel@tonic-gate case 4: 4250Sstevel@tonic-gate log_pri = LOG_ERR; 4260Sstevel@tonic-gate break; 427*7934SMark.Phalan@Sun.COM #ifdef LOG_WARNING 4280Sstevel@tonic-gate case 5: 4290Sstevel@tonic-gate log_pri = LOG_WARNING; 4300Sstevel@tonic-gate break; 431*7934SMark.Phalan@Sun.COM #endif /* LOG_WARNING */ 432*7934SMark.Phalan@Sun.COM #ifdef LOG_NOTICE 4330Sstevel@tonic-gate case 6: 4340Sstevel@tonic-gate log_pri = LOG_NOTICE; 4350Sstevel@tonic-gate break; 436*7934SMark.Phalan@Sun.COM #endif /* LOG_NOTICE */ 437*7934SMark.Phalan@Sun.COM #ifdef LOG_INFO 4380Sstevel@tonic-gate case 7: 4390Sstevel@tonic-gate log_pri = LOG_INFO; 4400Sstevel@tonic-gate break; 441*7934SMark.Phalan@Sun.COM #endif /* LOG_INFO */ 442*7934SMark.Phalan@Sun.COM #ifdef LOG_DEBUG 4430Sstevel@tonic-gate case 8: 4440Sstevel@tonic-gate log_pri = LOG_DEBUG; 4450Sstevel@tonic-gate break; 446*7934SMark.Phalan@Sun.COM #endif /* LOG_DEBUG */ 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate } 449*7934SMark.Phalan@Sun.COM #endif /* HAVE_SYSLOG */ 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate /* Now format the actual message */ 452*7934SMark.Phalan@Sun.COM #if HAVE_VSNPRINTF 453*7934SMark.Phalan@Sun.COM vsnprintf(cp, sizeof(outbuf) - (cp - outbuf), actual_format, ap); 454*7934SMark.Phalan@Sun.COM #elif HAVE_VSPRINTF 455*7934SMark.Phalan@Sun.COM vsprintf(cp, actual_format, ap); 456*7934SMark.Phalan@Sun.COM #else /* HAVE_VSPRINTF */ 457*7934SMark.Phalan@Sun.COM sprintf(cp, actual_format, ((int *) ap)[0], ((int *) ap)[1], 458*7934SMark.Phalan@Sun.COM ((int *) ap)[2], ((int *) ap)[3], 459*7934SMark.Phalan@Sun.COM ((int *) ap)[4], ((int *) ap)[5]); 460*7934SMark.Phalan@Sun.COM #endif /* HAVE_VSPRINTF */ 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* 4630Sstevel@tonic-gate * Now that we have the message formatted, perform the output to each 4640Sstevel@tonic-gate * logging specification. 4650Sstevel@tonic-gate */ 4660Sstevel@tonic-gate for (lindex = 0; lindex < log_control.log_nentries; lindex++) { 4670Sstevel@tonic-gate switch (log_control.log_entries[lindex].log_type) { 4680Sstevel@tonic-gate case K_LOG_FILE: 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate klog_rotate(&log_control.log_entries[lindex]); 4710Sstevel@tonic-gate /*FALLTHRU*/ 4720Sstevel@tonic-gate case K_LOG_STDERR: 4730Sstevel@tonic-gate /* 4740Sstevel@tonic-gate * Files/standard error. 4750Sstevel@tonic-gate */ 4760Sstevel@tonic-gate if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n", 4770Sstevel@tonic-gate outbuf) < 0) { 4780Sstevel@tonic-gate /* Attempt to report error */ 4790Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LOG_FILE_ERR), whoami, 4800Sstevel@tonic-gate log_control.log_entries[lindex].lfu_fname); 4810Sstevel@tonic-gate } 4820Sstevel@tonic-gate else { 4830Sstevel@tonic-gate fflush(log_control.log_entries[lindex].lfu_filep); 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate break; 4860Sstevel@tonic-gate case K_LOG_CONSOLE: 4870Sstevel@tonic-gate case K_LOG_DEVICE: 4880Sstevel@tonic-gate /* 4890Sstevel@tonic-gate * Devices (may need special handling) 4900Sstevel@tonic-gate */ 4910Sstevel@tonic-gate if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep, 4920Sstevel@tonic-gate outbuf) < 0) { 4930Sstevel@tonic-gate /* Attempt to report error */ 4940Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LOG_DEVICE_ERR), whoami, 4950Sstevel@tonic-gate log_control.log_entries[lindex].ldu_devname); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate break; 498*7934SMark.Phalan@Sun.COM #ifdef HAVE_SYSLOG 4990Sstevel@tonic-gate case K_LOG_SYSLOG: 5000Sstevel@tonic-gate /* 5010Sstevel@tonic-gate * System log. 5020Sstevel@tonic-gate */ 5030Sstevel@tonic-gate /* 5040Sstevel@tonic-gate * If we have specified a priority through our hackery, then 5050Sstevel@tonic-gate * use it, otherwise use the default. 5060Sstevel@tonic-gate */ 5070Sstevel@tonic-gate if (log_pri >= 0) 5080Sstevel@tonic-gate log_pri |= log_control.log_entries[lindex].lsu_facility; 5090Sstevel@tonic-gate else 5100Sstevel@tonic-gate log_pri = log_control.log_entries[lindex].lsu_facility | 5110Sstevel@tonic-gate log_control.log_entries[lindex].lsu_severity; 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate /* Log the message with our header trimmed off */ 5140Sstevel@tonic-gate syslog(log_pri, "%s", syslogp); 5150Sstevel@tonic-gate break; 516*7934SMark.Phalan@Sun.COM #endif /* HAVE_SYSLOG */ 5170Sstevel@tonic-gate default: 5180Sstevel@tonic-gate break; 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate } 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate /* 5240Sstevel@tonic-gate * krb5_klog_init() - Initialize logging. 5250Sstevel@tonic-gate * 5260Sstevel@tonic-gate * This routine parses the syntax described above to specify destinations for 5270Sstevel@tonic-gate * com_err(3) or krb5_klog_syslog() messages generated by the caller. 5280Sstevel@tonic-gate * 5290Sstevel@tonic-gate * Parameters: 5300Sstevel@tonic-gate * kcontext - Kerberos context. 5310Sstevel@tonic-gate * ename - Entity name as it is to appear in the profile. 5320Sstevel@tonic-gate * whoami - Entity name as it is to appear in error output. 5330Sstevel@tonic-gate * do_com_err - Take over com_err(3) processing. 5340Sstevel@tonic-gate * 5350Sstevel@tonic-gate * Implicit inputs: 5360Sstevel@tonic-gate * stderr - This is where STDERR output goes. 5370Sstevel@tonic-gate * 5380Sstevel@tonic-gate * Implicit outputs: 5390Sstevel@tonic-gate * log_nentries - Number of log entries, both valid and invalid. 5400Sstevel@tonic-gate * log_control - List of entries (log_nentries long) which contains 5410Sstevel@tonic-gate * data for klog_com_err_proc() to use to determine 5420Sstevel@tonic-gate * where/how to send output. 5430Sstevel@tonic-gate */ 5440Sstevel@tonic-gate krb5_error_code 545*7934SMark.Phalan@Sun.COM krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err) 5460Sstevel@tonic-gate { 5470Sstevel@tonic-gate const char *logging_profent[3]; 5480Sstevel@tonic-gate const char *logging_defent[3]; 5490Sstevel@tonic-gate char **logging_specs; 5500Sstevel@tonic-gate int i, ngood; 5510Sstevel@tonic-gate char *cp, *cp2; 552*7934SMark.Phalan@Sun.COM char savec = '\0'; 5530Sstevel@tonic-gate int error; 5540Sstevel@tonic-gate int do_openlog, log_facility; 5550Sstevel@tonic-gate FILE *f; 5560Sstevel@tonic-gate mode_t old_umask; 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate /* Initialize */ 5590Sstevel@tonic-gate do_openlog = 0; 5600Sstevel@tonic-gate log_facility = 0; 5610Sstevel@tonic-gate 5626426Smp153739 err_context = kcontext; 5636426Smp153739 5640Sstevel@tonic-gate /* 5650Sstevel@tonic-gate * Look up [logging]-><ename> in the profile. If that doesn't 5660Sstevel@tonic-gate * succeed, then look for [logging]->default. 5670Sstevel@tonic-gate */ 5680Sstevel@tonic-gate logging_profent[0] = "logging"; 5690Sstevel@tonic-gate logging_profent[1] = ename; 5700Sstevel@tonic-gate logging_profent[2] = (char *) NULL; 5710Sstevel@tonic-gate logging_defent[0] = "logging"; 5720Sstevel@tonic-gate logging_defent[1] = "default"; 5730Sstevel@tonic-gate logging_defent[2] = (char *) NULL; 5740Sstevel@tonic-gate logging_specs = (char **) NULL; 5750Sstevel@tonic-gate ngood = 0; 5760Sstevel@tonic-gate log_control.log_nentries = 0; 5770Sstevel@tonic-gate if (!profile_get_values(kcontext->profile, 5780Sstevel@tonic-gate logging_profent, 5790Sstevel@tonic-gate &logging_specs) || 5800Sstevel@tonic-gate !profile_get_values(kcontext->profile, 5810Sstevel@tonic-gate logging_defent, 5820Sstevel@tonic-gate &logging_specs)) { 5830Sstevel@tonic-gate /* 5840Sstevel@tonic-gate * We have a match, so we first count the number of elements 5850Sstevel@tonic-gate */ 5860Sstevel@tonic-gate for (log_control.log_nentries = 0; 5870Sstevel@tonic-gate logging_specs[log_control.log_nentries]; 5880Sstevel@tonic-gate log_control.log_nentries++); 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate /* 5910Sstevel@tonic-gate * Now allocate our structure. 5920Sstevel@tonic-gate */ 5930Sstevel@tonic-gate log_control.log_entries = (struct log_entry *) 5940Sstevel@tonic-gate malloc(log_control.log_nentries * sizeof(struct log_entry)); 5950Sstevel@tonic-gate if (log_control.log_entries) { 5960Sstevel@tonic-gate /* 5970Sstevel@tonic-gate * Scan through the list. 5980Sstevel@tonic-gate */ 5990Sstevel@tonic-gate for (i=0; i<log_control.log_nentries; i++) { 6000Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_NONE; 6010Sstevel@tonic-gate log_control.log_entries[i].log_2free = logging_specs[i]; 6020Sstevel@tonic-gate /* 6030Sstevel@tonic-gate * The format is: 6040Sstevel@tonic-gate * <whitespace><data><whitespace> 6050Sstevel@tonic-gate * so, trim off the leading and trailing whitespace here. 6060Sstevel@tonic-gate */ 607*7934SMark.Phalan@Sun.COM for (cp = logging_specs[i]; isspace((int) *cp); cp++); 6080Sstevel@tonic-gate for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1]; 609*7934SMark.Phalan@Sun.COM isspace((int) *cp2); cp2--); 6100Sstevel@tonic-gate cp2++; 6110Sstevel@tonic-gate *cp2 = '\0'; 6120Sstevel@tonic-gate /* 6130Sstevel@tonic-gate * Is this a file? 6140Sstevel@tonic-gate */ 6150Sstevel@tonic-gate if (!strncasecmp(cp, "FILE", 4)) { 6160Sstevel@tonic-gate /* 6170Sstevel@tonic-gate * Check for append/overwrite, then open the file. 6180Sstevel@tonic-gate */ 6190Sstevel@tonic-gate if (cp[4] == ':' || cp[4] == '=') { 6200Sstevel@tonic-gate log_control.log_entries[i].lfu_fopen_mode = 6211914Scasper (cp[4] == ':') ? "a+F" : "wF"; 6220Sstevel@tonic-gate old_umask = umask(077); 6230Sstevel@tonic-gate f = fopen(&cp[5], 6240Sstevel@tonic-gate log_control.log_entries[i].lfu_fopen_mode); 6250Sstevel@tonic-gate umask(old_umask); 6260Sstevel@tonic-gate if (f) { 6270Sstevel@tonic-gate char rotate_kw[128]; 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate log_control.log_entries[i].lfu_filep = f; 6300Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_FILE; 6310Sstevel@tonic-gate log_control.log_entries[i].lfu_fname = &cp[5]; 6320Sstevel@tonic-gate log_control.log_entries[i].lfu_rotate_period = 6330Sstevel@tonic-gate K_LOG_DEF_FILE_ROTATE_PERIOD; 6340Sstevel@tonic-gate log_control.log_entries[i].lfu_rotate_versions = 6350Sstevel@tonic-gate K_LOG_DEF_FILE_ROTATE_VERSIONS; 6360Sstevel@tonic-gate log_control.log_entries[i].lfu_last_rotated = 6370Sstevel@tonic-gate time(0); 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate /* 6400Sstevel@tonic-gate * Now parse for ename_"rotate" = { 6410Sstevel@tonic-gate * period = XXX 6420Sstevel@tonic-gate * versions = 10 6430Sstevel@tonic-gate * } 6440Sstevel@tonic-gate */ 6450Sstevel@tonic-gate if (strlen(ename) + strlen("_rotate") < 6460Sstevel@tonic-gate sizeof (rotate_kw)) { 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate char *time; 6490Sstevel@tonic-gate krb5_deltat dt; 6500Sstevel@tonic-gate int vers; 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate strcpy(rotate_kw, ename); 6530Sstevel@tonic-gate strcat(rotate_kw, "_rotate"); 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate if (!profile_get_string(kcontext->profile, 6560Sstevel@tonic-gate "logging", rotate_kw, "period", 6570Sstevel@tonic-gate NULL, &time)) { 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate if (time != NULL) { 6600Sstevel@tonic-gate if (!krb5_string_to_deltat(time, 6610Sstevel@tonic-gate &dt)) { 6620Sstevel@tonic-gate log_control.log_entries[i].lfu_rotate_period = 6630Sstevel@tonic-gate (time_t) dt; 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate free(time); 6660Sstevel@tonic-gate } 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate if (!profile_get_integer( 6700Sstevel@tonic-gate kcontext->profile, "logging", 6710Sstevel@tonic-gate rotate_kw, "versions", 6720Sstevel@tonic-gate K_LOG_DEF_FILE_ROTATE_VERSIONS, 6730Sstevel@tonic-gate &vers)) { 6740Sstevel@tonic-gate log_control.log_entries[i].lfu_rotate_versions = vers; 6750Sstevel@tonic-gate } 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate } 6780Sstevel@tonic-gate } else { 679*7934SMark.Phalan@Sun.COM fprintf(stderr, gettext("Couldn't open log file %s: %s\n"), 6800Sstevel@tonic-gate &cp[5], error_message(errno)); 6810Sstevel@tonic-gate continue; 6820Sstevel@tonic-gate } 6830Sstevel@tonic-gate } 6840Sstevel@tonic-gate } 685*7934SMark.Phalan@Sun.COM #ifdef HAVE_SYSLOG 6860Sstevel@tonic-gate /* 6870Sstevel@tonic-gate * Is this a syslog? 6880Sstevel@tonic-gate */ 6890Sstevel@tonic-gate else if (!strncasecmp(cp, "SYSLOG", 6)) { 6900Sstevel@tonic-gate error = 0; 6910Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_AUTH; 6920Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = LOG_ERR; 6930Sstevel@tonic-gate /* 6940Sstevel@tonic-gate * Is there a severify specified? 6950Sstevel@tonic-gate */ 6960Sstevel@tonic-gate if (cp[6] == ':') { 6970Sstevel@tonic-gate /* 6980Sstevel@tonic-gate * Find the end of the severity. 6990Sstevel@tonic-gate */ 700*7934SMark.Phalan@Sun.COM cp2 = strchr(&cp[7], ':'); 701*7934SMark.Phalan@Sun.COM if (cp2) { 7020Sstevel@tonic-gate savec = *cp2; 7030Sstevel@tonic-gate *cp2 = '\0'; 7040Sstevel@tonic-gate cp2++; 7050Sstevel@tonic-gate } 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate /* 7080Sstevel@tonic-gate * Match a severity. 7090Sstevel@tonic-gate */ 7100Sstevel@tonic-gate if (!strcasecmp(&cp[7], "ERR")) { 7110Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = LOG_ERR; 7120Sstevel@tonic-gate } 713*7934SMark.Phalan@Sun.COM #ifdef LOG_EMERG 7140Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "EMERG")) { 7150Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 7160Sstevel@tonic-gate LOG_EMERG; 7170Sstevel@tonic-gate } 718*7934SMark.Phalan@Sun.COM #endif /* LOG_EMERG */ 719*7934SMark.Phalan@Sun.COM #ifdef LOG_ALERT 7200Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "ALERT")) { 7210Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 7220Sstevel@tonic-gate LOG_ALERT; 7230Sstevel@tonic-gate } 724*7934SMark.Phalan@Sun.COM #endif /* LOG_ALERT */ 725*7934SMark.Phalan@Sun.COM #ifdef LOG_CRIT 7260Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "CRIT")) { 7270Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = LOG_CRIT; 7280Sstevel@tonic-gate } 729*7934SMark.Phalan@Sun.COM #endif /* LOG_CRIT */ 730*7934SMark.Phalan@Sun.COM #ifdef LOG_WARNING 7310Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "WARNING")) { 7320Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 7330Sstevel@tonic-gate LOG_WARNING; 7340Sstevel@tonic-gate } 735*7934SMark.Phalan@Sun.COM #endif /* LOG_WARNING */ 736*7934SMark.Phalan@Sun.COM #ifdef LOG_NOTICE 7370Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "NOTICE")) { 7380Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 7390Sstevel@tonic-gate LOG_NOTICE; 7400Sstevel@tonic-gate } 741*7934SMark.Phalan@Sun.COM #endif /* LOG_NOTICE */ 742*7934SMark.Phalan@Sun.COM #ifdef LOG_INFO 7430Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "INFO")) { 7440Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = LOG_INFO; 7450Sstevel@tonic-gate } 746*7934SMark.Phalan@Sun.COM #endif /* LOG_INFO */ 747*7934SMark.Phalan@Sun.COM #ifdef LOG_DEBUG 7480Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "DEBUG")) { 7490Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 7500Sstevel@tonic-gate LOG_DEBUG; 7510Sstevel@tonic-gate } 752*7934SMark.Phalan@Sun.COM #endif /* LOG_DEBUG */ 7530Sstevel@tonic-gate else 7540Sstevel@tonic-gate error = 1; 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate /* 7570Sstevel@tonic-gate * If there is a facility present, then parse that. 7580Sstevel@tonic-gate */ 7590Sstevel@tonic-gate if (cp2) { 7600Sstevel@tonic-gate if (!strcasecmp(cp2, "AUTH")) { 7610Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_AUTH; 7620Sstevel@tonic-gate } 7630Sstevel@tonic-gate else if (!strcasecmp(cp2, "KERN")) { 7640Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_KERN; 7650Sstevel@tonic-gate } 7660Sstevel@tonic-gate else if (!strcasecmp(cp2, "USER")) { 7670Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_USER; 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate else if (!strcasecmp(cp2, "MAIL")) { 7700Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_MAIL; 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate else if (!strcasecmp(cp2, "DAEMON")) { 7730Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_DAEMON; 7740Sstevel@tonic-gate } 7750Sstevel@tonic-gate else if (!strcasecmp(cp2, "LPR")) { 7760Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LPR; 7770Sstevel@tonic-gate } 7780Sstevel@tonic-gate else if (!strcasecmp(cp2, "NEWS")) { 7790Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_NEWS; 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate else if (!strcasecmp(cp2, "UUCP")) { 7820Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_UUCP; 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate else if (!strcasecmp(cp2, "CRON")) { 7850Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_CRON; 7860Sstevel@tonic-gate } 7870Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL0")) { 7880Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL0; 7890Sstevel@tonic-gate } 7900Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL1")) { 7910Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL1; 7920Sstevel@tonic-gate } 7930Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL2")) { 7940Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL2; 7950Sstevel@tonic-gate } 7960Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL3")) { 7970Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL3; 7980Sstevel@tonic-gate } 7990Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL4")) { 8000Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL4; 8010Sstevel@tonic-gate } 8020Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL5")) { 8030Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL5; 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL6")) { 8060Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL6; 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL7")) { 8090Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL7; 8100Sstevel@tonic-gate } 8110Sstevel@tonic-gate cp2--; 8120Sstevel@tonic-gate *cp2 = savec; 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate } 8150Sstevel@tonic-gate if (!error) { 8160Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_SYSLOG; 8170Sstevel@tonic-gate do_openlog = 1; 8180Sstevel@tonic-gate log_facility = log_control.log_entries[i].lsu_facility; 8190Sstevel@tonic-gate } 8200Sstevel@tonic-gate } 821*7934SMark.Phalan@Sun.COM #endif /* HAVE_SYSLOG */ 8220Sstevel@tonic-gate /* 8230Sstevel@tonic-gate * Is this a standard error specification? 8240Sstevel@tonic-gate */ 8250Sstevel@tonic-gate else if (!strcasecmp(cp, "STDERR")) { 826*7934SMark.Phalan@Sun.COM log_control.log_entries[i].lfu_filep = 827*7934SMark.Phalan@Sun.COM fdopen(fileno(stderr), "a+F"); 828*7934SMark.Phalan@Sun.COM if (log_control.log_entries[i].lfu_filep) { 8290Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_STDERR; 8300Sstevel@tonic-gate log_control.log_entries[i].lfu_fname = 8310Sstevel@tonic-gate "standard error"; 8320Sstevel@tonic-gate } 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate /* 8350Sstevel@tonic-gate * Is this a specification of the console? 8360Sstevel@tonic-gate */ 8370Sstevel@tonic-gate else if (!strcasecmp(cp, "CONSOLE")) { 838*7934SMark.Phalan@Sun.COM log_control.log_entries[i].ldu_filep = 839*7934SMark.Phalan@Sun.COM CONSOLE_OPEN("a+F"); 840*7934SMark.Phalan@Sun.COM if (log_control.log_entries[i].ldu_filep) { 8410Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_CONSOLE; 8420Sstevel@tonic-gate log_control.log_entries[i].ldu_devname = "console"; 8430Sstevel@tonic-gate } 8440Sstevel@tonic-gate } 8450Sstevel@tonic-gate /* 8460Sstevel@tonic-gate * Is this a specification of a device? 8470Sstevel@tonic-gate */ 8480Sstevel@tonic-gate else if (!strncasecmp(cp, "DEVICE", 6)) { 8490Sstevel@tonic-gate /* 8500Sstevel@tonic-gate * We handle devices very similarly to files. 8510Sstevel@tonic-gate */ 8520Sstevel@tonic-gate if (cp[6] == '=') { 853*7934SMark.Phalan@Sun.COM log_control.log_entries[i].ldu_filep = 854*7934SMark.Phalan@Sun.COM DEVICE_OPEN(&cp[7], "wF"); 855*7934SMark.Phalan@Sun.COM if (log_control.log_entries[i].ldu_filep) { 8560Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_DEVICE; 8570Sstevel@tonic-gate log_control.log_entries[i].ldu_devname = &cp[7]; 8580Sstevel@tonic-gate } 8590Sstevel@tonic-gate } 8600Sstevel@tonic-gate } 8610Sstevel@tonic-gate /* 8620Sstevel@tonic-gate * See if we successfully parsed this specification. 8630Sstevel@tonic-gate */ 8640Sstevel@tonic-gate if (log_control.log_entries[i].log_type == K_LOG_NONE) { 8650Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LSPEC_PARSE_ERR_1), whoami, cp); 8660Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LSPEC_PARSE_ERR_2), whoami); 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate else 8690Sstevel@tonic-gate ngood++; 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate } 8720Sstevel@tonic-gate /* 8730Sstevel@tonic-gate * If we didn't find anything, then free our lists. 8740Sstevel@tonic-gate */ 8750Sstevel@tonic-gate if (ngood == 0) { 8760Sstevel@tonic-gate for (i=0; i<log_control.log_nentries; i++) 8770Sstevel@tonic-gate free(logging_specs[i]); 8780Sstevel@tonic-gate } 8790Sstevel@tonic-gate free(logging_specs); 8800Sstevel@tonic-gate } 8810Sstevel@tonic-gate /* 8820Sstevel@tonic-gate * If we didn't find anything, go for the default which is to log to 8830Sstevel@tonic-gate * the system log. 8840Sstevel@tonic-gate */ 8850Sstevel@tonic-gate if (ngood == 0) { 8860Sstevel@tonic-gate if (log_control.log_entries) 8870Sstevel@tonic-gate free(log_control.log_entries); 8880Sstevel@tonic-gate log_control.log_entries = &def_log_entry; 8890Sstevel@tonic-gate log_control.log_entries->log_type = K_LOG_SYSLOG; 8900Sstevel@tonic-gate log_control.log_entries->log_2free = (krb5_pointer) NULL; 8910Sstevel@tonic-gate log_facility = log_control.log_entries->lsu_facility = LOG_AUTH; 8920Sstevel@tonic-gate log_control.log_entries->lsu_severity = LOG_ERR; 8930Sstevel@tonic-gate do_openlog = 1; 8940Sstevel@tonic-gate log_control.log_nentries = 1; 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate if (log_control.log_nentries) { 897*7934SMark.Phalan@Sun.COM log_control.log_whoami = (char *) malloc(strlen(whoami)+1); 898*7934SMark.Phalan@Sun.COM if (log_control.log_whoami) 8990Sstevel@tonic-gate strcpy(log_control.log_whoami, whoami); 900*7934SMark.Phalan@Sun.COM 901*7934SMark.Phalan@Sun.COM log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1); 902*7934SMark.Phalan@Sun.COM if (log_control.log_hostname) { 9030Sstevel@tonic-gate gethostname(log_control.log_hostname, MAXHOSTNAMELEN); 904*7934SMark.Phalan@Sun.COM log_control.log_hostname[MAXHOSTNAMELEN] = '\0'; 905*7934SMark.Phalan@Sun.COM } 906*7934SMark.Phalan@Sun.COM #ifdef HAVE_OPENLOG 9070Sstevel@tonic-gate if (do_openlog) { 9080Sstevel@tonic-gate openlog(whoami, LOG_NDELAY|LOG_PID, log_facility); 9090Sstevel@tonic-gate log_control.log_opened = 1; 9100Sstevel@tonic-gate } 911*7934SMark.Phalan@Sun.COM #endif /* HAVE_OPENLOG */ 9120Sstevel@tonic-gate if (do_com_err) 9130Sstevel@tonic-gate (void) set_com_err_hook(klog_com_err_proc); 9140Sstevel@tonic-gate } 9150Sstevel@tonic-gate return((log_control.log_nentries) ? 0 : ENOENT); 9160Sstevel@tonic-gate } 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate /* 9190Sstevel@tonic-gate * krb5_klog_close() - Close the logging context and free all data. 9200Sstevel@tonic-gate */ 9210Sstevel@tonic-gate void 922*7934SMark.Phalan@Sun.COM krb5_klog_close(krb5_context kcontext) 9230Sstevel@tonic-gate { 9240Sstevel@tonic-gate int lindex; 9250Sstevel@tonic-gate (void) reset_com_err_hook(); 9260Sstevel@tonic-gate for (lindex = 0; lindex < log_control.log_nentries; lindex++) { 9270Sstevel@tonic-gate switch (log_control.log_entries[lindex].log_type) { 9280Sstevel@tonic-gate case K_LOG_FILE: 9290Sstevel@tonic-gate case K_LOG_STDERR: 9300Sstevel@tonic-gate /* 9310Sstevel@tonic-gate * Files/standard error. 9320Sstevel@tonic-gate */ 9330Sstevel@tonic-gate fclose(log_control.log_entries[lindex].lfu_filep); 9340Sstevel@tonic-gate break; 9350Sstevel@tonic-gate case K_LOG_CONSOLE: 9360Sstevel@tonic-gate case K_LOG_DEVICE: 9370Sstevel@tonic-gate /* 9380Sstevel@tonic-gate * Devices (may need special handling) 9390Sstevel@tonic-gate */ 9400Sstevel@tonic-gate DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep); 9410Sstevel@tonic-gate break; 942*7934SMark.Phalan@Sun.COM #ifdef HAVE_SYSLOG 9430Sstevel@tonic-gate case K_LOG_SYSLOG: 9440Sstevel@tonic-gate /* 9450Sstevel@tonic-gate * System log. 9460Sstevel@tonic-gate */ 9470Sstevel@tonic-gate break; 948*7934SMark.Phalan@Sun.COM #endif /* HAVE_SYSLOG */ 9490Sstevel@tonic-gate default: 9500Sstevel@tonic-gate break; 9510Sstevel@tonic-gate } 9520Sstevel@tonic-gate if (log_control.log_entries[lindex].log_2free) 9530Sstevel@tonic-gate free(log_control.log_entries[lindex].log_2free); 9540Sstevel@tonic-gate } 9550Sstevel@tonic-gate if (log_control.log_entries != &def_log_entry) 9560Sstevel@tonic-gate free(log_control.log_entries); 9570Sstevel@tonic-gate log_control.log_entries = (struct log_entry *) NULL; 9580Sstevel@tonic-gate log_control.log_nentries = 0; 9590Sstevel@tonic-gate if (log_control.log_whoami) 9600Sstevel@tonic-gate free(log_control.log_whoami); 9610Sstevel@tonic-gate log_control.log_whoami = (char *) NULL; 9620Sstevel@tonic-gate if (log_control.log_hostname) 9630Sstevel@tonic-gate free(log_control.log_hostname); 9640Sstevel@tonic-gate log_control.log_hostname = (char *) NULL; 965*7934SMark.Phalan@Sun.COM #ifdef HAVE_CLOSELOG 9660Sstevel@tonic-gate if (log_control.log_opened) 9670Sstevel@tonic-gate closelog(); 968*7934SMark.Phalan@Sun.COM #endif /* HAVE_CLOSELOG */ 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate 9710Sstevel@tonic-gate /* 9720Sstevel@tonic-gate * severity2string() - Convert a severity to a string. 9730Sstevel@tonic-gate */ 974*7934SMark.Phalan@Sun.COM static const char * 975*7934SMark.Phalan@Sun.COM severity2string(int severity) 9760Sstevel@tonic-gate { 9770Sstevel@tonic-gate int s; 9780Sstevel@tonic-gate const char *ss; 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate s = severity & LOG_PRIMASK; 9810Sstevel@tonic-gate ss = krb5_log_error_table(LOG_UFO_STRING); 9820Sstevel@tonic-gate switch (s) { 983*7934SMark.Phalan@Sun.COM #ifdef LOG_EMERG 9840Sstevel@tonic-gate case LOG_EMERG: 9850Sstevel@tonic-gate ss = krb5_log_error_table(LOG_EMERG_STRING); 9860Sstevel@tonic-gate break; 987*7934SMark.Phalan@Sun.COM #endif /* LOG_EMERG */ 988*7934SMark.Phalan@Sun.COM #ifdef LOG_ALERT 9890Sstevel@tonic-gate case LOG_ALERT: 9900Sstevel@tonic-gate ss = krb5_log_error_table(LOG_ALERT_STRING); 9910Sstevel@tonic-gate break; 992*7934SMark.Phalan@Sun.COM #endif /* LOG_ALERT */ 993*7934SMark.Phalan@Sun.COM #ifdef LOG_CRIT 9940Sstevel@tonic-gate case LOG_CRIT: 9950Sstevel@tonic-gate ss = krb5_log_error_table(LOG_CRIT_STRING); 9960Sstevel@tonic-gate break; 997*7934SMark.Phalan@Sun.COM #endif /* LOG_CRIT */ 9980Sstevel@tonic-gate case LOG_ERR: 9990Sstevel@tonic-gate ss = krb5_log_error_table(LOG_ERR_STRING); 10000Sstevel@tonic-gate break; 1001*7934SMark.Phalan@Sun.COM #ifdef LOG_WARNING 10020Sstevel@tonic-gate case LOG_WARNING: 10030Sstevel@tonic-gate ss = krb5_log_error_table(LOG_WARNING_STRING); 10040Sstevel@tonic-gate break; 1005*7934SMark.Phalan@Sun.COM #endif /* LOG_WARNING */ 1006*7934SMark.Phalan@Sun.COM #ifdef LOG_NOTICE 10070Sstevel@tonic-gate case LOG_NOTICE: 10080Sstevel@tonic-gate ss = krb5_log_error_table(LOG_NOTICE_STRING); 10090Sstevel@tonic-gate break; 1010*7934SMark.Phalan@Sun.COM #endif /* LOG_NOTICE */ 1011*7934SMark.Phalan@Sun.COM #ifdef LOG_INFO 10120Sstevel@tonic-gate case LOG_INFO: 10130Sstevel@tonic-gate ss = krb5_log_error_table(LOG_INFO_STRING); 10140Sstevel@tonic-gate break; 1015*7934SMark.Phalan@Sun.COM #endif /* LOG_INFO */ 1016*7934SMark.Phalan@Sun.COM #ifdef LOG_DEBUG 10170Sstevel@tonic-gate case LOG_DEBUG: 10180Sstevel@tonic-gate ss = krb5_log_error_table(LOG_DEBUG_STRING); 10190Sstevel@tonic-gate break; 1020*7934SMark.Phalan@Sun.COM #endif /* LOG_DEBUG */ 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate return((char *) ss); 10230Sstevel@tonic-gate } 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate /* 10260Sstevel@tonic-gate * krb5_klog_syslog() - Simulate the calling sequence of syslog(3), while 10270Sstevel@tonic-gate * also performing the logging redirection as specified 10280Sstevel@tonic-gate * by krb5_klog_init(). 10290Sstevel@tonic-gate */ 10300Sstevel@tonic-gate static int 1031*7934SMark.Phalan@Sun.COM klog_vsyslog(int priority, const char *format, va_list arglist) 10320Sstevel@tonic-gate { 10330Sstevel@tonic-gate char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE]; 10340Sstevel@tonic-gate int lindex; 10350Sstevel@tonic-gate char *syslogp; 10360Sstevel@tonic-gate char *cp; 10370Sstevel@tonic-gate time_t now; 1038*7934SMark.Phalan@Sun.COM #ifdef HAVE_STRFTIME 10390Sstevel@tonic-gate size_t soff; 1040*7934SMark.Phalan@Sun.COM #endif /* HAVE_STRFTIME */ 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate /* 10430Sstevel@tonic-gate * Format a syslog-esque message of the format: 10440Sstevel@tonic-gate * 10450Sstevel@tonic-gate * (verbose form) 10460Sstevel@tonic-gate * <date> <hostname> <id>[<pid>](<priority>): <message> 10470Sstevel@tonic-gate * 10480Sstevel@tonic-gate * (short form) 10490Sstevel@tonic-gate * <date> <message> 10500Sstevel@tonic-gate */ 10510Sstevel@tonic-gate cp = outbuf; 10520Sstevel@tonic-gate (void) time(&now); 1053*7934SMark.Phalan@Sun.COM #ifdef HAVE_STRFTIME 10540Sstevel@tonic-gate /* 10550Sstevel@tonic-gate * Format the date: mon dd hh:mm:ss 10560Sstevel@tonic-gate */ 10570Sstevel@tonic-gate soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", localtime(&now)); 10580Sstevel@tonic-gate if (soff > 0) 10590Sstevel@tonic-gate cp += soff; 10600Sstevel@tonic-gate else 10610Sstevel@tonic-gate return(-1); 1062*7934SMark.Phalan@Sun.COM #else /* HAVE_STRFTIME */ 1063*7934SMark.Phalan@Sun.COM /* 1064*7934SMark.Phalan@Sun.COM * Format the date: 1065*7934SMark.Phalan@Sun.COM * We ASSUME here that the output of ctime is of the format: 1066*7934SMark.Phalan@Sun.COM * dow mon dd hh:mm:ss tzs yyyy\n 1067*7934SMark.Phalan@Sun.COM * 012345678901234567890123456789 1068*7934SMark.Phalan@Sun.COM */ 1069*7934SMark.Phalan@Sun.COM strncpy(outbuf, ctime(&now) + 4, 15); 1070*7934SMark.Phalan@Sun.COM cp += 15; 1071*7934SMark.Phalan@Sun.COM #endif /* HAVE_STRFTIME */ 10720Sstevel@tonic-gate #ifdef VERBOSE_LOGS 10730Sstevel@tonic-gate sprintf(cp, " %s %s[%ld](%s): ", 10740Sstevel@tonic-gate log_control.log_hostname, log_control.log_whoami, (long) getpid(), 10750Sstevel@tonic-gate severity2string(priority)); 10760Sstevel@tonic-gate #else 10770Sstevel@tonic-gate sprintf(cp, " "); 10780Sstevel@tonic-gate #endif 10790Sstevel@tonic-gate syslogp = &outbuf[strlen(outbuf)]; 10800Sstevel@tonic-gate 10810Sstevel@tonic-gate /* Now format the actual message */ 1082*7934SMark.Phalan@Sun.COM #ifdef HAVE_VSNPRINTF 1083*7934SMark.Phalan@Sun.COM vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist); 1084*7934SMark.Phalan@Sun.COM #elif HAVE_VSPRINTF 1085*7934SMark.Phalan@Sun.COM vsprintf(syslogp, format, arglist); 1086*7934SMark.Phalan@Sun.COM #else /* HAVE_VSPRINTF */ 1087*7934SMark.Phalan@Sun.COM sprintf(syslogp, format, ((int *) arglist)[0], ((int *) arglist)[1], 1088*7934SMark.Phalan@Sun.COM ((int *) arglist)[2], ((int *) arglist)[3], 1089*7934SMark.Phalan@Sun.COM ((int *) arglist)[4], ((int *) arglist)[5]); 1090*7934SMark.Phalan@Sun.COM #endif /* HAVE_VSPRINTF */ 1091*7934SMark.Phalan@Sun.COM 1092*7934SMark.Phalan@Sun.COM /* 1093*7934SMark.Phalan@Sun.COM * If the user did not use krb5_klog_init() instead of dropping 1094*7934SMark.Phalan@Sun.COM * the request on the floor, syslog it - if it exists 1095*7934SMark.Phalan@Sun.COM */ 1096*7934SMark.Phalan@Sun.COM #ifdef HAVE_SYSLOG 1097*7934SMark.Phalan@Sun.COM if (log_control.log_nentries == 0) { 1098*7934SMark.Phalan@Sun.COM /* Log the message with our header trimmed off */ 1099*7934SMark.Phalan@Sun.COM syslog(priority, "%s", syslogp); 1100*7934SMark.Phalan@Sun.COM } 1101*7934SMark.Phalan@Sun.COM #endif 11020Sstevel@tonic-gate 11030Sstevel@tonic-gate /* 11040Sstevel@tonic-gate * Now that we have the message formatted, perform the output to each 11050Sstevel@tonic-gate * logging specification. 11060Sstevel@tonic-gate */ 11070Sstevel@tonic-gate for (lindex = 0; lindex < log_control.log_nentries; lindex++) { 11080Sstevel@tonic-gate switch (log_control.log_entries[lindex].log_type) { 11090Sstevel@tonic-gate case K_LOG_FILE: 11100Sstevel@tonic-gate 11110Sstevel@tonic-gate klog_rotate(&log_control.log_entries[lindex]); 11120Sstevel@tonic-gate /*FALLTHRU*/ 11130Sstevel@tonic-gate case K_LOG_STDERR: 11140Sstevel@tonic-gate /* 11150Sstevel@tonic-gate * Files/standard error. 11160Sstevel@tonic-gate */ 11170Sstevel@tonic-gate if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n", 11180Sstevel@tonic-gate outbuf) < 0) { 11190Sstevel@tonic-gate /* Attempt to report error */ 11200Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LOG_FILE_ERR), 11210Sstevel@tonic-gate log_control.log_whoami, 11220Sstevel@tonic-gate log_control.log_entries[lindex].lfu_fname); 11230Sstevel@tonic-gate } 11240Sstevel@tonic-gate else { 11250Sstevel@tonic-gate fflush(log_control.log_entries[lindex].lfu_filep); 11260Sstevel@tonic-gate } 11270Sstevel@tonic-gate break; 11280Sstevel@tonic-gate case K_LOG_CONSOLE: 11290Sstevel@tonic-gate case K_LOG_DEVICE: 11300Sstevel@tonic-gate /* 11310Sstevel@tonic-gate * Devices (may need special handling) 11320Sstevel@tonic-gate */ 11330Sstevel@tonic-gate if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep, 11340Sstevel@tonic-gate outbuf) < 0) { 11350Sstevel@tonic-gate /* Attempt to report error */ 11360Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LOG_DEVICE_ERR), 11370Sstevel@tonic-gate log_control.log_whoami, 11380Sstevel@tonic-gate log_control.log_entries[lindex].ldu_devname); 11390Sstevel@tonic-gate } 11400Sstevel@tonic-gate break; 1141*7934SMark.Phalan@Sun.COM #ifdef HAVE_SYSLOG 11420Sstevel@tonic-gate case K_LOG_SYSLOG: 11430Sstevel@tonic-gate /* 11440Sstevel@tonic-gate * System log. 11450Sstevel@tonic-gate */ 11460Sstevel@tonic-gate 11470Sstevel@tonic-gate /* Log the message with our header trimmed off */ 11480Sstevel@tonic-gate syslog(priority, "%s", syslogp); 11490Sstevel@tonic-gate break; 1150*7934SMark.Phalan@Sun.COM #endif /* HAVE_SYSLOG */ 11510Sstevel@tonic-gate default: 11520Sstevel@tonic-gate break; 11530Sstevel@tonic-gate } 11540Sstevel@tonic-gate } 11550Sstevel@tonic-gate return(0); 11560Sstevel@tonic-gate } 11570Sstevel@tonic-gate 11580Sstevel@tonic-gate int 11590Sstevel@tonic-gate krb5_klog_syslog(int priority, const char *format, ...) 11600Sstevel@tonic-gate { 11610Sstevel@tonic-gate int retval; 11620Sstevel@tonic-gate va_list pvar; 11630Sstevel@tonic-gate 11640Sstevel@tonic-gate va_start(pvar, format); 11650Sstevel@tonic-gate retval = klog_vsyslog(priority, format, pvar); 11660Sstevel@tonic-gate va_end(pvar); 11670Sstevel@tonic-gate return(retval); 11680Sstevel@tonic-gate } 11690Sstevel@tonic-gate 11700Sstevel@tonic-gate /* 11710Sstevel@tonic-gate * krb5_klog_reopen() - Close and reopen any open (non-syslog) log files. 11720Sstevel@tonic-gate * This function is called when a SIGHUP is received 11730Sstevel@tonic-gate * so that external log-archival utilities may 11740Sstevel@tonic-gate * alert the Kerberos daemons that they should get 11750Sstevel@tonic-gate * a new file descriptor for the give filename. 11760Sstevel@tonic-gate */ 11770Sstevel@tonic-gate void 1178*7934SMark.Phalan@Sun.COM krb5_klog_reopen(krb5_context kcontext) 11790Sstevel@tonic-gate { 11800Sstevel@tonic-gate int lindex; 11810Sstevel@tonic-gate FILE *f; 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate /* 11840Sstevel@tonic-gate * Only logs which are actually files need to be closed 11850Sstevel@tonic-gate * and reopened in response to a SIGHUP 11860Sstevel@tonic-gate */ 11870Sstevel@tonic-gate for (lindex = 0; lindex < log_control.log_nentries; lindex++) { 11880Sstevel@tonic-gate if (log_control.log_entries[lindex].log_type == K_LOG_FILE) { 11890Sstevel@tonic-gate fclose(log_control.log_entries[lindex].lfu_filep); 11900Sstevel@tonic-gate /* 11910Sstevel@tonic-gate * In case the old logfile did not get moved out of the 11920Sstevel@tonic-gate * way, open for append to prevent squashing the old logs. 11930Sstevel@tonic-gate */ 11941914Scasper f = fopen(log_control.log_entries[lindex].lfu_fname, "a+F"); 11950Sstevel@tonic-gate if (f) { 11960Sstevel@tonic-gate log_control.log_entries[lindex].lfu_filep = f; 11970Sstevel@tonic-gate } else { 11980Sstevel@tonic-gate fprintf(stderr, "Couldn't open log file %s: %s\n", 11990Sstevel@tonic-gate log_control.log_entries[lindex].lfu_fname, 12000Sstevel@tonic-gate error_message(errno)); 12010Sstevel@tonic-gate } 12020Sstevel@tonic-gate } 12030Sstevel@tonic-gate } 12040Sstevel@tonic-gate } 12056426Smp153739 12066426Smp153739 /* 12076426Smp153739 * Solaris Kerberos: 12086426Smp153739 * Switch the current context to the one supplied 12096426Smp153739 */ 12106426Smp153739 void krb5_klog_set_context(krb5_context context) { 12116426Smp153739 err_context = context; 12126426Smp153739 } 12136426Smp153739 12146426Smp153739 /* 12156426Smp153739 * Solaris Kerberos: 12166426Smp153739 * Return a string representation of "facility" 12176426Smp153739 */ 12186426Smp153739 static const char * facility2string(int facility) { 12196426Smp153739 switch (facility) { 12206426Smp153739 case (LOG_AUTH): 12216426Smp153739 return ("AUTH"); 12226426Smp153739 case (LOG_KERN): 12236426Smp153739 return ("KERN"); 12246426Smp153739 case (LOG_USER): 12256426Smp153739 return ("USER"); 12266426Smp153739 case (LOG_MAIL): 12276426Smp153739 return ("MAIL"); 12286426Smp153739 case (LOG_DAEMON): 12296426Smp153739 return ("DAEMON"); 12306426Smp153739 case (LOG_LPR): 12316426Smp153739 return ("LPR"); 12326426Smp153739 case (LOG_NEWS): 12336426Smp153739 return ("NEWS"); 12346426Smp153739 case (LOG_UUCP): 12356426Smp153739 return ("UUCP"); 12366426Smp153739 case (LOG_CRON): 12376426Smp153739 return ("CRON"); 12386426Smp153739 case (LOG_LOCAL0): 12396426Smp153739 return ("LOCAL0"); 12406426Smp153739 case (LOG_LOCAL1): 12416426Smp153739 return ("LOCAL1"); 12426426Smp153739 case (LOG_LOCAL2): 12436426Smp153739 return ("LOCAL2"); 12446426Smp153739 case (LOG_LOCAL3): 12456426Smp153739 return ("LOCAL3"); 12466426Smp153739 case (LOG_LOCAL4): 12476426Smp153739 return ("LOCAL4"); 12486426Smp153739 case (LOG_LOCAL5): 12496426Smp153739 return ("LOCAL6"); 12506426Smp153739 case (LOG_LOCAL7): 12516426Smp153739 return ("LOCAL7"); 12526426Smp153739 } 12536426Smp153739 return ("UNKNOWN"); 12546426Smp153739 } 12556426Smp153739 12566426Smp153739 /* 12576426Smp153739 * Solaris Kerberos: 12586426Smp153739 * Print to stderr where logging is being done 12596426Smp153739 */ 12606426Smp153739 krb5_error_code krb5_klog_list_logs(const char *whoami) { 12616426Smp153739 int lindex; 12626426Smp153739 12636426Smp153739 fprintf(stderr, gettext("%s: logging to "), whoami); 12646426Smp153739 for (lindex = 0; lindex < log_control.log_nentries; lindex++) { 12656426Smp153739 if (lindex != 0 && log_control.log_entries[lindex].log_type != K_LOG_NONE) 12666426Smp153739 fprintf(stderr, ", "); 12676426Smp153739 switch (log_control.log_entries[lindex].log_type) { 12686426Smp153739 case K_LOG_FILE: 12696426Smp153739 fprintf(stderr, "FILE=%s", log_control.log_entries[lindex].lfu_fname); 12706426Smp153739 break; 12716426Smp153739 case K_LOG_STDERR: 12726426Smp153739 fprintf(stderr, "STDERR"); 12736426Smp153739 break; 12746426Smp153739 case K_LOG_CONSOLE: 12756426Smp153739 fprintf(stderr, "CONSOLE"); 12766426Smp153739 break; 12776426Smp153739 case K_LOG_DEVICE: 12786426Smp153739 fprintf(stderr, "DEVICE=%s", log_control.log_entries[lindex].ldu_devname); 12796426Smp153739 break; 12806426Smp153739 case K_LOG_SYSLOG: 12816426Smp153739 fprintf(stderr, "SYSLOG=%s:%s", 12826426Smp153739 severity2string(log_control.log_entries[lindex].lsu_severity), 12836426Smp153739 facility2string(log_control.log_entries[lindex].lsu_facility)); 12846426Smp153739 break; 12856426Smp153739 case K_LOG_NONE: 12866426Smp153739 break; 12876426Smp153739 default: /* Should never get here */ 12886426Smp153739 return (-1); 12896426Smp153739 } 12906426Smp153739 } 12916426Smp153739 fprintf(stderr, "\n"); 12926426Smp153739 return (0); 12936426Smp153739 } 12946426Smp153739 12956426Smp153739 /* 12966426Smp153739 * Solaris Kerberos: 12976426Smp153739 * Add logging to stderr. 12986426Smp153739 */ 12996426Smp153739 krb5_error_code krb5_klog_add_stderr() { 13006426Smp153739 13016426Smp153739 struct log_entry *tmp_log_entries = log_control.log_entries; 13026426Smp153739 int i; 13036426Smp153739 13046426Smp153739 if (log_control.log_entries != &def_log_entry) { 13056426Smp153739 log_control.log_entries = realloc(log_control.log_entries, 13066426Smp153739 (log_control.log_nentries + 1) * sizeof(struct log_entry)); 13076426Smp153739 if (log_control.log_entries == NULL) { 13086426Smp153739 log_control.log_entries = tmp_log_entries; 13096426Smp153739 return (ENOMEM); 13106426Smp153739 } 13116426Smp153739 } else { 13126426Smp153739 log_control.log_entries = malloc(2 * sizeof(struct log_entry)); 13136426Smp153739 if (log_control.log_entries == NULL) { 13146426Smp153739 log_control.log_entries = &def_log_entry; 13156426Smp153739 return (ENOMEM); 13166426Smp153739 } 13176426Smp153739 (void) memcpy(&log_control.log_entries[0], &def_log_entry, 13186426Smp153739 sizeof(struct log_entry)); 13196426Smp153739 } 13206426Smp153739 13216426Smp153739 i = log_control.log_nentries; 13226426Smp153739 if (log_control.log_entries[i].lfu_filep = 13236426Smp153739 fdopen(fileno(stderr), "a+F")) { 13246426Smp153739 log_control.log_entries[i].log_type = K_LOG_STDERR; 13256426Smp153739 log_control.log_entries[i].log_2free = NULL; 13266426Smp153739 log_control.log_entries[i].lfu_fname = "standard error"; 13276426Smp153739 log_control.log_nentries++; 13286426Smp153739 } else { 13296426Smp153739 /* Free the alloc'ed extra entry */ 13306426Smp153739 int err = errno; 13316426Smp153739 tmp_log_entries = log_control.log_entries; 13326426Smp153739 log_control.log_entries = realloc(log_control.log_entries, 13336426Smp153739 (log_control.log_nentries) * sizeof(struct log_entry)); 13346426Smp153739 if (log_control.log_entries == NULL) 13356426Smp153739 log_control.log_entries = tmp_log_entries; 13366426Smp153739 return (err); 13376426Smp153739 } 13386426Smp153739 13396426Smp153739 return (0); 13406426Smp153739 } 13416426Smp153739 13426426Smp153739 /* 13436426Smp153739 * Solaris Kerberos 13446426Smp153739 * Remove logging to stderr. 13456426Smp153739 */ 13466426Smp153739 void krb5_klog_remove_stderr() { 13476426Smp153739 13486426Smp153739 struct log_entry *tmp_log_entries = log_control.log_entries; 13496426Smp153739 int i; 13506426Smp153739 13516426Smp153739 /* Find the entry (if it exists) */ 13526426Smp153739 for (i = 0; i < log_control.log_nentries; i++) { 13536426Smp153739 if (log_control.log_entries[i].log_type == K_LOG_STDERR) { 13546426Smp153739 break; 13556426Smp153739 } 13566426Smp153739 } 13576426Smp153739 13586426Smp153739 if ( i < log_control.log_nentries) { 13596426Smp153739 for (; i < log_control.log_nentries - 1; i++) 13606426Smp153739 log_control.log_entries[i] = 13616426Smp153739 log_control.log_entries[i + 1]; 13626426Smp153739 13636426Smp153739 if (log_control.log_nentries > 1) { 13646426Smp153739 log_control.log_entries = 13656426Smp153739 realloc(log_control.log_entries, 13666426Smp153739 (log_control.log_nentries + 1) * 13676426Smp153739 sizeof(struct log_entry)); 13686426Smp153739 if (log_control.log_entries != NULL) 13696426Smp153739 log_control.log_nentries--; 13706426Smp153739 else 13716426Smp153739 log_control.log_entries = tmp_log_entries; 13726426Smp153739 } else { 13736426Smp153739 if (log_control.log_entries != NULL) 13746426Smp153739 free(log_control.log_entries); 13756426Smp153739 } 13766426Smp153739 } 13776426Smp153739 } 13786426Smp153739 13796426Smp153739 /* Solaris Kerberos: Indicate if currently logging to stderr */ 13806426Smp153739 krb5_boolean krb5_klog_logging_to_stderr() { 13816426Smp153739 int i; 13826426Smp153739 13836426Smp153739 /* Find the entry (if it exists) */ 13846426Smp153739 for (i = 0; i < log_control.log_nentries; i++) { 13856426Smp153739 if (log_control.log_entries[i].log_type == K_LOG_STDERR) { 13866426Smp153739 return (TRUE); 13876426Smp153739 } 13886426Smp153739 } 13896426Smp153739 return (FALSE); 13906426Smp153739 } 13916426Smp153739 1392