Blame src/lib/kadm5/logger.c

Packit fd8b60
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit fd8b60
/* lib/kadm5/logger.c */
Packit fd8b60
/*
Packit fd8b60
 * Copyright 1995, 2007 by the Massachusetts Institute of Technology.
Packit fd8b60
 * All Rights Reserved.
Packit fd8b60
 *
Packit fd8b60
 * Export of this software from the United States of America may
Packit fd8b60
 *   require a specific license from the United States Government.
Packit fd8b60
 *   It is the responsibility of any person or organization contemplating
Packit fd8b60
 *   export to obtain such a license before exporting.
Packit fd8b60
 *
Packit fd8b60
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
Packit fd8b60
 * distribute this software and its documentation for any purpose and
Packit fd8b60
 * without fee is hereby granted, provided that the above copyright
Packit fd8b60
 * notice appear in all copies and that both that copyright notice and
Packit fd8b60
 * this permission notice appear in supporting documentation, and that
Packit fd8b60
 * the name of M.I.T. not be used in advertising or publicity pertaining
Packit fd8b60
 * to distribution of the software without specific, written prior
Packit fd8b60
 * permission.  Furthermore if you modify this software you must label
Packit fd8b60
 * your software as modified software and not distribute it in such a
Packit fd8b60
 * fashion that it might be confused with the original M.I.T. software.
Packit fd8b60
 * M.I.T. makes no representations about the suitability of
Packit fd8b60
 * this software for any purpose.  It is provided "as is" without express
Packit fd8b60
 * or implied warranty.
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
/* KADM5 wants non-syslog log files to contain syslog-like entries */
Packit fd8b60
#define VERBOSE_LOGS
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * logger.c     - Handle logging functions for those who want it.
Packit fd8b60
 */
Packit fd8b60
#include "k5-int.h"
Packit fd8b60
#include "adm_proto.h"
Packit fd8b60
#include "com_err.h"
Packit fd8b60
#include <stdio.h>
Packit fd8b60
#include <ctype.h>
Packit fd8b60
#include <syslog.h>
Packit fd8b60
#include <stdarg.h>
Packit fd8b60
Packit fd8b60
#define KRB5_KLOG_MAX_ERRMSG_SIZE       2048
Packit fd8b60
#ifndef MAXHOSTNAMELEN
Packit fd8b60
#define MAXHOSTNAMELEN  256
Packit fd8b60
#endif  /* MAXHOSTNAMELEN */
Packit fd8b60
Packit fd8b60
/* This is to assure that we have at least one match in the syslog stuff */
Packit fd8b60
#ifndef LOG_AUTH
Packit fd8b60
#define LOG_AUTH        0
Packit fd8b60
#endif  /* LOG_AUTH */
Packit fd8b60
#ifndef LOG_ERR
Packit fd8b60
#define LOG_ERR         0
Packit fd8b60
#endif  /* LOG_ERR */
Packit fd8b60
Packit fd8b60
#define lspec_parse_err_1       _("%s: cannot parse <%s>\n")
Packit fd8b60
#define lspec_parse_err_2       _("%s: warning - logging entry syntax error\n")
Packit fd8b60
#define log_file_err            _("%s: error writing to %s\n")
Packit fd8b60
#define log_device_err          _("%s: error writing to %s device\n")
Packit fd8b60
#define log_ufo_string          "?\?\?" /* nb: avoid trigraphs */
Packit fd8b60
#define log_emerg_string        _("EMERGENCY")
Packit fd8b60
#define log_alert_string        _("ALERT")
Packit fd8b60
#define log_crit_string         _("CRITICAL")
Packit fd8b60
#define log_err_string          _("Error")
Packit fd8b60
#define log_warning_string      _("Warning")
Packit fd8b60
#define log_notice_string       _("Notice")
Packit fd8b60
#define log_info_string         _("info")
Packit fd8b60
#define log_debug_string        _("debug")
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * Output logging.
Packit fd8b60
 *
Packit fd8b60
 * Output logging is now controlled by the configuration file.  We can specify
Packit fd8b60
 * the following syntaxes under the [logging]->entity specification.
Packit fd8b60
 *      FILE<opentype><pathname>
Packit fd8b60
 *      SYSLOG[=<severity>[:<facility>]]
Packit fd8b60
 *      STDERR
Packit fd8b60
 *      CONSOLE
Packit fd8b60
 *      DEVICE=<device-spec>
Packit fd8b60
 *
Packit fd8b60
 * Where:
Packit fd8b60
 *      <opentype> is ":" for open/append, "=" for open/create.
Packit fd8b60
 *      <pathname> is a valid path name.
Packit fd8b60
 *      <severity> is one of: (default = ERR)
Packit fd8b60
 *              EMERG
Packit fd8b60
 *              ALERT
Packit fd8b60
 *              CRIT
Packit fd8b60
 *              ERR
Packit fd8b60
 *              WARNING
Packit fd8b60
 *              NOTICE
Packit fd8b60
 *              INFO
Packit fd8b60
 *              DEBUG
Packit fd8b60
 *      <facility> is one of: (default = AUTH)
Packit fd8b60
 *              KERN
Packit fd8b60
 *              USER
