1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * lib/kadm/logger.c 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * Copyright 1995 by the Massachusetts Institute of Technology. 5*0Sstevel@tonic-gate * All Rights Reserved. 6*0Sstevel@tonic-gate * 7*0Sstevel@tonic-gate * Export of this software from the United States of America may 8*0Sstevel@tonic-gate * require a specific license from the United States Government. 9*0Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 10*0Sstevel@tonic-gate * export to obtain such a license before exporting. 11*0Sstevel@tonic-gate * 12*0Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13*0Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 14*0Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 15*0Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 16*0Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 17*0Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 18*0Sstevel@tonic-gate * to distribution of the software without specific, written prior 19*0Sstevel@tonic-gate * permission. M.I.T. makes no representations about the suitability of 20*0Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 21*0Sstevel@tonic-gate * or implied warranty. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate */ 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate /* 26*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 27*0Sstevel@tonic-gate * Use is subject to license terms. 28*0Sstevel@tonic-gate */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate /* KADM5 wants non-syslog log files to contain syslog-like entries */ 34*0Sstevel@tonic-gate #define VERBOSE_LOGS 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate /* 37*0Sstevel@tonic-gate * logger.c - Handle logging functions for those who want it. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate #include "k5-int.h" 40*0Sstevel@tonic-gate #include "adm_proto.h" 41*0Sstevel@tonic-gate #include "com_err.h" 42*0Sstevel@tonic-gate #include <stdio.h> 43*0Sstevel@tonic-gate #include <ctype.h> 44*0Sstevel@tonic-gate #include <syslog.h> 45*0Sstevel@tonic-gate #include <stdarg.h> 46*0Sstevel@tonic-gate #include <libintl.h> 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #define KRB5_KLOG_MAX_ERRMSG_SIZE 1024 49*0Sstevel@tonic-gate #ifndef MAXHOSTNAMELEN 50*0Sstevel@tonic-gate #define MAXHOSTNAMELEN 256 51*0Sstevel@tonic-gate #endif /* MAXHOSTNAMELEN */ 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #define LSPEC_PARSE_ERR_1 1 54*0Sstevel@tonic-gate #define LSPEC_PARSE_ERR_2 2 55*0Sstevel@tonic-gate #define LOG_FILE_ERR 3 56*0Sstevel@tonic-gate #define LOG_DEVICE_ERR 4 57*0Sstevel@tonic-gate #define LOG_UFO_STRING 5 58*0Sstevel@tonic-gate #define LOG_EMERG_STRING 6 59*0Sstevel@tonic-gate #define LOG_ALERT_STRING 7 60*0Sstevel@tonic-gate #define LOG_CRIT_STRING 8 61*0Sstevel@tonic-gate #define LOG_ERR_STRING 9 62*0Sstevel@tonic-gate #define LOG_WARNING_STRING 10 63*0Sstevel@tonic-gate #define LOG_NOTICE_STRING 11 64*0Sstevel@tonic-gate #define LOG_INFO_STRING 12 65*0Sstevel@tonic-gate #define LOG_DEBUG_STRING 13 66*0Sstevel@tonic-gate /* This is to assure that we have at least one match in the syslog stuff */ 67*0Sstevel@tonic-gate /* 68*0Sstevel@tonic-gate static const char LSPEC_PARSE_ERR_1[] = "%s: cannot parse <%s>\n"; 69*0Sstevel@tonic-gate static const char LSPEC_PARSE_ERR_2[] = "%s: warning - logging entry syntax error\n"; 70*0Sstevel@tonic-gate static const char LOG_FILE_ERR[] = "%s: error writing to %s\n"; 71*0Sstevel@tonic-gate static const char LOG_DEVICE_ERR[] = "%s: error writing to %s device\n"; 72*0Sstevel@tonic-gate static const char LOG_UFO_STRING[] = "???"; 73*0Sstevel@tonic-gate static const char LOG_EMERG_STRING[] = "EMERGENCY"; 74*0Sstevel@tonic-gate static const char LOG_ALERT_STRING[] = "ALERT"; 75*0Sstevel@tonic-gate static const char LOG_CRIT_STRING[] = "CRITICAL"; 76*0Sstevel@tonic-gate static const char LOG_ERR_STRING[] = "Error"; 77*0Sstevel@tonic-gate static const char LOG_WARNING_STRING[] = "Warning"; 78*0Sstevel@tonic-gate static const char LOG_NOTICE_STRING[] = "Notice"; 79*0Sstevel@tonic-gate static const char LOG_INFO_STRING[] = "info"; 80*0Sstevel@tonic-gate static const char LOG_DEBUG_STRING[] = "debug"; 81*0Sstevel@tonic-gate */ 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate const char * 85*0Sstevel@tonic-gate krb5_log_error_table(long errorno) { 86*0Sstevel@tonic-gate switch (errorno) { 87*0Sstevel@tonic-gate case LSPEC_PARSE_ERR_1: 88*0Sstevel@tonic-gate return(gettext("%s: cannot parse <%s>\n")); 89*0Sstevel@tonic-gate case LSPEC_PARSE_ERR_2: 90*0Sstevel@tonic-gate return(gettext("%s: warning - logging entry syntax error\n")); 91*0Sstevel@tonic-gate case LOG_FILE_ERR: 92*0Sstevel@tonic-gate return(gettext("%s: error writing to %s\n")); 93*0Sstevel@tonic-gate case LOG_DEVICE_ERR: 94*0Sstevel@tonic-gate return(gettext("%s: error writing to %s device\n")); 95*0Sstevel@tonic-gate case LOG_UFO_STRING: 96*0Sstevel@tonic-gate return(gettext("???")); 97*0Sstevel@tonic-gate case LOG_EMERG_STRING: 98*0Sstevel@tonic-gate return(gettext("EMERGENCY")); 99*0Sstevel@tonic-gate case LOG_ALERT_STRING: 100*0Sstevel@tonic-gate return(gettext("ALERT")); 101*0Sstevel@tonic-gate case LOG_CRIT_STRING: 102*0Sstevel@tonic-gate return(gettext("CRITICAL")); 103*0Sstevel@tonic-gate case LOG_ERR_STRING: 104*0Sstevel@tonic-gate return(gettext("Error")); 105*0Sstevel@tonic-gate case LOG_WARNING_STRING: 106*0Sstevel@tonic-gate return(gettext("Warning")); 107*0Sstevel@tonic-gate case LOG_NOTICE_STRING: 108*0Sstevel@tonic-gate return(gettext("Notice")); 109*0Sstevel@tonic-gate case LOG_INFO_STRING: 110*0Sstevel@tonic-gate case LOG_DEBUG_STRING: 111*0Sstevel@tonic-gate default: 112*0Sstevel@tonic-gate return(gettext("info")); 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate /* 117*0Sstevel@tonic-gate * Output logging. 118*0Sstevel@tonic-gate * 119*0Sstevel@tonic-gate * Output logging is now controlled by the configuration file. We can specify 120*0Sstevel@tonic-gate * the following syntaxes under the [logging]->entity specification. 121*0Sstevel@tonic-gate * FILE<opentype><pathname> 122*0Sstevel@tonic-gate * SYSLOG[=<severity>[:<facility>]] 123*0Sstevel@tonic-gate * STDERR 124*0Sstevel@tonic-gate * CONSOLE 125*0Sstevel@tonic-gate * DEVICE=<device-spec> 126*0Sstevel@tonic-gate * 127*0Sstevel@tonic-gate * Where: 128*0Sstevel@tonic-gate * <opentype> is ":" for open/append, "=" for open/create. 129*0Sstevel@tonic-gate * <pathname> is a valid path name. 130*0Sstevel@tonic-gate * <severity> is one of: (default = ERR) 131*0Sstevel@tonic-gate * EMERG 132*0Sstevel@tonic-gate * ALERT 133*0Sstevel@tonic-gate * CRIT 134*0Sstevel@tonic-gate * ERR 135*0Sstevel@tonic-gate * WARNING 136*0Sstevel@tonic-gate * NOTICE 137*0Sstevel@tonic-gate * INFO 138*0Sstevel@tonic-gate * DEBUG 139*0Sstevel@tonic-gate * <facility> is one of: (default = AUTH) 140*0Sstevel@tonic-gate * KERN 141*0Sstevel@tonic-gate * USER 142*0Sstevel@tonic-gate * MAIL 143*0Sstevel@tonic-gate * DAEMON 144*0Sstevel@tonic-gate * AUTH 145*0Sstevel@tonic-gate * LPR 146*0Sstevel@tonic-gate * NEWS 147*0Sstevel@tonic-gate * UUCP 148*0Sstevel@tonic-gate * AUDIT 149*0Sstevel@tonic-gate * CRON 150*0Sstevel@tonic-gate * LOCAL0..LOCAL7 151*0Sstevel@tonic-gate * <device-spec> is a valid device specification. 152*0Sstevel@tonic-gate */ 153*0Sstevel@tonic-gate struct log_entry { 154*0Sstevel@tonic-gate enum log_type { K_LOG_FILE, 155*0Sstevel@tonic-gate K_LOG_SYSLOG, 156*0Sstevel@tonic-gate K_LOG_STDERR, 157*0Sstevel@tonic-gate K_LOG_CONSOLE, 158*0Sstevel@tonic-gate K_LOG_DEVICE, 159*0Sstevel@tonic-gate K_LOG_NONE } log_type; 160*0Sstevel@tonic-gate krb5_pointer log_2free; 161*0Sstevel@tonic-gate union log_union { 162*0Sstevel@tonic-gate struct log_file { 163*0Sstevel@tonic-gate FILE *lf_filep; 164*0Sstevel@tonic-gate char *lf_fname; 165*0Sstevel@tonic-gate char *lf_fopen_mode; /* "a+" or "w" */ 166*0Sstevel@tonic-gate #define K_LOG_DEF_FILE_ROTATE_PERIOD -1 /* never */ 167*0Sstevel@tonic-gate #define K_LOG_DEF_FILE_ROTATE_VERSIONS 0 /* no versions */ 168*0Sstevel@tonic-gate time_t lf_rotate_period; 169*0Sstevel@tonic-gate time_t lf_last_rotated; 170*0Sstevel@tonic-gate int lf_rotate_versions; 171*0Sstevel@tonic-gate } log_file; 172*0Sstevel@tonic-gate struct log_syslog { 173*0Sstevel@tonic-gate int ls_facility; 174*0Sstevel@tonic-gate int ls_severity; 175*0Sstevel@tonic-gate } log_syslog; 176*0Sstevel@tonic-gate struct log_device { 177*0Sstevel@tonic-gate FILE *ld_filep; 178*0Sstevel@tonic-gate char *ld_devname; 179*0Sstevel@tonic-gate } log_device; 180*0Sstevel@tonic-gate } log_union; 181*0Sstevel@tonic-gate }; 182*0Sstevel@tonic-gate #define lfu_filep log_union.log_file.lf_filep 183*0Sstevel@tonic-gate #define lfu_fname log_union.log_file.lf_fname 184*0Sstevel@tonic-gate #define lfu_fopen_mode log_union.log_file.lf_fopen_mode 185*0Sstevel@tonic-gate #define lfu_rotate_period log_union.log_file.lf_rotate_period 186*0Sstevel@tonic-gate #define lfu_last_rotated log_union.log_file.lf_last_rotated 187*0Sstevel@tonic-gate #define lfu_rotate_versions log_union.log_file.lf_rotate_versions 188*0Sstevel@tonic-gate #define lsu_facility log_union.log_syslog.ls_facility 189*0Sstevel@tonic-gate #define lsu_severity log_union.log_syslog.ls_severity 190*0Sstevel@tonic-gate #define ldu_filep log_union.log_device.ld_filep 191*0Sstevel@tonic-gate #define ldu_devname log_union.log_device.ld_devname 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate struct log_control { 194*0Sstevel@tonic-gate struct log_entry *log_entries; 195*0Sstevel@tonic-gate int log_nentries; 196*0Sstevel@tonic-gate char *log_whoami; 197*0Sstevel@tonic-gate char *log_hostname; 198*0Sstevel@tonic-gate krb5_boolean log_opened; 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate }; 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate static struct log_control log_control = { 203*0Sstevel@tonic-gate (struct log_entry *) NULL, 204*0Sstevel@tonic-gate 0, 205*0Sstevel@tonic-gate (char *) NULL, 206*0Sstevel@tonic-gate (char *) NULL, 207*0Sstevel@tonic-gate 0 208*0Sstevel@tonic-gate }; 209*0Sstevel@tonic-gate static struct log_entry def_log_entry; 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate /* 212*0Sstevel@tonic-gate * These macros define any special processing that needs to happen for 213*0Sstevel@tonic-gate * devices. For unix, of course, this is hardly anything. 214*0Sstevel@tonic-gate */ 215*0Sstevel@tonic-gate #define DEVICE_OPEN(d, m) fopen(d, m) 216*0Sstevel@tonic-gate #define CONSOLE_OPEN(m) fopen("/dev/console", m) 217*0Sstevel@tonic-gate #define DEVICE_PRINT(f, m) ((fprintf(f, m) >= 0) ? \ 218*0Sstevel@tonic-gate (fprintf(f, "\r\n"), fflush(f), 0) : \ 219*0Sstevel@tonic-gate -1) 220*0Sstevel@tonic-gate #define DEVICE_CLOSE(d) fclose(d) 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* 224*0Sstevel@tonic-gate * klog_rotate() - roate a log file if we have specified rotation 225*0Sstevel@tonic-gate * parameters in krb5.conf. 226*0Sstevel@tonic-gate */ 227*0Sstevel@tonic-gate static void 228*0Sstevel@tonic-gate klog_rotate(struct log_entry *le) 229*0Sstevel@tonic-gate { 230*0Sstevel@tonic-gate time_t t; 231*0Sstevel@tonic-gate int i; 232*0Sstevel@tonic-gate char *name_buf1; 233*0Sstevel@tonic-gate char *name_buf2; 234*0Sstevel@tonic-gate char *old_name; 235*0Sstevel@tonic-gate char *new_name; 236*0Sstevel@tonic-gate char *tmp; 237*0Sstevel@tonic-gate FILE *fp; 238*0Sstevel@tonic-gate int num_vers; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate /* 241*0Sstevel@tonic-gate * By default we don't rotate. 242*0Sstevel@tonic-gate */ 243*0Sstevel@tonic-gate if (le->lfu_rotate_period == K_LOG_DEF_FILE_ROTATE_PERIOD) 244*0Sstevel@tonic-gate return; 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate t = time(0); 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if (t >= le->lfu_last_rotated + le->lfu_rotate_period) { 249*0Sstevel@tonic-gate /* 250*0Sstevel@tonic-gate * The N log file versions will be renamed X.N-1 X.N-2, ... X.0. 251*0Sstevel@tonic-gate * So the allocate file name buffers that can the version 252*0Sstevel@tonic-gate * number extensions. 253*0Sstevel@tonic-gate * 32 extra bytes is plenty. 254*0Sstevel@tonic-gate */ 255*0Sstevel@tonic-gate name_buf1 = malloc(strlen(le->lfu_fname) + 32); 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate if (name_buf1 == NULL) 258*0Sstevel@tonic-gate return; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate name_buf2 = malloc(strlen(le->lfu_fname) + 32); 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate if (name_buf2 == NULL) { 263*0Sstevel@tonic-gate free(name_buf1); 264*0Sstevel@tonic-gate return; 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate old_name = name_buf1; 268*0Sstevel@tonic-gate new_name = name_buf2; 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate /* 271*0Sstevel@tonic-gate * If there N versions, then the first one has file extension 272*0Sstevel@tonic-gate * of N-1. 273*0Sstevel@tonic-gate */ 274*0Sstevel@tonic-gate (void) sprintf(new_name, "%s.%d", le->lfu_fname, 275*0Sstevel@tonic-gate le->lfu_rotate_versions - 1); 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate /* 278*0Sstevel@tonic-gate * Rename file.N-2 to file.N-1, file.N-3 to file.N-2, ... 279*0Sstevel@tonic-gate * file.0 to file.1 280*0Sstevel@tonic-gate */ 281*0Sstevel@tonic-gate for (i = le->lfu_rotate_versions - 1; i > 0; i--) { 282*0Sstevel@tonic-gate (void) sprintf(old_name, "%s.%d", le->lfu_fname, i - 1); 283*0Sstevel@tonic-gate (void) rename(old_name, new_name); 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate /* 286*0Sstevel@tonic-gate * swap old name and new name. This way, 287*0Sstevel@tonic-gate * on the next iteration, new_name.X 288*0Sstevel@tonic-gate * becomes new_name.X-1. 289*0Sstevel@tonic-gate */ 290*0Sstevel@tonic-gate tmp = old_name; 291*0Sstevel@tonic-gate old_name = new_name; 292*0Sstevel@tonic-gate new_name = tmp; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate old_name = le->lfu_fname; 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate (void) rename(old_name, new_name); 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate /* 299*0Sstevel@tonic-gate * Even though we don't know yet if the fopen() 300*0Sstevel@tonic-gate * of the log file will succeed, we mark the log 301*0Sstevel@tonic-gate * as rotated. This is so we don't repeatably 302*0Sstevel@tonic-gate * rotate file.N-2 to file.N-1 ... etc without 303*0Sstevel@tonic-gate * waiting for the rotate period to elapse. 304*0Sstevel@tonic-gate */ 305*0Sstevel@tonic-gate le->lfu_last_rotated = t; 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate fp = fopen(old_name, le->lfu_fopen_mode); 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate if (fp != NULL) { 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate /* Set the permissions to 644 */ 312*0Sstevel@tonic-gate if (fchmod(fileno(fp), 313*0Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) { 314*0Sstevel@tonic-gate fprintf(stderr, 315*0Sstevel@tonic-gate gettext("During rotate, couldn't set permissions for log file %s: %s\n"), 316*0Sstevel@tonic-gate old_name, error_message(errno)); 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate (void) fclose(le->lfu_filep); 320*0Sstevel@tonic-gate le->lfu_filep = fp; 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate /* 323*0Sstevel@tonic-gate * If the version parameter in krb5.conf was 324*0Sstevel@tonic-gate * 0, then we take this to mean that rotating the 325*0Sstevel@tonic-gate * log file will cause us to dispose of the 326*0Sstevel@tonic-gate * old one, and created a new one. We have just 327*0Sstevel@tonic-gate * renamed the old one to file.-1, so remove it. 328*0Sstevel@tonic-gate */ 329*0Sstevel@tonic-gate if (le->lfu_rotate_versions <= 0) 330*0Sstevel@tonic-gate (void) unlink(new_name); 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate } else { 333*0Sstevel@tonic-gate fprintf(stderr, 334*0Sstevel@tonic-gate gettext("During rotate, couldn't open log file %s: %s\n"), 335*0Sstevel@tonic-gate old_name, error_message(errno)); 336*0Sstevel@tonic-gate /* 337*0Sstevel@tonic-gate * Put it back. 338*0Sstevel@tonic-gate */ 339*0Sstevel@tonic-gate (void) rename(new_name, old_name); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate free(name_buf1); 342*0Sstevel@tonic-gate free(name_buf2); 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate /* 347*0Sstevel@tonic-gate * klog_com_err_proc() - Handle com_err(3) messages as specified by the 348*0Sstevel@tonic-gate * profile. 349*0Sstevel@tonic-gate */ 350*0Sstevel@tonic-gate static void 351*0Sstevel@tonic-gate klog_com_err_proc(whoami, code, format, ap) 352*0Sstevel@tonic-gate const char *whoami; 353*0Sstevel@tonic-gate long code; 354*0Sstevel@tonic-gate const char *format; 355*0Sstevel@tonic-gate va_list ap; 356*0Sstevel@tonic-gate { 357*0Sstevel@tonic-gate char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE]; 358*0Sstevel@tonic-gate int lindex; 359*0Sstevel@tonic-gate char *actual_format; 360*0Sstevel@tonic-gate int log_pri = -1; 361*0Sstevel@tonic-gate char *cp; 362*0Sstevel@tonic-gate char *syslogp; 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate /* Make the header */ 365*0Sstevel@tonic-gate sprintf(outbuf, "%s: ", whoami); 366*0Sstevel@tonic-gate /* 367*0Sstevel@tonic-gate * Squirrel away address after header for syslog since syslog makes 368*0Sstevel@tonic-gate * a header 369*0Sstevel@tonic-gate */ 370*0Sstevel@tonic-gate syslogp = &outbuf[strlen(outbuf)]; 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* If reporting an error message, separate it. */ 373*0Sstevel@tonic-gate if (code) { 374*0Sstevel@tonic-gate strcat(outbuf, error_message(code)); 375*0Sstevel@tonic-gate strcat(outbuf, " - "); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate cp = &outbuf[strlen(outbuf)]; 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate actual_format = (char *) format; 380*0Sstevel@tonic-gate /* 381*0Sstevel@tonic-gate * This is an unpleasant hack. If the first character is less than 382*0Sstevel@tonic-gate * 8, then we assume that it is a priority. 383*0Sstevel@tonic-gate * 384*0Sstevel@tonic-gate * Since it is not guaranteed that there is a direct mapping between 385*0Sstevel@tonic-gate * syslog priorities (e.g. Ultrix and old BSD), we resort to this 386*0Sstevel@tonic-gate * intermediate representation. 387*0Sstevel@tonic-gate */ 388*0Sstevel@tonic-gate if ((((unsigned char) *format) > 0) && (((unsigned char) *format) <= 8)) { 389*0Sstevel@tonic-gate actual_format = (char *) (format + 1); 390*0Sstevel@tonic-gate switch ((unsigned char) *format) { 391*0Sstevel@tonic-gate case 1: 392*0Sstevel@tonic-gate log_pri = LOG_EMERG; 393*0Sstevel@tonic-gate break; 394*0Sstevel@tonic-gate case 2: 395*0Sstevel@tonic-gate log_pri = LOG_ALERT; 396*0Sstevel@tonic-gate break; 397*0Sstevel@tonic-gate case 3: 398*0Sstevel@tonic-gate log_pri = LOG_CRIT; 399*0Sstevel@tonic-gate break; 400*0Sstevel@tonic-gate default: 401*0Sstevel@tonic-gate case 4: 402*0Sstevel@tonic-gate log_pri = LOG_ERR; 403*0Sstevel@tonic-gate break; 404*0Sstevel@tonic-gate case 5: 405*0Sstevel@tonic-gate log_pri = LOG_WARNING; 406*0Sstevel@tonic-gate break; 407*0Sstevel@tonic-gate case 6: 408*0Sstevel@tonic-gate log_pri = LOG_NOTICE; 409*0Sstevel@tonic-gate break; 410*0Sstevel@tonic-gate case 7: 411*0Sstevel@tonic-gate log_pri = LOG_INFO; 412*0Sstevel@tonic-gate break; 413*0Sstevel@tonic-gate case 8: 414*0Sstevel@tonic-gate log_pri = LOG_DEBUG; 415*0Sstevel@tonic-gate break; 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate /* Now format the actual message */ 420*0Sstevel@tonic-gate vsprintf(cp, actual_format, ap); 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate /* 423*0Sstevel@tonic-gate * Now that we have the message formatted, perform the output to each 424*0Sstevel@tonic-gate * logging specification. 425*0Sstevel@tonic-gate */ 426*0Sstevel@tonic-gate for (lindex = 0; lindex < log_control.log_nentries; lindex++) { 427*0Sstevel@tonic-gate switch (log_control.log_entries[lindex].log_type) { 428*0Sstevel@tonic-gate case K_LOG_FILE: 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate klog_rotate(&log_control.log_entries[lindex]); 431*0Sstevel@tonic-gate /*FALLTHRU*/ 432*0Sstevel@tonic-gate case K_LOG_STDERR: 433*0Sstevel@tonic-gate /* 434*0Sstevel@tonic-gate * Files/standard error. 435*0Sstevel@tonic-gate */ 436*0Sstevel@tonic-gate if (fprintf(log_control.log_entries[lindex].lfu_filep, 437*0Sstevel@tonic-gate outbuf) < 0) { 438*0Sstevel@tonic-gate /* Attempt to report error */ 439*0Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LOG_FILE_ERR), whoami, 440*0Sstevel@tonic-gate log_control.log_entries[lindex].lfu_fname); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate else { 443*0Sstevel@tonic-gate fprintf(log_control.log_entries[lindex].lfu_filep, "\n"); 444*0Sstevel@tonic-gate fflush(log_control.log_entries[lindex].lfu_filep); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate break; 447*0Sstevel@tonic-gate case K_LOG_CONSOLE: 448*0Sstevel@tonic-gate case K_LOG_DEVICE: 449*0Sstevel@tonic-gate /* 450*0Sstevel@tonic-gate * Devices (may need special handling) 451*0Sstevel@tonic-gate */ 452*0Sstevel@tonic-gate if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep, 453*0Sstevel@tonic-gate outbuf) < 0) { 454*0Sstevel@tonic-gate /* Attempt to report error */ 455*0Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LOG_DEVICE_ERR), whoami, 456*0Sstevel@tonic-gate log_control.log_entries[lindex].ldu_devname); 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate break; 459*0Sstevel@tonic-gate case K_LOG_SYSLOG: 460*0Sstevel@tonic-gate /* 461*0Sstevel@tonic-gate * System log. 462*0Sstevel@tonic-gate */ 463*0Sstevel@tonic-gate /* 464*0Sstevel@tonic-gate * If we have specified a priority through our hackery, then 465*0Sstevel@tonic-gate * use it, otherwise use the default. 466*0Sstevel@tonic-gate */ 467*0Sstevel@tonic-gate if (log_pri >= 0) 468*0Sstevel@tonic-gate log_pri |= log_control.log_entries[lindex].lsu_facility; 469*0Sstevel@tonic-gate else 470*0Sstevel@tonic-gate log_pri = log_control.log_entries[lindex].lsu_facility | 471*0Sstevel@tonic-gate log_control.log_entries[lindex].lsu_severity; 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate /* Log the message with our header trimmed off */ 474*0Sstevel@tonic-gate syslog(log_pri, syslogp); 475*0Sstevel@tonic-gate break; 476*0Sstevel@tonic-gate default: 477*0Sstevel@tonic-gate break; 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate /* 483*0Sstevel@tonic-gate * krb5_klog_init() - Initialize logging. 484*0Sstevel@tonic-gate * 485*0Sstevel@tonic-gate * This routine parses the syntax described above to specify destinations for 486*0Sstevel@tonic-gate * com_err(3) or krb5_klog_syslog() messages generated by the caller. 487*0Sstevel@tonic-gate * 488*0Sstevel@tonic-gate * Parameters: 489*0Sstevel@tonic-gate * kcontext - Kerberos context. 490*0Sstevel@tonic-gate * ename - Entity name as it is to appear in the profile. 491*0Sstevel@tonic-gate * whoami - Entity name as it is to appear in error output. 492*0Sstevel@tonic-gate * do_com_err - Take over com_err(3) processing. 493*0Sstevel@tonic-gate * 494*0Sstevel@tonic-gate * Implicit inputs: 495*0Sstevel@tonic-gate * stderr - This is where STDERR output goes. 496*0Sstevel@tonic-gate * 497*0Sstevel@tonic-gate * Implicit outputs: 498*0Sstevel@tonic-gate * log_nentries - Number of log entries, both valid and invalid. 499*0Sstevel@tonic-gate * log_control - List of entries (log_nentries long) which contains 500*0Sstevel@tonic-gate * data for klog_com_err_proc() to use to determine 501*0Sstevel@tonic-gate * where/how to send output. 502*0Sstevel@tonic-gate */ 503*0Sstevel@tonic-gate krb5_error_code 504*0Sstevel@tonic-gate krb5_klog_init(kcontext, ename, whoami, do_com_err) 505*0Sstevel@tonic-gate krb5_context kcontext; 506*0Sstevel@tonic-gate char *ename; 507*0Sstevel@tonic-gate char *whoami; 508*0Sstevel@tonic-gate krb5_boolean do_com_err; 509*0Sstevel@tonic-gate { 510*0Sstevel@tonic-gate const char *logging_profent[3]; 511*0Sstevel@tonic-gate const char *logging_defent[3]; 512*0Sstevel@tonic-gate char **logging_specs; 513*0Sstevel@tonic-gate int i, ngood; 514*0Sstevel@tonic-gate char *cp, *cp2; 515*0Sstevel@tonic-gate char savec; 516*0Sstevel@tonic-gate int error; 517*0Sstevel@tonic-gate int do_openlog, log_facility; 518*0Sstevel@tonic-gate FILE *f; 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate /* Initialize */ 521*0Sstevel@tonic-gate do_openlog = 0; 522*0Sstevel@tonic-gate log_facility = 0; 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate /* 525*0Sstevel@tonic-gate * Look up [logging]-><ename> in the profile. If that doesn't 526*0Sstevel@tonic-gate * succeed, then look for [logging]->default. 527*0Sstevel@tonic-gate */ 528*0Sstevel@tonic-gate logging_profent[0] = "logging"; 529*0Sstevel@tonic-gate logging_profent[1] = ename; 530*0Sstevel@tonic-gate logging_profent[2] = (char *) NULL; 531*0Sstevel@tonic-gate logging_defent[0] = "logging"; 532*0Sstevel@tonic-gate logging_defent[1] = "default"; 533*0Sstevel@tonic-gate logging_defent[2] = (char *) NULL; 534*0Sstevel@tonic-gate logging_specs = (char **) NULL; 535*0Sstevel@tonic-gate ngood = 0; 536*0Sstevel@tonic-gate log_control.log_nentries = 0; 537*0Sstevel@tonic-gate if (!profile_get_values(kcontext->profile, 538*0Sstevel@tonic-gate logging_profent, 539*0Sstevel@tonic-gate &logging_specs) || 540*0Sstevel@tonic-gate !profile_get_values(kcontext->profile, 541*0Sstevel@tonic-gate logging_defent, 542*0Sstevel@tonic-gate &logging_specs)) { 543*0Sstevel@tonic-gate /* 544*0Sstevel@tonic-gate * We have a match, so we first count the number of elements 545*0Sstevel@tonic-gate */ 546*0Sstevel@tonic-gate for (log_control.log_nentries = 0; 547*0Sstevel@tonic-gate logging_specs[log_control.log_nentries]; 548*0Sstevel@tonic-gate log_control.log_nentries++); 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate /* 551*0Sstevel@tonic-gate * Now allocate our structure. 552*0Sstevel@tonic-gate */ 553*0Sstevel@tonic-gate log_control.log_entries = (struct log_entry *) 554*0Sstevel@tonic-gate malloc(log_control.log_nentries * sizeof(struct log_entry)); 555*0Sstevel@tonic-gate if (log_control.log_entries) { 556*0Sstevel@tonic-gate /* 557*0Sstevel@tonic-gate * Scan through the list. 558*0Sstevel@tonic-gate */ 559*0Sstevel@tonic-gate for (i=0; i<log_control.log_nentries; i++) { 560*0Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_NONE; 561*0Sstevel@tonic-gate log_control.log_entries[i].log_2free = logging_specs[i]; 562*0Sstevel@tonic-gate /* 563*0Sstevel@tonic-gate * The format is: 564*0Sstevel@tonic-gate * <whitespace><data><whitespace> 565*0Sstevel@tonic-gate * so, trim off the leading and trailing whitespace here. 566*0Sstevel@tonic-gate */ 567*0Sstevel@tonic-gate for (cp = logging_specs[i]; isspace(*cp); cp++); 568*0Sstevel@tonic-gate for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1]; 569*0Sstevel@tonic-gate isspace(*cp2); cp2--); 570*0Sstevel@tonic-gate cp2++; 571*0Sstevel@tonic-gate *cp2 = '\0'; 572*0Sstevel@tonic-gate /* 573*0Sstevel@tonic-gate * Is this a file? 574*0Sstevel@tonic-gate */ 575*0Sstevel@tonic-gate if (!strncasecmp(cp, "FILE", 4)) { 576*0Sstevel@tonic-gate /* 577*0Sstevel@tonic-gate * Check for append/overwrite, then open the file. 578*0Sstevel@tonic-gate */ 579*0Sstevel@tonic-gate if (cp[4] == ':' || cp[4] == '=') { 580*0Sstevel@tonic-gate log_control.log_entries[i].lfu_fopen_mode = 581*0Sstevel@tonic-gate (cp[4] == ':') ? "a+" : "w"; 582*0Sstevel@tonic-gate f = fopen(&cp[5], 583*0Sstevel@tonic-gate log_control.log_entries[i].lfu_fopen_mode); 584*0Sstevel@tonic-gate if (f) { 585*0Sstevel@tonic-gate char rotate_kw[128]; 586*0Sstevel@tonic-gate /* Set the permissions to 644 */ 587*0Sstevel@tonic-gate if (fchmod(fileno(f), 588*0Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) { 589*0Sstevel@tonic-gate fprintf(stderr,gettext("Couldn't set permissions for log file %s: %s\n"), 590*0Sstevel@tonic-gate &cp[5], error_message(errno)); 591*0Sstevel@tonic-gate } 592*0Sstevel@tonic-gate log_control.log_entries[i].lfu_filep = f; 593*0Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_FILE; 594*0Sstevel@tonic-gate log_control.log_entries[i].lfu_fname = &cp[5]; 595*0Sstevel@tonic-gate log_control.log_entries[i].lfu_rotate_period = 596*0Sstevel@tonic-gate K_LOG_DEF_FILE_ROTATE_PERIOD; 597*0Sstevel@tonic-gate log_control.log_entries[i].lfu_rotate_versions = 598*0Sstevel@tonic-gate K_LOG_DEF_FILE_ROTATE_VERSIONS; 599*0Sstevel@tonic-gate log_control.log_entries[i].lfu_last_rotated = 600*0Sstevel@tonic-gate time(0); 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate /* 603*0Sstevel@tonic-gate * Now parse for ename_"rotate" = { 604*0Sstevel@tonic-gate * period = XXX 605*0Sstevel@tonic-gate * versions = 10 606*0Sstevel@tonic-gate * } 607*0Sstevel@tonic-gate */ 608*0Sstevel@tonic-gate if (strlen(ename) + strlen("_rotate") < 609*0Sstevel@tonic-gate sizeof (rotate_kw)) { 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate char *time; 612*0Sstevel@tonic-gate krb5_deltat dt; 613*0Sstevel@tonic-gate int vers; 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate strcpy(rotate_kw, ename); 616*0Sstevel@tonic-gate strcat(rotate_kw, "_rotate"); 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate if (!profile_get_string(kcontext->profile, 619*0Sstevel@tonic-gate "logging", rotate_kw, "period", 620*0Sstevel@tonic-gate NULL, &time)) { 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate if (time != NULL) { 623*0Sstevel@tonic-gate if (!krb5_string_to_deltat(time, 624*0Sstevel@tonic-gate &dt)) { 625*0Sstevel@tonic-gate log_control.log_entries[i].lfu_rotate_period = 626*0Sstevel@tonic-gate (time_t) dt; 627*0Sstevel@tonic-gate } 628*0Sstevel@tonic-gate free(time); 629*0Sstevel@tonic-gate } 630*0Sstevel@tonic-gate } 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate if (!profile_get_integer( 633*0Sstevel@tonic-gate kcontext->profile, "logging", 634*0Sstevel@tonic-gate rotate_kw, "versions", 635*0Sstevel@tonic-gate K_LOG_DEF_FILE_ROTATE_VERSIONS, 636*0Sstevel@tonic-gate &vers)) { 637*0Sstevel@tonic-gate log_control.log_entries[i].lfu_rotate_versions = vers; 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate } 641*0Sstevel@tonic-gate } else { 642*0Sstevel@tonic-gate fprintf(stderr,gettext("Couldn't open log file %s: %s\n"), 643*0Sstevel@tonic-gate &cp[5], error_message(errno)); 644*0Sstevel@tonic-gate continue; 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate } 647*0Sstevel@tonic-gate } 648*0Sstevel@tonic-gate /* 649*0Sstevel@tonic-gate * Is this a syslog? 650*0Sstevel@tonic-gate */ 651*0Sstevel@tonic-gate else if (!strncasecmp(cp, "SYSLOG", 6)) { 652*0Sstevel@tonic-gate error = 0; 653*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_AUTH; 654*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = LOG_ERR; 655*0Sstevel@tonic-gate /* 656*0Sstevel@tonic-gate * Is there a severify specified? 657*0Sstevel@tonic-gate */ 658*0Sstevel@tonic-gate if (cp[6] == ':') { 659*0Sstevel@tonic-gate /* 660*0Sstevel@tonic-gate * Find the end of the severity. 661*0Sstevel@tonic-gate */ 662*0Sstevel@tonic-gate if (cp2 = strchr(&cp[7], ':')) { 663*0Sstevel@tonic-gate savec = *cp2; 664*0Sstevel@tonic-gate *cp2 = '\0'; 665*0Sstevel@tonic-gate cp2++; 666*0Sstevel@tonic-gate } 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate /* 669*0Sstevel@tonic-gate * Match a severity. 670*0Sstevel@tonic-gate */ 671*0Sstevel@tonic-gate if (!strcasecmp(&cp[7], "ERR")) { 672*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = LOG_ERR; 673*0Sstevel@tonic-gate } 674*0Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "EMERG")) { 675*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 676*0Sstevel@tonic-gate LOG_EMERG; 677*0Sstevel@tonic-gate } 678*0Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "ALERT")) { 679*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 680*0Sstevel@tonic-gate LOG_ALERT; 681*0Sstevel@tonic-gate } 682*0Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "CRIT")) { 683*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = LOG_CRIT; 684*0Sstevel@tonic-gate } 685*0Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "WARNING")) { 686*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 687*0Sstevel@tonic-gate LOG_WARNING; 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "NOTICE")) { 690*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 691*0Sstevel@tonic-gate LOG_NOTICE; 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "INFO")) { 694*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = LOG_INFO; 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate else if (!strcasecmp(&cp[7], "DEBUG")) { 697*0Sstevel@tonic-gate log_control.log_entries[i].lsu_severity = 698*0Sstevel@tonic-gate LOG_DEBUG; 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate else 701*0Sstevel@tonic-gate error = 1; 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate /* 704*0Sstevel@tonic-gate * If there is a facility present, then parse that. 705*0Sstevel@tonic-gate */ 706*0Sstevel@tonic-gate if (cp2) { 707*0Sstevel@tonic-gate if (!strcasecmp(cp2, "AUTH")) { 708*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_AUTH; 709*0Sstevel@tonic-gate } 710*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "KERN")) { 711*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_KERN; 712*0Sstevel@tonic-gate } 713*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "USER")) { 714*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_USER; 715*0Sstevel@tonic-gate } 716*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "MAIL")) { 717*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_MAIL; 718*0Sstevel@tonic-gate } 719*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "DAEMON")) { 720*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_DAEMON; 721*0Sstevel@tonic-gate } 722*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LPR")) { 723*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LPR; 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "NEWS")) { 726*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_NEWS; 727*0Sstevel@tonic-gate } 728*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "UUCP")) { 729*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_UUCP; 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "CRON")) { 732*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_CRON; 733*0Sstevel@tonic-gate } 734*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "AUDIT")) { 735*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_AUDIT; 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL0")) { 738*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL0; 739*0Sstevel@tonic-gate } 740*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL1")) { 741*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL1; 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL2")) { 744*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL2; 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL3")) { 747*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL3; 748*0Sstevel@tonic-gate } 749*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL4")) { 750*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL4; 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL5")) { 753*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL5; 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL6")) { 756*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL6; 757*0Sstevel@tonic-gate } 758*0Sstevel@tonic-gate else if (!strcasecmp(cp2, "LOCAL7")) { 759*0Sstevel@tonic-gate log_control.log_entries[i].lsu_facility = LOG_LOCAL7; 760*0Sstevel@tonic-gate } 761*0Sstevel@tonic-gate cp2--; 762*0Sstevel@tonic-gate *cp2 = savec; 763*0Sstevel@tonic-gate } 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate if (!error) { 766*0Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_SYSLOG; 767*0Sstevel@tonic-gate do_openlog = 1; 768*0Sstevel@tonic-gate log_facility = log_control.log_entries[i].lsu_facility; 769*0Sstevel@tonic-gate } 770*0Sstevel@tonic-gate } 771*0Sstevel@tonic-gate /* 772*0Sstevel@tonic-gate * Is this a standard error specification? 773*0Sstevel@tonic-gate */ 774*0Sstevel@tonic-gate else if (!strcasecmp(cp, "STDERR")) { 775*0Sstevel@tonic-gate if (log_control.log_entries[i].lfu_filep = 776*0Sstevel@tonic-gate fdopen(fileno(stderr), "a+")) { 777*0Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_STDERR; 778*0Sstevel@tonic-gate log_control.log_entries[i].lfu_fname = 779*0Sstevel@tonic-gate "standard error"; 780*0Sstevel@tonic-gate } 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate /* 783*0Sstevel@tonic-gate * Is this a specification of the console? 784*0Sstevel@tonic-gate */ 785*0Sstevel@tonic-gate else if (!strcasecmp(cp, "CONSOLE")) { 786*0Sstevel@tonic-gate if (log_control.log_entries[i].ldu_filep = 787*0Sstevel@tonic-gate CONSOLE_OPEN("a+")) { 788*0Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_CONSOLE; 789*0Sstevel@tonic-gate log_control.log_entries[i].ldu_devname = "console"; 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate } 792*0Sstevel@tonic-gate /* 793*0Sstevel@tonic-gate * Is this a specification of a device? 794*0Sstevel@tonic-gate */ 795*0Sstevel@tonic-gate else if (!strncasecmp(cp, "DEVICE", 6)) { 796*0Sstevel@tonic-gate /* 797*0Sstevel@tonic-gate * We handle devices very similarly to files. 798*0Sstevel@tonic-gate */ 799*0Sstevel@tonic-gate if (cp[6] == '=') { 800*0Sstevel@tonic-gate if (log_control.log_entries[i].ldu_filep = 801*0Sstevel@tonic-gate DEVICE_OPEN(&cp[7], "w")) { 802*0Sstevel@tonic-gate log_control.log_entries[i].log_type = K_LOG_DEVICE; 803*0Sstevel@tonic-gate log_control.log_entries[i].ldu_devname = &cp[7]; 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate } 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate /* 808*0Sstevel@tonic-gate * See if we successfully parsed this specification. 809*0Sstevel@tonic-gate */ 810*0Sstevel@tonic-gate if (log_control.log_entries[i].log_type == K_LOG_NONE) { 811*0Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LSPEC_PARSE_ERR_1), whoami, cp); 812*0Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LSPEC_PARSE_ERR_2), whoami); 813*0Sstevel@tonic-gate } 814*0Sstevel@tonic-gate else 815*0Sstevel@tonic-gate ngood++; 816*0Sstevel@tonic-gate } 817*0Sstevel@tonic-gate } 818*0Sstevel@tonic-gate /* 819*0Sstevel@tonic-gate * If we didn't find anything, then free our lists. 820*0Sstevel@tonic-gate */ 821*0Sstevel@tonic-gate if (ngood == 0) { 822*0Sstevel@tonic-gate for (i=0; i<log_control.log_nentries; i++) 823*0Sstevel@tonic-gate free(logging_specs[i]); 824*0Sstevel@tonic-gate } 825*0Sstevel@tonic-gate free(logging_specs); 826*0Sstevel@tonic-gate } 827*0Sstevel@tonic-gate /* 828*0Sstevel@tonic-gate * If we didn't find anything, go for the default which is to log to 829*0Sstevel@tonic-gate * the system log. 830*0Sstevel@tonic-gate */ 831*0Sstevel@tonic-gate if (ngood == 0) { 832*0Sstevel@tonic-gate if (log_control.log_entries) 833*0Sstevel@tonic-gate free(log_control.log_entries); 834*0Sstevel@tonic-gate log_control.log_entries = &def_log_entry; 835*0Sstevel@tonic-gate log_control.log_entries->log_type = K_LOG_SYSLOG; 836*0Sstevel@tonic-gate log_control.log_entries->log_2free = (krb5_pointer) NULL; 837*0Sstevel@tonic-gate log_facility = log_control.log_entries->lsu_facility = LOG_AUTH; 838*0Sstevel@tonic-gate log_control.log_entries->lsu_severity = LOG_ERR; 839*0Sstevel@tonic-gate do_openlog = 1; 840*0Sstevel@tonic-gate log_control.log_nentries = 1; 841*0Sstevel@tonic-gate } 842*0Sstevel@tonic-gate if (log_control.log_nentries) { 843*0Sstevel@tonic-gate if (log_control.log_whoami = (char *) malloc(strlen(whoami)+1)) 844*0Sstevel@tonic-gate strcpy(log_control.log_whoami, whoami); 845*0Sstevel@tonic-gate if (log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN)) 846*0Sstevel@tonic-gate gethostname(log_control.log_hostname, MAXHOSTNAMELEN); 847*0Sstevel@tonic-gate if (do_openlog) { 848*0Sstevel@tonic-gate openlog(whoami, LOG_NDELAY|LOG_PID, log_facility); 849*0Sstevel@tonic-gate log_control.log_opened = 1; 850*0Sstevel@tonic-gate } 851*0Sstevel@tonic-gate if (do_com_err) 852*0Sstevel@tonic-gate (void) set_com_err_hook(klog_com_err_proc); 853*0Sstevel@tonic-gate } 854*0Sstevel@tonic-gate return((log_control.log_nentries) ? 0 : ENOENT); 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate /* 858*0Sstevel@tonic-gate * krb5_klog_close() - Close the logging context and free all data. 859*0Sstevel@tonic-gate */ 860*0Sstevel@tonic-gate void 861*0Sstevel@tonic-gate krb5_klog_close(kcontext) 862*0Sstevel@tonic-gate krb5_context kcontext; 863*0Sstevel@tonic-gate { 864*0Sstevel@tonic-gate int lindex; 865*0Sstevel@tonic-gate (void) reset_com_err_hook(); 866*0Sstevel@tonic-gate for (lindex = 0; lindex < log_control.log_nentries; lindex++) { 867*0Sstevel@tonic-gate switch (log_control.log_entries[lindex].log_type) { 868*0Sstevel@tonic-gate case K_LOG_FILE: 869*0Sstevel@tonic-gate case K_LOG_STDERR: 870*0Sstevel@tonic-gate /* 871*0Sstevel@tonic-gate * Files/standard error. 872*0Sstevel@tonic-gate */ 873*0Sstevel@tonic-gate fclose(log_control.log_entries[lindex].lfu_filep); 874*0Sstevel@tonic-gate break; 875*0Sstevel@tonic-gate case K_LOG_CONSOLE: 876*0Sstevel@tonic-gate case K_LOG_DEVICE: 877*0Sstevel@tonic-gate /* 878*0Sstevel@tonic-gate * Devices (may need special handling) 879*0Sstevel@tonic-gate */ 880*0Sstevel@tonic-gate DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep); 881*0Sstevel@tonic-gate break; 882*0Sstevel@tonic-gate case K_LOG_SYSLOG: 883*0Sstevel@tonic-gate /* 884*0Sstevel@tonic-gate * System log. 885*0Sstevel@tonic-gate */ 886*0Sstevel@tonic-gate break; 887*0Sstevel@tonic-gate default: 888*0Sstevel@tonic-gate break; 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate if (log_control.log_entries[lindex].log_2free) 891*0Sstevel@tonic-gate free(log_control.log_entries[lindex].log_2free); 892*0Sstevel@tonic-gate } 893*0Sstevel@tonic-gate if (log_control.log_entries != &def_log_entry) 894*0Sstevel@tonic-gate free(log_control.log_entries); 895*0Sstevel@tonic-gate log_control.log_entries = (struct log_entry *) NULL; 896*0Sstevel@tonic-gate log_control.log_nentries = 0; 897*0Sstevel@tonic-gate if (log_control.log_whoami) 898*0Sstevel@tonic-gate free(log_control.log_whoami); 899*0Sstevel@tonic-gate log_control.log_whoami = (char *) NULL; 900*0Sstevel@tonic-gate if (log_control.log_hostname) 901*0Sstevel@tonic-gate free(log_control.log_hostname); 902*0Sstevel@tonic-gate log_control.log_hostname = (char *) NULL; 903*0Sstevel@tonic-gate if (log_control.log_opened) 904*0Sstevel@tonic-gate closelog(); 905*0Sstevel@tonic-gate } 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate /* 908*0Sstevel@tonic-gate * severity2string() - Convert a severity to a string. 909*0Sstevel@tonic-gate */ 910*0Sstevel@tonic-gate static char * 911*0Sstevel@tonic-gate severity2string(severity) 912*0Sstevel@tonic-gate int severity; 913*0Sstevel@tonic-gate { 914*0Sstevel@tonic-gate int s; 915*0Sstevel@tonic-gate const char *ss; 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate s = severity & LOG_PRIMASK; 918*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_UFO_STRING); 919*0Sstevel@tonic-gate switch (s) { 920*0Sstevel@tonic-gate case LOG_EMERG: 921*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_EMERG_STRING); 922*0Sstevel@tonic-gate break; 923*0Sstevel@tonic-gate case LOG_ALERT: 924*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_ALERT_STRING); 925*0Sstevel@tonic-gate break; 926*0Sstevel@tonic-gate case LOG_CRIT: 927*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_CRIT_STRING); 928*0Sstevel@tonic-gate break; 929*0Sstevel@tonic-gate case LOG_ERR: 930*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_ERR_STRING); 931*0Sstevel@tonic-gate break; 932*0Sstevel@tonic-gate case LOG_WARNING: 933*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_WARNING_STRING); 934*0Sstevel@tonic-gate break; 935*0Sstevel@tonic-gate case LOG_NOTICE: 936*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_NOTICE_STRING); 937*0Sstevel@tonic-gate break; 938*0Sstevel@tonic-gate case LOG_INFO: 939*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_INFO_STRING); 940*0Sstevel@tonic-gate break; 941*0Sstevel@tonic-gate case LOG_DEBUG: 942*0Sstevel@tonic-gate ss = krb5_log_error_table(LOG_DEBUG_STRING); 943*0Sstevel@tonic-gate break; 944*0Sstevel@tonic-gate } 945*0Sstevel@tonic-gate return((char *) ss); 946*0Sstevel@tonic-gate } 947*0Sstevel@tonic-gate 948*0Sstevel@tonic-gate /* 949*0Sstevel@tonic-gate * krb5_klog_syslog() - Simulate the calling sequence of syslog(3), while 950*0Sstevel@tonic-gate * also performing the logging redirection as specified 951*0Sstevel@tonic-gate * by krb5_klog_init(). 952*0Sstevel@tonic-gate */ 953*0Sstevel@tonic-gate static int 954*0Sstevel@tonic-gate klog_vsyslog(priority, format, arglist) 955*0Sstevel@tonic-gate int priority; 956*0Sstevel@tonic-gate const char *format; 957*0Sstevel@tonic-gate va_list arglist; 958*0Sstevel@tonic-gate { 959*0Sstevel@tonic-gate char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE]; 960*0Sstevel@tonic-gate int lindex; 961*0Sstevel@tonic-gate char *syslogp; 962*0Sstevel@tonic-gate char *cp; 963*0Sstevel@tonic-gate time_t now; 964*0Sstevel@tonic-gate size_t soff; 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate /* 967*0Sstevel@tonic-gate * Format a syslog-esque message of the format: 968*0Sstevel@tonic-gate * 969*0Sstevel@tonic-gate * (verbose form) 970*0Sstevel@tonic-gate * <date> <hostname> <id>[<pid>](<priority>): <message> 971*0Sstevel@tonic-gate * 972*0Sstevel@tonic-gate * (short form) 973*0Sstevel@tonic-gate * <date> <message> 974*0Sstevel@tonic-gate */ 975*0Sstevel@tonic-gate cp = outbuf; 976*0Sstevel@tonic-gate (void) time(&now); 977*0Sstevel@tonic-gate /* 978*0Sstevel@tonic-gate * Format the date: mon dd hh:mm:ss 979*0Sstevel@tonic-gate */ 980*0Sstevel@tonic-gate soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", localtime(&now)); 981*0Sstevel@tonic-gate if (soff > 0) 982*0Sstevel@tonic-gate cp += soff; 983*0Sstevel@tonic-gate else 984*0Sstevel@tonic-gate return(-1); 985*0Sstevel@tonic-gate #ifdef VERBOSE_LOGS 986*0Sstevel@tonic-gate sprintf(cp, " %s %s[%d](%s): ", 987*0Sstevel@tonic-gate log_control.log_hostname, log_control.log_whoami, getpid(), 988*0Sstevel@tonic-gate severity2string(priority)); 989*0Sstevel@tonic-gate #else 990*0Sstevel@tonic-gate sprintf(cp, " "); 991*0Sstevel@tonic-gate #endif 992*0Sstevel@tonic-gate syslogp = &outbuf[strlen(outbuf)]; 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate /* Now format the actual message */ 995*0Sstevel@tonic-gate vsprintf(syslogp, format, arglist); 996*0Sstevel@tonic-gate 997*0Sstevel@tonic-gate /* 998*0Sstevel@tonic-gate * Now that we have the message formatted, perform the output to each 999*0Sstevel@tonic-gate * logging specification. 1000*0Sstevel@tonic-gate */ 1001*0Sstevel@tonic-gate for (lindex = 0; lindex < log_control.log_nentries; lindex++) { 1002*0Sstevel@tonic-gate switch (log_control.log_entries[lindex].log_type) { 1003*0Sstevel@tonic-gate case K_LOG_FILE: 1004*0Sstevel@tonic-gate 1005*0Sstevel@tonic-gate klog_rotate(&log_control.log_entries[lindex]); 1006*0Sstevel@tonic-gate /*FALLTHRU*/ 1007*0Sstevel@tonic-gate case K_LOG_STDERR: 1008*0Sstevel@tonic-gate /* 1009*0Sstevel@tonic-gate * Files/standard error. 1010*0Sstevel@tonic-gate */ 1011*0Sstevel@tonic-gate if (fprintf(log_control.log_entries[lindex].lfu_filep, 1012*0Sstevel@tonic-gate outbuf) < 0) { 1013*0Sstevel@tonic-gate /* Attempt to report error */ 1014*0Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LOG_FILE_ERR), 1015*0Sstevel@tonic-gate log_control.log_entries[lindex].lfu_fname); 1016*0Sstevel@tonic-gate } 1017*0Sstevel@tonic-gate else { 1018*0Sstevel@tonic-gate fprintf(log_control.log_entries[lindex].lfu_filep, "\n"); 1019*0Sstevel@tonic-gate fflush(log_control.log_entries[lindex].lfu_filep); 1020*0Sstevel@tonic-gate } 1021*0Sstevel@tonic-gate break; 1022*0Sstevel@tonic-gate case K_LOG_CONSOLE: 1023*0Sstevel@tonic-gate case K_LOG_DEVICE: 1024*0Sstevel@tonic-gate /* 1025*0Sstevel@tonic-gate * Devices (may need special handling) 1026*0Sstevel@tonic-gate */ 1027*0Sstevel@tonic-gate if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep, 1028*0Sstevel@tonic-gate outbuf) < 0) { 1029*0Sstevel@tonic-gate /* Attempt to report error */ 1030*0Sstevel@tonic-gate fprintf(stderr, krb5_log_error_table(LOG_DEVICE_ERR), 1031*0Sstevel@tonic-gate log_control.log_entries[lindex].ldu_devname); 1032*0Sstevel@tonic-gate } 1033*0Sstevel@tonic-gate break; 1034*0Sstevel@tonic-gate case K_LOG_SYSLOG: 1035*0Sstevel@tonic-gate /* 1036*0Sstevel@tonic-gate * System log. 1037*0Sstevel@tonic-gate */ 1038*0Sstevel@tonic-gate 1039*0Sstevel@tonic-gate /* Log the message with our header trimmed off */ 1040*0Sstevel@tonic-gate syslog(priority, syslogp); 1041*0Sstevel@tonic-gate break; 1042*0Sstevel@tonic-gate default: 1043*0Sstevel@tonic-gate break; 1044*0Sstevel@tonic-gate } 1045*0Sstevel@tonic-gate } 1046*0Sstevel@tonic-gate return(0); 1047*0Sstevel@tonic-gate } 1048*0Sstevel@tonic-gate 1049*0Sstevel@tonic-gate int 1050*0Sstevel@tonic-gate krb5_klog_syslog(int priority, const char *format, ...) 1051*0Sstevel@tonic-gate { 1052*0Sstevel@tonic-gate int retval; 1053*0Sstevel@tonic-gate va_list pvar; 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate va_start(pvar, format); 1056*0Sstevel@tonic-gate retval = klog_vsyslog(priority, format, pvar); 1057*0Sstevel@tonic-gate va_end(pvar); 1058*0Sstevel@tonic-gate return(retval); 1059*0Sstevel@tonic-gate } 1060