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 *
krb5_log_error_table(long errorno)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
klog_rotate(struct log_entry * le)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
klog_com_err_proc(const char * whoami,long code,const char * format,va_list ap)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
krb5_klog_init(krb5_context kcontext,char * ename,char * whoami,krb5_boolean do_com_err)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
krb5_klog_close(krb5_context kcontext)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 *
severity2string(int severity)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
klog_vsyslog(int priority,const char * format,va_list arglist)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
krb5_klog_syslog(int priority,const char * format,...)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
krb5_klog_reopen(krb5_context kcontext)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 */
krb5_klog_set_context(krb5_context context)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 */
facility2string(int facility)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 */
krb5_klog_list_logs(const char * whoami)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 */
krb5_klog_add_stderr()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 */
krb5_klog_remove_stderr()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 */
krb5_klog_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