Packit fd8b60
 *              MAIL
Packit fd8b60
 *              DAEMON
Packit fd8b60
 *              AUTH
Packit fd8b60
 *              LPR
Packit fd8b60
 *              NEWS
Packit fd8b60
 *              UUCP
Packit fd8b60
 *              CRON
Packit fd8b60
 *              LOCAL0..LOCAL7
Packit fd8b60
 *      <device-spec> is a valid device specification.
Packit fd8b60
 */
Packit fd8b60
struct log_entry {
Packit fd8b60
    enum log_type { K_LOG_FILE,
Packit fd8b60
                    K_LOG_SYSLOG,
Packit fd8b60
                    K_LOG_STDERR,
Packit fd8b60
                    K_LOG_CONSOLE,
Packit fd8b60
                    K_LOG_DEVICE,
Packit fd8b60
                    K_LOG_NONE } log_type;
Packit fd8b60
    krb5_pointer log_2free;
Packit fd8b60
    union log_union {
Packit fd8b60
        struct log_file {
Packit fd8b60
            FILE        *lf_filep;
Packit fd8b60
            char        *lf_fname;
Packit fd8b60
        } log_file;
Packit fd8b60
        struct log_syslog {
Packit fd8b60
            int         ls_facility;
Packit fd8b60
        } log_syslog;
Packit fd8b60
        struct log_device {
Packit fd8b60
            FILE        *ld_filep;
Packit fd8b60
            char        *ld_devname;
Packit fd8b60
        } log_device;
Packit fd8b60
    } log_union;
Packit fd8b60
};
Packit fd8b60
#define lfu_filep       log_union.log_file.lf_filep
Packit fd8b60
#define lfu_fname       log_union.log_file.lf_fname
Packit fd8b60
#define lsu_facility    log_union.log_syslog.ls_facility
Packit fd8b60
#define ldu_filep       log_union.log_device.ld_filep
Packit fd8b60
#define ldu_devname     log_union.log_device.ld_devname
Packit fd8b60
Packit fd8b60
struct log_control {
Packit fd8b60
    struct log_entry    *log_entries;
Packit fd8b60
    int                 log_nentries;
Packit fd8b60
    char                *log_whoami;
Packit fd8b60
    char                *log_hostname;
Packit fd8b60
    krb5_boolean        log_opened;
Packit fd8b60
    krb5_boolean        log_debug;
Packit fd8b60
};
Packit fd8b60
Packit fd8b60
static struct log_control log_control = {
Packit fd8b60
    (struct log_entry *) NULL,
Packit fd8b60
    0,
Packit fd8b60
    (char *) NULL,
Packit fd8b60
    (char *) NULL,
Packit fd8b60
    0
Packit fd8b60
};
Packit fd8b60
static struct log_entry def_log_entry;
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * These macros define any special processing that needs to happen for
Packit fd8b60
 * devices.  For unix, of course, this is hardly anything.
Packit fd8b60
 */
Packit fd8b60
#define DEVICE_OPEN(d, m)       fopen(d, m)
Packit fd8b60
#define CONSOLE_OPEN(m)         fopen("/dev/console", m)
Packit fd8b60
#define DEVICE_PRINT(f, m)      ((fprintf(f, "%s\r\n", m) >= 0) ?       \
Packit fd8b60
                                 (fflush(f), 0) :                       \
Packit fd8b60
                                 -1)
Packit fd8b60
#define DEVICE_CLOSE(d)         fclose(d)
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * klog_com_err_proc()  - Handle com_err(3) messages as specified by the
Packit fd8b60
 *                        profile.
Packit fd8b60
 */
Packit fd8b60
static krb5_context err_context;
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap)
Packit fd8b60
#if !defined(__cplusplus) && (__GNUC__ > 2)
Packit fd8b60
    __attribute__((__format__(__printf__, 3, 0)))
Packit fd8b60
#endif
Packit fd8b60
    ;
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * Write com_err() messages to the configured logging devices.  Ignore whoami,
Packit fd8b60
 * as krb5_klog_init() already received a whoami value.  If code is nonzero,
Packit fd8b60
 * log its error message (retrieved using err_context) and the formatted
Packit fd8b60
 * message at error severity.  If code is zero, log the formatted message at
Packit fd8b60
 * informational severity.
Packit fd8b60
 */
Packit fd8b60
static void
Packit fd8b60
klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap)
Packit fd8b60
{
Packit fd8b60
    struct k5buf buf;
Packit fd8b60
    const char *emsg;
Packit fd8b60
Packit fd8b60
    if (format == NULL)
Packit fd8b60
        return;
Packit fd8b60
Packit fd8b60
    k5_buf_init_dynamic(&buf;;
Packit fd8b60
Packit fd8b60
    if (code) {
Packit fd8b60
        /* Start with the error message and a separator. */
Packit fd8b60
        emsg = krb5_get_error_message(err_context, code);
Packit fd8b60
        k5_buf_add(&buf, emsg);
Packit fd8b60
        krb5_free_error_message(err_context, emsg);
Packit fd8b60
        k5_buf_add(&buf, " - ");
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* Add the formatted message. */
Packit fd8b60
    k5_buf_add_vfmt(&buf, format, ap);
Packit fd8b60
Packit fd8b60
    if (k5_buf_status(&buf) == 0)
Packit fd8b60
        krb5_klog_syslog(code ? LOG_ERR : LOG_INFO, "%s", (char *)buf.data);
Packit fd8b60
Packit fd8b60
    k5_buf_free(&buf;;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * krb5_klog_init()     - Initialize logging.
Packit fd8b60
 *
Packit fd8b60
 * This routine parses the syntax described above to specify destinations for
Packit fd8b60
 * com_err(3) or krb5_klog_syslog() messages generated by the caller.
Packit fd8b60
 *
Packit fd8b60
 * Parameters:
Packit fd8b60
 *      kcontext        - Kerberos context.
Packit fd8b60
 *      ename           - Entity name as it is to appear in the profile.
Packit fd8b60
 *      whoami          - Entity name as it is to appear in error output.
Packit fd8b60
 *      do_com_err      - Take over com_err(3) processing.
Packit fd8b60
 *
Packit fd8b60
 * Implicit inputs:
Packit fd8b60
 *      stderr          - This is where STDERR output goes.
Packit fd8b60
 *
Packit fd8b60
 * Implicit outputs:
Packit fd8b60
 *      log_nentries    - Number of log entries, both valid and invalid.
Packit fd8b60
 *      log_control     - List of entries (log_nentries long) which contains
Packit fd8b60
 *                        data for klog_com_err_proc() to use to determine
Packit fd8b60
 *                        where/how to send output.
Packit fd8b60
 */
Packit fd8b60
krb5_error_code
Packit fd8b60
krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err)
Packit fd8b60
{
Packit fd8b60
    const char  *logging_profent[3];
Packit fd8b60
    const char  *logging_defent[3];
Packit fd8b60
    char        **logging_specs;
Packit fd8b60
    int         i, ngood, fd, append;
Packit fd8b60
    char        *cp, *cp2;
Packit fd8b60
    char        savec = '\0';
Packit fd8b60
    int         error, debug;
Packit fd8b60
    int         do_openlog, log_facility;
Packit fd8b60
    FILE        *f = NULL;
Packit fd8b60
Packit fd8b60
    /* Initialize */
Packit fd8b60
    do_openlog = 0;
Packit fd8b60
    log_facility = 0;
Packit fd8b60
Packit fd8b60
    err_context = kcontext;
Packit fd8b60
Packit fd8b60
    /* Look up [logging]->debug in the profile to see if we should include
Packit fd8b60
     * debug messages for types other than syslog.  Default to false. */
Packit fd8b60
    if (!profile_get_boolean(kcontext->profile, KRB5_CONF_LOGGING,
Packit fd8b60
                             KRB5_CONF_DEBUG, NULL, 0, &debug))
Packit fd8b60
        log_control.log_debug = debug;
Packit fd8b60
Packit fd8b60
    /*
Packit fd8b60
     * Look up [logging]-><ename> in the profile.  If that doesn't
Packit fd8b60
     * succeed, then look for [logging]->default.
Packit fd8b60
     */
Packit fd8b60
    logging_profent[0] = KRB5_CONF_LOGGING;
Packit fd8b60
    logging_profent[1] = ename;
Packit fd8b60
    logging_profent[2] = (char *) NULL;
Packit fd8b60
    logging_defent[0] = KRB5_CONF_LOGGING;
Packit fd8b60
    logging_defent[1] = KRB5_CONF_DEFAULT;
Packit fd8b60
    logging_defent[2] = (char *) NULL;
Packit fd8b60
    logging_specs = (char **) NULL;
Packit fd8b60
    ngood = 0;
Packit fd8b60
    log_control.log_nentries = 0;
Packit fd8b60
    if (!profile_get_values(kcontext->profile,
Packit fd8b60
                            logging_profent,
Packit fd8b60
                            &logging_specs) ||
Packit fd8b60
        !profile_get_values(kcontext->profile,
Packit fd8b60
                            logging_defent,
Packit fd8b60
                            &logging_specs)) {
Packit fd8b60
        /*
Packit fd8b60
         * We have a match, so we first count the number of elements
Packit fd8b60
         */
Packit fd8b60
        for (log_control.log_nentries = 0;
Packit fd8b60
             logging_specs[log_control.log_nentries];
Packit fd8b60
             log_control.log_nentries++);
Packit fd8b60
Packit fd8b60
        /*
Packit fd8b60
         * Now allocate our structure.
Packit fd8b60
         */
Packit fd8b60
        log_control.log_entries = (struct log_entry *)
Packit fd8b60
            malloc(log_control.log_nentries * sizeof(struct log_entry));
Packit fd8b60
        if (log_control.log_entries) {
Packit fd8b60
            /*
Packit fd8b60
             * Scan through the list.
Packit fd8b60
             */
Packit fd8b60
            for (i=0; i
Packit fd8b60
                log_control.log_entries[i].log_type = K_LOG_NONE;
Packit fd8b60
                log_control.log_entries[i].log_2free = logging_specs[i];
Packit fd8b60
                /*
Packit fd8b60
                 * The format is:
Packit fd8b60
                 *      <whitespace><data><whitespace>
Packit fd8b60
                 * so, trim off the leading and trailing whitespace here.
Packit fd8b60
                 */
Packit fd8b60
                for (cp = logging_specs[i]; isspace((int) *cp); cp++);
Packit fd8b60
                for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1];
Packit fd8b60
                     isspace((int) *cp2); cp2--);
Packit fd8b60
                cp2++;
Packit fd8b60
                *cp2 = '\0';
Packit fd8b60
                /*
Packit fd8b60
                 * Is this a file?
Packit fd8b60
                 */
Packit fd8b60
                if (!strncasecmp(cp, "FILE", 4)) {
Packit fd8b60
                    /*
Packit fd8b60
                     * Check for append/overwrite, then open the file.
Packit fd8b60
                     */
Packit fd8b60
                    append = (cp[4] == ':') ? O_APPEND : 0;
Packit fd8b60
                    if (append || cp[4] == '=') {
Packit Service e737ee
                        fd = open(&cp[5], O_CREAT | O_WRONLY | append,
Packit fd8b60
                                  S_IRUSR | S_IWUSR | S_IRGRP);
Packit fd8b60
                        if (fd != -1)
Packit fd8b60
                            f = fdopen(fd, append ? "a" : "w");
Packit fd8b60
                        if (fd == -1 || f == NULL) {
Packit fd8b60
                            fprintf(stderr,"Couldn't open log file %s: %s\n",
Packit fd8b60
                                    &cp[5], error_message(errno));
Packit fd8b60
                            continue;
Packit fd8b60
                        }
Packit fd8b60
                        set_cloexec_file(f);
Packit fd8b60
                        log_control.log_entries[i].lfu_filep = f;
Packit fd8b60
                        log_control.log_entries[i].log_type = K_LOG_FILE;
Packit fd8b60
                        log_control.log_entries[i].lfu_fname = &cp[5];
Packit fd8b60
                    }
Packit fd8b60
                }
Packit fd8b60
                /*
Packit fd8b60
                 * Is this a syslog?
Packit fd8b60
                 */
Packit fd8b60
                else if (!strncasecmp(cp, "SYSLOG", 6)) {
Packit fd8b60
                    error = 0;
Packit fd8b60
                    log_control.log_entries[i].lsu_facility = LOG_AUTH;
Packit fd8b60
                    /*
Packit fd8b60
                     * Is there a severify (which is now ignored) specified?
Packit fd8b60
                     */
Packit fd8b60
                    if (cp[6] == ':') {
Packit fd8b60
                        /*
Packit fd8b60
                         * Find the end of the severity.
Packit fd8b60
                         */
Packit fd8b60
                        cp2 = strchr(&cp[7], ':');
Packit fd8b60
                        if (cp2) {
Packit fd8b60
                            savec = *cp2;
Packit fd8b60
                            *cp2 = '\0';
Packit fd8b60
                            cp2++;
Packit fd8b60
                        }
Packit fd8b60
Packit fd8b60
                        /*
Packit fd8b60
                         * If there is a facility present, then parse that.
Packit fd8b60
                         */
Packit fd8b60
                        if (cp2) {
Packit fd8b60
                            static const struct {
Packit fd8b60
                                const char *name;
Packit fd8b60
                                int value;
Packit fd8b60
                            } facilities[] = {
Packit fd8b60
                                { "AUTH",       LOG_AUTH        },
Packit fd8b60
#ifdef  LOG_AUTHPRIV
Packit fd8b60
                                { "AUTHPRIV",   LOG_AUTHPRIV    },
Packit fd8b60
#endif  /* LOG_AUTHPRIV */
Packit fd8b60
#ifdef  LOG_KERN
Packit fd8b60
                                { "KERN",       LOG_KERN        },
Packit fd8b60
#endif  /* LOG_KERN */
Packit fd8b60
#ifdef  LOG_USER
Packit fd8b60
                                { "USER",       LOG_USER        },
Packit fd8b60
#endif  /* LOG_USER */
Packit fd8b60
#ifdef  LOG_MAIL
Packit fd8b60
                                { "MAIL",       LOG_MAIL        },
Packit fd8b60
#endif  /* LOG_MAIL */
Packit fd8b60
#ifdef  LOG_DAEMON
Packit fd8b60
                                { "DAEMON",     LOG_DAEMON      },
Packit fd8b60
#endif  /* LOG_DAEMON */
Packit fd8b60
#ifdef  LOG_FTP
Packit fd8b60
                                { "FTP",        LOG_FTP         },
Packit fd8b60
#endif  /* LOG_FTP */
Packit fd8b60
#ifdef  LOG_LPR
Packit fd8b60
                                { "LPR",        LOG_LPR         },
Packit fd8b60
#endif  /* LOG_LPR */
Packit fd8b60
#ifdef  LOG_NEWS
Packit fd8b60
                                { "NEWS",       LOG_NEWS        },
Packit fd8b60
#endif  /* LOG_NEWS */
Packit fd8b60
#ifdef  LOG_UUCP
Packit fd8b60
                                { "UUCP",       LOG_UUCP        },
Packit fd8b60
#endif  /* LOG_UUCP */
Packit fd8b60
#ifdef  LOG_CRON
Packit fd8b60
                                { "CRON",       LOG_CRON        },
Packit fd8b60
#endif  /* LOG_CRON */
Packit fd8b60
#ifdef  LOG_LOCAL0
Packit fd8b60
                                { "LOCAL0",     LOG_LOCAL0      },
Packit fd8b60
#endif  /* LOG_LOCAL0 */
Packit fd8b60
#ifdef  LOG_LOCAL1
Packit fd8b60
                                { "LOCAL1",     LOG_LOCAL1      },
Packit fd8b60
#endif  /* LOG_LOCAL1 */
Packit fd8b60
#ifdef  LOG_LOCAL2
Packit fd8b60
                                { "LOCAL2",     LOG_LOCAL2      },
Packit fd8b60
#endif  /* LOG_LOCAL2 */
Packit fd8b60
#ifdef  LOG_LOCAL3
Packit fd8b60
                                { "LOCAL3",     LOG_LOCAL3      },
Packit fd8b60
#endif  /* LOG_LOCAL3 */
Packit fd8b60
#ifdef  LOG_LOCAL4
Packit fd8b60
                                { "LOCAL4",     LOG_LOCAL4      },
Packit fd8b60
#endif  /* LOG_LOCAL4 */
Packit fd8b60
#ifdef  LOG_LOCAL5
Packit fd8b60
                                { "LOCAL5",     LOG_LOCAL5      },
Packit fd8b60
#endif  /* LOG_LOCAL5 */
Packit fd8b60
#ifdef  LOG_LOCAL6
Packit fd8b60
                                { "LOCAL6",     LOG_LOCAL6      },
Packit fd8b60
#endif  /* LOG_LOCAL6 */
Packit fd8b60
#ifdef  LOG_LOCAL7
Packit fd8b60
                                { "LOCAL7",     LOG_LOCAL7      },
Packit fd8b60
#endif  /* LOG_LOCAL7 */
Packit fd8b60
                            };
Packit fd8b60
                            unsigned int j;
Packit fd8b60
Packit fd8b60
                            for (j = 0; j < sizeof(facilities)/sizeof(facilities[0]); j++)
Packit fd8b60
                                if (!strcasecmp(cp2, facilities[j].name)) {
Packit fd8b60
                                    log_control.log_entries[i].lsu_facility = facilities[j].value;
Packit fd8b60
                                    break;
Packit fd8b60
                                }
Packit fd8b60
                            cp2--;
Packit fd8b60
                            *cp2 = savec;
Packit fd8b60
                        }
Packit fd8b60
                    }
Packit fd8b60
                    if (!error) {
Packit fd8b60
                        log_control.log_entries[i].log_type = K_LOG_SYSLOG;
Packit fd8b60
                        do_openlog = 1;
Packit fd8b60
                        log_facility = log_control.log_entries[i].lsu_facility;
Packit fd8b60
                    }
Packit fd8b60
                }
Packit fd8b60
                /*
Packit fd8b60
                 * Is this a standard error specification?
Packit fd8b60
                 */
Packit fd8b60
                else if (!strcasecmp(cp, "STDERR")) {
Packit fd8b60
                    log_control.log_entries[i].lfu_filep =
Packit fd8b60
                        fdopen(fileno(stderr), "w");
Packit fd8b60
                    if (log_control.log_entries[i].lfu_filep) {
Packit fd8b60
                        log_control.log_entries[i].log_type = K_LOG_STDERR;
Packit fd8b60
                        log_control.log_entries[i].lfu_fname =
Packit fd8b60
                            "standard error";
Packit fd8b60
                    }
Packit fd8b60
                }
Packit fd8b60
                /*
Packit fd8b60
                 * Is this a specification of the console?
Packit fd8b60
                 */
Packit fd8b60
                else if (!strcasecmp(cp, "CONSOLE")) {
Packit fd8b60
                    log_control.log_entries[i].ldu_filep =
Packit fd8b60
                        CONSOLE_OPEN("a+");
Packit fd8b60
                    if (log_control.log_entries[i].ldu_filep) {
Packit fd8b60
                        set_cloexec_file(log_control.log_entries[i].ldu_filep);
Packit fd8b60
                        log_control.log_entries[i].log_type = K_LOG_CONSOLE;
Packit fd8b60
                        log_control.log_entries[i].ldu_devname = "console";
Packit fd8b60
                    }
Packit fd8b60
                }
Packit fd8b60
                /*
Packit fd8b60
                 * Is this a specification of a device?
Packit fd8b60
                 */
Packit fd8b60
                else if (!strncasecmp(cp, "DEVICE", 6)) {
Packit fd8b60
                    /*
Packit fd8b60
                     * We handle devices very similarly to files.
Packit fd8b60
                     */
Packit fd8b60
                    if (cp[6] == '=') {
Packit fd8b60
                        log_control.log_entries[i].ldu_filep =
Packit fd8b60
                            DEVICE_OPEN(&cp[7], "w");
Packit fd8b60
                        if (log_control.log_entries[i].ldu_filep) {
Packit fd8b60
                            set_cloexec_file(log_control.log_entries[i].ldu_filep);
Packit fd8b60
                            log_control.log_entries[i].log_type = K_LOG_DEVICE;
Packit fd8b60
                            log_control.log_entries[i].ldu_devname = &cp[7];
Packit fd8b60
                        }
Packit fd8b60
                    }
Packit fd8b60
                }
Packit fd8b60
                /*
Packit fd8b60
                 * See if we successfully parsed this specification.
Packit fd8b60
                 */
Packit fd8b60
                if (log_control.log_entries[i].log_type == K_LOG_NONE) {
Packit fd8b60
                    fprintf(stderr, lspec_parse_err_1, whoami, cp);
Packit fd8b60
                    fprintf(stderr, lspec_parse_err_2, whoami);
Packit fd8b60
                }
Packit fd8b60
                else
Packit fd8b60
                    ngood++;
Packit fd8b60
            }
Packit fd8b60
        }
Packit fd8b60
        /*
Packit fd8b60
         * If we didn't find anything, then free our lists.
Packit fd8b60
         */
Packit fd8b60
        if (ngood == 0) {
Packit fd8b60
            for (i=0; i
Packit fd8b60
                free(logging_specs[i]);
Packit fd8b60
        }
Packit fd8b60
        free(logging_specs);
Packit fd8b60
    }
Packit fd8b60
    /*
Packit fd8b60
     * If we didn't find anything, go for the default which is to log to
Packit fd8b60
     * the system log.
Packit fd8b60
     */
Packit fd8b60
    if (ngood == 0) {
Packit fd8b60
        if (log_control.log_entries)
Packit fd8b60
            free(log_control.log_entries);
Packit fd8b60
        log_control.log_entries = &def_log_entry;
Packit fd8b60
        log_control.log_entries->log_type = K_LOG_SYSLOG;
Packit fd8b60
        log_control.log_entries->log_2free = (krb5_pointer) NULL;
Packit fd8b60
        log_facility = log_control.log_entries->lsu_facility = LOG_AUTH;
Packit fd8b60
        do_openlog = 1;
Packit fd8b60
        log_control.log_nentries = 1;
Packit fd8b60
    }
Packit fd8b60
    if (log_control.log_nentries) {
Packit fd8b60
        log_control.log_whoami = strdup(whoami);
Packit fd8b60
        log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1);
Packit fd8b60
        if (log_control.log_hostname) {
Packit fd8b60
            if (gethostname(log_control.log_hostname, MAXHOSTNAMELEN) == -1) {
Packit fd8b60
                free(log_control.log_hostname);
Packit fd8b60
                log_control.log_hostname = NULL;
Packit fd8b60
            } else
Packit fd8b60
                log_control.log_hostname[MAXHOSTNAMELEN] = '\0';
Packit fd8b60
        }
Packit fd8b60
        if (do_openlog) {
Packit fd8b60
            openlog(whoami, LOG_NDELAY|LOG_PID, log_facility);
Packit fd8b60
            log_control.log_opened = 1;
Packit fd8b60
        }
Packit fd8b60
        if (do_com_err)
Packit fd8b60
            (void) set_com_err_hook(klog_com_err_proc);
Packit fd8b60
    }
Packit fd8b60
    return((log_control.log_nentries) ? 0 : ENOENT);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/* Reset the context used by the com_err hook to retrieve error messages. */
Packit fd8b60
void
Packit fd8b60
krb5_klog_set_context(krb5_context kcontext)
Packit fd8b60
{
Packit fd8b60
    err_context = kcontext;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * krb5_klog_close()    - Close the logging context and free all data.
Packit fd8b60
 */
Packit fd8b60
void
Packit fd8b60
krb5_klog_close(krb5_context kcontext)
Packit fd8b60
{
Packit fd8b60
    int lindex;
Packit fd8b60
    (void) reset_com_err_hook();
Packit fd8b60
    for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
Packit fd8b60
        switch (log_control.log_entries[lindex].log_type) {
Packit fd8b60
        case K_LOG_FILE:
Packit fd8b60
        case K_LOG_STDERR:
Packit fd8b60
            /*
Packit fd8b60
             * Files/standard error.
Packit fd8b60
             */
Packit fd8b60
            fclose(log_control.log_entries[lindex].lfu_filep);
Packit fd8b60
            break;
Packit fd8b60
        case K_LOG_CONSOLE:
Packit fd8b60
        case K_LOG_DEVICE:
Packit fd8b60
            /*
Packit fd8b60
             * Devices (may need special handling)
Packit fd8b60
             */
Packit fd8b60
            DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep);
Packit fd8b60
            break;
Packit fd8b60
        case K_LOG_SYSLOG:
Packit fd8b60
            /*
Packit fd8b60
             * System log.
Packit fd8b60
             */
Packit fd8b60
            break;
Packit fd8b60
        default:
Packit fd8b60
            break;
Packit fd8b60
        }
Packit fd8b60
        if (log_control.log_entries[lindex].log_2free)
Packit fd8b60
            free(log_control.log_entries[lindex].log_2free);
Packit fd8b60
    }
Packit fd8b60
    if (log_control.log_entries != &def_log_entry)
Packit fd8b60
        free(log_control.log_entries);
Packit fd8b60
    log_control.log_entries = (struct log_entry *) NULL;
Packit fd8b60
    log_control.log_nentries = 0;
Packit fd8b60
    if (log_control.log_whoami)
Packit fd8b60
        free(log_control.log_whoami);
Packit fd8b60
    log_control.log_whoami = (char *) NULL;
Packit fd8b60
    if (log_control.log_hostname)
Packit fd8b60
        free(log_control.log_hostname);
Packit fd8b60
    log_control.log_hostname = (char *) NULL;
Packit fd8b60
    if (log_control.log_opened)
Packit fd8b60
        closelog();
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * severity2string()    - Convert a severity to a string.
Packit fd8b60
 */
Packit fd8b60
static const char *
Packit fd8b60
severity2string(int severity)
Packit fd8b60
{
Packit fd8b60
    int s;
Packit fd8b60
    const char *ss;
Packit fd8b60
Packit fd8b60
    s = severity & LOG_PRIMASK;
Packit fd8b60
    ss = log_ufo_string;
Packit fd8b60
    switch (s) {
Packit fd8b60
    case LOG_EMERG:
Packit fd8b60
        ss = log_emerg_string;
Packit fd8b60
        break;
Packit fd8b60
    case LOG_ALERT:
Packit fd8b60
        ss = log_alert_string;
Packit fd8b60
        break;
Packit fd8b60
    case LOG_CRIT:
Packit fd8b60
        ss = log_crit_string;
Packit fd8b60
        break;
Packit fd8b60
    case LOG_ERR:
Packit fd8b60
        ss = log_err_string;
Packit fd8b60
        break;
Packit fd8b60
    case LOG_WARNING:
Packit fd8b60
        ss = log_warning_string;
Packit fd8b60
        break;
Packit fd8b60
    case LOG_NOTICE:
Packit fd8b60
        ss = log_notice_string;
Packit fd8b60
        break;
Packit fd8b60
    case LOG_INFO:
Packit fd8b60
        ss = log_info_string;
Packit fd8b60
        break;
Packit fd8b60
    case LOG_DEBUG:
Packit fd8b60
        ss = log_debug_string;
Packit fd8b60
        break;
Packit fd8b60
    }
Packit fd8b60
    return(ss);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * krb5_klog_syslog()   - Simulate the calling sequence of syslog(3), while
Packit fd8b60
 *                        also performing the logging redirection as specified
Packit fd8b60
 *                        by krb5_klog_init().
Packit fd8b60
 */
Packit fd8b60
static int
Packit fd8b60
klog_vsyslog(int priority, const char *format, va_list arglist)
Packit fd8b60
#if !defined(__cplusplus) && (__GNUC__ > 2)
Packit fd8b60
    __attribute__((__format__(__printf__, 2, 0)))
Packit fd8b60
#endif
Packit fd8b60
    ;
Packit fd8b60
Packit fd8b60
static int
Packit fd8b60
klog_vsyslog(int priority, const char *format, va_list arglist)
Packit fd8b60
{
Packit fd8b60
    char        outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
Packit fd8b60
    int         lindex;
Packit fd8b60
    char        *syslogp;
Packit fd8b60
    char        *cp;
Packit fd8b60
    time_t      now;
Packit fd8b60
    size_t      soff;
Packit fd8b60
    struct tm  *tm;
Packit fd8b60
Packit fd8b60
    /*
Packit fd8b60
     * Format a syslog-esque message of the format:
Packit fd8b60
     *
Packit fd8b60
     * (verbose form)
Packit fd8b60
     *          <date> <hostname> <id>[<pid>](<priority>): <message>
Packit fd8b60
     *
Packit fd8b60
     * (short form)
Packit fd8b60
     *          <date> <message>
Packit fd8b60
     */
Packit fd8b60
    cp = outbuf;
Packit fd8b60
    (void) time(&now;;
Packit fd8b60
Packit fd8b60
    /*
Packit fd8b60
     * Format the date: mon dd hh:mm:ss
Packit fd8b60
     */
Packit fd8b60
    tm = localtime(&now;;
Packit fd8b60
    if (tm == NULL)
Packit fd8b60
        return(-1);
Packit fd8b60
    soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", tm);
Packit fd8b60
    if (soff > 0)
Packit fd8b60
        cp += soff;
Packit fd8b60
    else
Packit fd8b60
        return(-1);
Packit fd8b60
Packit fd8b60
#ifdef VERBOSE_LOGS
Packit fd8b60
    snprintf(cp, sizeof(outbuf) - (cp-outbuf), " %s %s[%ld](%s): ",
Packit fd8b60
             log_control.log_hostname ? log_control.log_hostname : "",
Packit fd8b60
             log_control.log_whoami ? log_control.log_whoami : "",
Packit fd8b60
             (long) getpid(),
Packit fd8b60
             severity2string(priority));
Packit fd8b60
#else
Packit fd8b60
    snprintf(cp, sizeof(outbuf) - (cp-outbuf), " ");
Packit fd8b60
#endif
Packit fd8b60
    syslogp = &outbuf[strlen(outbuf)];
Packit fd8b60
Packit fd8b60
    /* Now format the actual message */
Packit fd8b60
    vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist);
Packit fd8b60
Packit fd8b60
    /*
Packit fd8b60
     * If the user did not use krb5_klog_init() instead of dropping
Packit fd8b60
     * the request on the floor, syslog it - if it exists
Packit fd8b60
     */
Packit fd8b60
    if (log_control.log_nentries == 0) {
Packit fd8b60
        /* Log the message with our header trimmed off */
Packit fd8b60
        syslog(priority, "%s", syslogp);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /*
Packit fd8b60
     * Now that we have the message formatted, perform the output to each
Packit fd8b60
     * logging specification.
Packit fd8b60
     */
Packit fd8b60
    for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
Packit fd8b60
        /* Omit LOG_DEBUG messages for non-syslog outputs unless we are
Packit fd8b60
         * configured to include them. */
Packit fd8b60
        if (priority == LOG_DEBUG && !log_control.log_debug &&
Packit fd8b60
            log_control.log_entries[lindex].log_type != K_LOG_SYSLOG)
Packit fd8b60
            continue;
Packit fd8b60
Packit fd8b60
        switch (log_control.log_entries[lindex].log_type) {
Packit fd8b60
        case K_LOG_FILE:
Packit fd8b60
        case K_LOG_STDERR:
Packit fd8b60
            /*
Packit fd8b60
             * Files/standard error.
Packit fd8b60
             */
Packit fd8b60
            if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
Packit fd8b60
                        outbuf) < 0) {
Packit fd8b60
                /* Attempt to report error */
Packit fd8b60
                fprintf(stderr, log_file_err, log_control.log_whoami,
Packit fd8b60
                        log_control.log_entries[lindex].lfu_fname);
Packit fd8b60
            }
Packit fd8b60
            else {
Packit fd8b60
                fflush(log_control.log_entries[lindex].lfu_filep);
Packit fd8b60
            }
Packit fd8b60
            break;
Packit fd8b60
        case K_LOG_CONSOLE:
Packit fd8b60
        case K_LOG_DEVICE:
Packit fd8b60
            /*
Packit fd8b60
             * Devices (may need special handling)
Packit fd8b60
             */
Packit fd8b60
            if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
Packit fd8b60
                             outbuf) < 0) {
Packit fd8b60
                /* Attempt to report error */
Packit fd8b60
                fprintf(stderr, log_device_err, log_control.log_whoami,
Packit fd8b60
                        log_control.log_entries[lindex].ldu_devname);
Packit fd8b60
            }
Packit fd8b60
            break;
Packit fd8b60
        case K_LOG_SYSLOG:
Packit fd8b60
            /*
Packit fd8b60
             * System log.
Packit fd8b60
             */
Packit fd8b60
Packit fd8b60
            /* Log the message with our header trimmed off */
Packit fd8b60
            syslog(priority, "%s", syslogp);
Packit fd8b60
            break;
Packit fd8b60
        default:
Packit fd8b60
            break;
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
    return(0);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
int
Packit fd8b60
krb5_klog_syslog(int priority, const char *format, ...)
Packit fd8b60
{
Packit fd8b60
    int         retval;
Packit fd8b60
    va_list     pvar;
Packit fd8b60
Packit fd8b60
    va_start(pvar, format);
Packit fd8b60
    retval = klog_vsyslog(priority, format, pvar);
Packit fd8b60
    va_end(pvar);
Packit fd8b60
    return(retval);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * krb5_klog_reopen() - Close and reopen any open (non-syslog) log files.
Packit fd8b60
 *                      This function is called when a SIGHUP is received
Packit fd8b60
 *                      so that external log-archival utilities may
Packit fd8b60
 *                      alert the Kerberos daemons that they should get
Packit fd8b60
 *                      a new file descriptor for the give filename.
Packit fd8b60
 */
Packit fd8b60
void
Packit fd8b60
krb5_klog_reopen(krb5_context kcontext)
Packit fd8b60
{
Packit fd8b60
    int lindex;
Packit fd8b60
    FILE *f;
Packit fd8b60
Packit fd8b60
    /*
Packit fd8b60
     * Only logs which are actually files need to be closed
Packit fd8b60
     * and reopened in response to a SIGHUP
Packit fd8b60
     */
Packit fd8b60
    for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
Packit fd8b60
        if (log_control.log_entries[lindex].log_type == K_LOG_FILE) {
Packit fd8b60
            fclose(log_control.log_entries[lindex].lfu_filep);
Packit fd8b60
            /*
Packit fd8b60
             * In case the old logfile did not get moved out of the
Packit fd8b60
             * way, open for append to prevent squashing the old logs.
Packit fd8b60
             */
Packit Service e737ee
            f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
Packit fd8b60
            if (f) {
Packit fd8b60
                set_cloexec_file(f);
Packit fd8b60
                log_control.log_entries[lindex].lfu_filep = f;
Packit fd8b60
            } else {
Packit fd8b60
                fprintf(stderr, _("Couldn't open log file %s: %s\n"),
Packit fd8b60
                        log_control.log_entries[lindex].lfu_fname,
Packit fd8b60
                        error_message(errno));
Packit fd8b60
            }
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
}