xref: /freebsd/crypto/krb5/src/lib/kadm5/logger.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* lib/kadm5/logger.c */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright 1995, 2007 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert 
27*7f2fe78bSCy Schubert /* KADM5 wants non-syslog log files to contain syslog-like entries */
28*7f2fe78bSCy Schubert #define VERBOSE_LOGS
29*7f2fe78bSCy Schubert 
30*7f2fe78bSCy Schubert /*
31*7f2fe78bSCy Schubert  * logger.c     - Handle logging functions for those who want it.
32*7f2fe78bSCy Schubert  */
33*7f2fe78bSCy Schubert #include "k5-int.h"
34*7f2fe78bSCy Schubert #include "adm_proto.h"
35*7f2fe78bSCy Schubert #include "com_err.h"
36*7f2fe78bSCy Schubert #include <stdio.h>
37*7f2fe78bSCy Schubert #include <ctype.h>
38*7f2fe78bSCy Schubert #include <syslog.h>
39*7f2fe78bSCy Schubert #include <stdarg.h>
40*7f2fe78bSCy Schubert 
41*7f2fe78bSCy Schubert #define KRB5_KLOG_MAX_ERRMSG_SIZE       2048
42*7f2fe78bSCy Schubert #ifndef MAXHOSTNAMELEN
43*7f2fe78bSCy Schubert #define MAXHOSTNAMELEN  256
44*7f2fe78bSCy Schubert #endif  /* MAXHOSTNAMELEN */
45*7f2fe78bSCy Schubert 
46*7f2fe78bSCy Schubert /* This is to assure that we have at least one match in the syslog stuff */
47*7f2fe78bSCy Schubert #ifndef LOG_AUTH
48*7f2fe78bSCy Schubert #define LOG_AUTH        0
49*7f2fe78bSCy Schubert #endif  /* LOG_AUTH */
50*7f2fe78bSCy Schubert #ifndef LOG_ERR
51*7f2fe78bSCy Schubert #define LOG_ERR         0
52*7f2fe78bSCy Schubert #endif  /* LOG_ERR */
53*7f2fe78bSCy Schubert 
54*7f2fe78bSCy Schubert #define lspec_parse_err_1       _("%s: cannot parse <%s>\n")
55*7f2fe78bSCy Schubert #define lspec_parse_err_2       _("%s: warning - logging entry syntax error\n")
56*7f2fe78bSCy Schubert #define log_file_err            _("%s: error writing to %s\n")
57*7f2fe78bSCy Schubert #define log_device_err          _("%s: error writing to %s device\n")
58*7f2fe78bSCy Schubert #define log_ufo_string          "?\?\?" /* nb: avoid trigraphs */
59*7f2fe78bSCy Schubert #define log_emerg_string        _("EMERGENCY")
60*7f2fe78bSCy Schubert #define log_alert_string        _("ALERT")
61*7f2fe78bSCy Schubert #define log_crit_string         _("CRITICAL")
62*7f2fe78bSCy Schubert #define log_err_string          _("Error")
63*7f2fe78bSCy Schubert #define log_warning_string      _("Warning")
64*7f2fe78bSCy Schubert #define log_notice_string       _("Notice")
65*7f2fe78bSCy Schubert #define log_info_string         _("info")
66*7f2fe78bSCy Schubert #define log_debug_string        _("debug")
67*7f2fe78bSCy Schubert 
68*7f2fe78bSCy Schubert /*
69*7f2fe78bSCy Schubert  * Output logging.
70*7f2fe78bSCy Schubert  *
71*7f2fe78bSCy Schubert  * Output logging is now controlled by the configuration file.  We can specify
72*7f2fe78bSCy Schubert  * the following syntaxes under the [logging]->entity specification.
73*7f2fe78bSCy Schubert  *      FILE<opentype><pathname>
74*7f2fe78bSCy Schubert  *      SYSLOG[=<severity>[:<facility>]]
75*7f2fe78bSCy Schubert  *      STDERR
76*7f2fe78bSCy Schubert  *      CONSOLE
77*7f2fe78bSCy Schubert  *      DEVICE=<device-spec>
78*7f2fe78bSCy Schubert  *
79*7f2fe78bSCy Schubert  * Where:
80*7f2fe78bSCy Schubert  *      <opentype> is ":" for open/append, "=" for open/create.
81*7f2fe78bSCy Schubert  *      <pathname> is a valid path name.
82*7f2fe78bSCy Schubert  *      <severity> is one of: (default = ERR)
83*7f2fe78bSCy Schubert  *              EMERG
84*7f2fe78bSCy Schubert  *              ALERT
85*7f2fe78bSCy Schubert  *              CRIT
86*7f2fe78bSCy Schubert  *              ERR
87*7f2fe78bSCy Schubert  *              WARNING
88*7f2fe78bSCy Schubert  *              NOTICE
89*7f2fe78bSCy Schubert  *              INFO
90*7f2fe78bSCy Schubert  *              DEBUG
91*7f2fe78bSCy Schubert  *      <facility> is one of: (default = AUTH)
92*7f2fe78bSCy Schubert  *              KERN
93*7f2fe78bSCy Schubert  *              USER
94*7f2fe78bSCy Schubert  *              MAIL
95*7f2fe78bSCy Schubert  *              DAEMON
96*7f2fe78bSCy Schubert  *              AUTH
97*7f2fe78bSCy Schubert  *              LPR
98*7f2fe78bSCy Schubert  *              NEWS
99*7f2fe78bSCy Schubert  *              UUCP
100*7f2fe78bSCy Schubert  *              CRON
101*7f2fe78bSCy Schubert  *              LOCAL0..LOCAL7
102*7f2fe78bSCy Schubert  *      <device-spec> is a valid device specification.
103*7f2fe78bSCy Schubert  */
104*7f2fe78bSCy Schubert struct log_entry {
105*7f2fe78bSCy Schubert     enum log_type { K_LOG_FILE,
106*7f2fe78bSCy Schubert                     K_LOG_SYSLOG,
107*7f2fe78bSCy Schubert                     K_LOG_STDERR,
108*7f2fe78bSCy Schubert                     K_LOG_CONSOLE,
109*7f2fe78bSCy Schubert                     K_LOG_DEVICE,
110*7f2fe78bSCy Schubert                     K_LOG_NONE } log_type;
111*7f2fe78bSCy Schubert     krb5_pointer log_2free;
112*7f2fe78bSCy Schubert     union log_union {
113*7f2fe78bSCy Schubert         struct log_file {
114*7f2fe78bSCy Schubert             FILE        *lf_filep;
115*7f2fe78bSCy Schubert             char        *lf_fname;
116*7f2fe78bSCy Schubert         } log_file;
117*7f2fe78bSCy Schubert         struct log_syslog {
118*7f2fe78bSCy Schubert             int         ls_facility;
119*7f2fe78bSCy Schubert         } log_syslog;
120*7f2fe78bSCy Schubert         struct log_device {
121*7f2fe78bSCy Schubert             FILE        *ld_filep;
122*7f2fe78bSCy Schubert             char        *ld_devname;
123*7f2fe78bSCy Schubert         } log_device;
124*7f2fe78bSCy Schubert     } log_union;
125*7f2fe78bSCy Schubert };
126*7f2fe78bSCy Schubert #define lfu_filep       log_union.log_file.lf_filep
127*7f2fe78bSCy Schubert #define lfu_fname       log_union.log_file.lf_fname
128*7f2fe78bSCy Schubert #define lsu_facility    log_union.log_syslog.ls_facility
129*7f2fe78bSCy Schubert #define ldu_filep       log_union.log_device.ld_filep
130*7f2fe78bSCy Schubert #define ldu_devname     log_union.log_device.ld_devname
131*7f2fe78bSCy Schubert 
132*7f2fe78bSCy Schubert struct log_control {
133*7f2fe78bSCy Schubert     struct log_entry    *log_entries;
134*7f2fe78bSCy Schubert     int                 log_nentries;
135*7f2fe78bSCy Schubert     char                *log_whoami;
136*7f2fe78bSCy Schubert     char                *log_hostname;
137*7f2fe78bSCy Schubert     krb5_boolean        log_opened;
138*7f2fe78bSCy Schubert     krb5_boolean        log_debug;
139*7f2fe78bSCy Schubert };
140*7f2fe78bSCy Schubert 
141*7f2fe78bSCy Schubert static struct log_control log_control = {
142*7f2fe78bSCy Schubert     (struct log_entry *) NULL,
143*7f2fe78bSCy Schubert     0,
144*7f2fe78bSCy Schubert     (char *) NULL,
145*7f2fe78bSCy Schubert     (char *) NULL,
146*7f2fe78bSCy Schubert     0
147*7f2fe78bSCy Schubert };
148*7f2fe78bSCy Schubert static struct log_entry def_log_entry;
149*7f2fe78bSCy Schubert 
150*7f2fe78bSCy Schubert /*
151*7f2fe78bSCy Schubert  * These macros define any special processing that needs to happen for
152*7f2fe78bSCy Schubert  * devices.  For unix, of course, this is hardly anything.
153*7f2fe78bSCy Schubert  */
154*7f2fe78bSCy Schubert #define DEVICE_OPEN(d, m)       fopen(d, m)
155*7f2fe78bSCy Schubert #define CONSOLE_OPEN(m)         fopen("/dev/console", m)
156*7f2fe78bSCy Schubert #define DEVICE_PRINT(f, m)      ((fprintf(f, "%s\r\n", m) >= 0) ?       \
157*7f2fe78bSCy Schubert                                  (fflush(f), 0) :                       \
158*7f2fe78bSCy Schubert                                  -1)
159*7f2fe78bSCy Schubert #define DEVICE_CLOSE(d)         fclose(d)
160*7f2fe78bSCy Schubert 
161*7f2fe78bSCy Schubert /*
162*7f2fe78bSCy Schubert  * klog_com_err_proc()  - Handle com_err(3) messages as specified by the
163*7f2fe78bSCy Schubert  *                        profile.
164*7f2fe78bSCy Schubert  */
165*7f2fe78bSCy Schubert static krb5_context err_context;
166*7f2fe78bSCy Schubert 
167*7f2fe78bSCy Schubert static void
168*7f2fe78bSCy Schubert klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap)
169*7f2fe78bSCy Schubert #if !defined(__cplusplus) && (__GNUC__ > 2)
170*7f2fe78bSCy Schubert     __attribute__((__format__(__printf__, 3, 0)))
171*7f2fe78bSCy Schubert #endif
172*7f2fe78bSCy Schubert     ;
173*7f2fe78bSCy Schubert 
174*7f2fe78bSCy Schubert /*
175*7f2fe78bSCy Schubert  * Write com_err() messages to the configured logging devices.  Ignore whoami,
176*7f2fe78bSCy Schubert  * as krb5_klog_init() already received a whoami value.  If code is nonzero,
177*7f2fe78bSCy Schubert  * log its error message (retrieved using err_context) and the formatted
178*7f2fe78bSCy Schubert  * message at error severity.  If code is zero, log the formatted message at
179*7f2fe78bSCy Schubert  * informational severity.
180*7f2fe78bSCy Schubert  */
181*7f2fe78bSCy Schubert static void
klog_com_err_proc(const char * whoami,long int code,const char * format,va_list ap)182*7f2fe78bSCy Schubert klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap)
183*7f2fe78bSCy Schubert {
184*7f2fe78bSCy Schubert     struct k5buf buf;
185*7f2fe78bSCy Schubert     const char *emsg, *msg;
186*7f2fe78bSCy Schubert 
187*7f2fe78bSCy Schubert     if (format == NULL)
188*7f2fe78bSCy Schubert         return;
189*7f2fe78bSCy Schubert 
190*7f2fe78bSCy Schubert     k5_buf_init_dynamic(&buf);
191*7f2fe78bSCy Schubert 
192*7f2fe78bSCy Schubert     if (code) {
193*7f2fe78bSCy Schubert         /* Start with the error message and a separator. */
194*7f2fe78bSCy Schubert         emsg = krb5_get_error_message(err_context, code);
195*7f2fe78bSCy Schubert         k5_buf_add(&buf, emsg);
196*7f2fe78bSCy Schubert         krb5_free_error_message(err_context, emsg);
197*7f2fe78bSCy Schubert         k5_buf_add(&buf, " - ");
198*7f2fe78bSCy Schubert     }
199*7f2fe78bSCy Schubert 
200*7f2fe78bSCy Schubert     /* Add the formatted message. */
201*7f2fe78bSCy Schubert     k5_buf_add_vfmt(&buf, format, ap);
202*7f2fe78bSCy Schubert 
203*7f2fe78bSCy Schubert     msg = k5_buf_cstring(&buf);
204*7f2fe78bSCy Schubert     if (msg != NULL)
205*7f2fe78bSCy Schubert         krb5_klog_syslog(code ? LOG_ERR : LOG_INFO, "%s", msg);
206*7f2fe78bSCy Schubert 
207*7f2fe78bSCy Schubert     k5_buf_free(&buf);
208*7f2fe78bSCy Schubert }
209*7f2fe78bSCy Schubert 
210*7f2fe78bSCy Schubert /*
211*7f2fe78bSCy Schubert  * krb5_klog_init()     - Initialize logging.
212*7f2fe78bSCy Schubert  *
213*7f2fe78bSCy Schubert  * This routine parses the syntax described above to specify destinations for
214*7f2fe78bSCy Schubert  * com_err(3) or krb5_klog_syslog() messages generated by the caller.
215*7f2fe78bSCy Schubert  *
216*7f2fe78bSCy Schubert  * Parameters:
217*7f2fe78bSCy Schubert  *      kcontext        - Kerberos context.
218*7f2fe78bSCy Schubert  *      ename           - Entity name as it is to appear in the profile.
219*7f2fe78bSCy Schubert  *      whoami          - Entity name as it is to appear in error output.
220*7f2fe78bSCy Schubert  *      do_com_err      - Take over com_err(3) processing.
221*7f2fe78bSCy Schubert  *
222*7f2fe78bSCy Schubert  * Implicit inputs:
223*7f2fe78bSCy Schubert  *      stderr          - This is where STDERR output goes.
224*7f2fe78bSCy Schubert  *
225*7f2fe78bSCy Schubert  * Implicit outputs:
226*7f2fe78bSCy Schubert  *      log_nentries    - Number of log entries, both valid and invalid.
227*7f2fe78bSCy Schubert  *      log_control     - List of entries (log_nentries long) which contains
228*7f2fe78bSCy Schubert  *                        data for klog_com_err_proc() to use to determine
229*7f2fe78bSCy Schubert  *                        where/how to send output.
230*7f2fe78bSCy Schubert  */
231*7f2fe78bSCy Schubert krb5_error_code
krb5_klog_init(krb5_context kcontext,char * ename,char * whoami,krb5_boolean do_com_err)232*7f2fe78bSCy Schubert krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err)
233*7f2fe78bSCy Schubert {
234*7f2fe78bSCy Schubert     const char  *logging_profent[3];
235*7f2fe78bSCy Schubert     const char  *logging_defent[3];
236*7f2fe78bSCy Schubert     char        **logging_specs;
237*7f2fe78bSCy Schubert     int         i, ngood, fd, append;
238*7f2fe78bSCy Schubert     char        *cp, *cp2;
239*7f2fe78bSCy Schubert     char        savec = '\0';
240*7f2fe78bSCy Schubert     int         error, debug;
241*7f2fe78bSCy Schubert     int         do_openlog, log_facility;
242*7f2fe78bSCy Schubert     FILE        *f = NULL;
243*7f2fe78bSCy Schubert 
244*7f2fe78bSCy Schubert     /* Initialize */
245*7f2fe78bSCy Schubert     do_openlog = 0;
246*7f2fe78bSCy Schubert     log_facility = 0;
247*7f2fe78bSCy Schubert 
248*7f2fe78bSCy Schubert     err_context = kcontext;
249*7f2fe78bSCy Schubert 
250*7f2fe78bSCy Schubert     /* Look up [logging]->debug in the profile to see if we should include
251*7f2fe78bSCy Schubert      * debug messages for types other than syslog.  Default to false. */
252*7f2fe78bSCy Schubert     if (!profile_get_boolean(kcontext->profile, KRB5_CONF_LOGGING,
253*7f2fe78bSCy Schubert                              KRB5_CONF_DEBUG, NULL, 0, &debug))
254*7f2fe78bSCy Schubert         log_control.log_debug = debug;
255*7f2fe78bSCy Schubert 
256*7f2fe78bSCy Schubert     /*
257*7f2fe78bSCy Schubert      * Look up [logging]-><ename> in the profile.  If that doesn't
258*7f2fe78bSCy Schubert      * succeed, then look for [logging]->default.
259*7f2fe78bSCy Schubert      */
260*7f2fe78bSCy Schubert     logging_profent[0] = KRB5_CONF_LOGGING;
261*7f2fe78bSCy Schubert     logging_profent[1] = ename;
262*7f2fe78bSCy Schubert     logging_profent[2] = (char *) NULL;
263*7f2fe78bSCy Schubert     logging_defent[0] = KRB5_CONF_LOGGING;
264*7f2fe78bSCy Schubert     logging_defent[1] = KRB5_CONF_DEFAULT;
265*7f2fe78bSCy Schubert     logging_defent[2] = (char *) NULL;
266*7f2fe78bSCy Schubert     logging_specs = (char **) NULL;
267*7f2fe78bSCy Schubert     ngood = 0;
268*7f2fe78bSCy Schubert     log_control.log_nentries = 0;
269*7f2fe78bSCy Schubert     if (!profile_get_values(kcontext->profile,
270*7f2fe78bSCy Schubert                             logging_profent,
271*7f2fe78bSCy Schubert                             &logging_specs) ||
272*7f2fe78bSCy Schubert         !profile_get_values(kcontext->profile,
273*7f2fe78bSCy Schubert                             logging_defent,
274*7f2fe78bSCy Schubert                             &logging_specs)) {
275*7f2fe78bSCy Schubert         /*
276*7f2fe78bSCy Schubert          * We have a match, so we first count the number of elements
277*7f2fe78bSCy Schubert          */
278*7f2fe78bSCy Schubert         for (log_control.log_nentries = 0;
279*7f2fe78bSCy Schubert              logging_specs[log_control.log_nentries];
280*7f2fe78bSCy Schubert              log_control.log_nentries++);
281*7f2fe78bSCy Schubert 
282*7f2fe78bSCy Schubert         /*
283*7f2fe78bSCy Schubert          * Now allocate our structure.
284*7f2fe78bSCy Schubert          */
285*7f2fe78bSCy Schubert         log_control.log_entries = (struct log_entry *)
286*7f2fe78bSCy Schubert             malloc(log_control.log_nentries * sizeof(struct log_entry));
287*7f2fe78bSCy Schubert         if (log_control.log_entries) {
288*7f2fe78bSCy Schubert             /*
289*7f2fe78bSCy Schubert              * Scan through the list.
290*7f2fe78bSCy Schubert              */
291*7f2fe78bSCy Schubert             for (i=0; i<log_control.log_nentries; i++) {
292*7f2fe78bSCy Schubert                 log_control.log_entries[i].log_type = K_LOG_NONE;
293*7f2fe78bSCy Schubert                 log_control.log_entries[i].log_2free = logging_specs[i];
294*7f2fe78bSCy Schubert                 /*
295*7f2fe78bSCy Schubert                  * The format is:
296*7f2fe78bSCy Schubert                  *      <whitespace><data><whitespace>
297*7f2fe78bSCy Schubert                  * so, trim off the leading and trailing whitespace here.
298*7f2fe78bSCy Schubert                  */
299*7f2fe78bSCy Schubert                 for (cp = logging_specs[i]; isspace((int) *cp); cp++);
300*7f2fe78bSCy Schubert                 for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1];
301*7f2fe78bSCy Schubert                      isspace((int) *cp2); cp2--);
302*7f2fe78bSCy Schubert                 cp2++;
303*7f2fe78bSCy Schubert                 *cp2 = '\0';
304*7f2fe78bSCy Schubert                 /*
305*7f2fe78bSCy Schubert                  * Is this a file?
306*7f2fe78bSCy Schubert                  */
307*7f2fe78bSCy Schubert                 if (!strncasecmp(cp, "FILE", 4)) {
308*7f2fe78bSCy Schubert                     /*
309*7f2fe78bSCy Schubert                      * Check for append/overwrite, then open the file.
310*7f2fe78bSCy Schubert                      */
311*7f2fe78bSCy Schubert                     append = (cp[4] == ':') ? O_APPEND : 0;
312*7f2fe78bSCy Schubert                     if (append || cp[4] == '=') {
313*7f2fe78bSCy Schubert                         fd = open(&cp[5], O_CREAT | O_WRONLY | append,
314*7f2fe78bSCy Schubert                                   S_IRUSR | S_IWUSR | S_IRGRP);
315*7f2fe78bSCy Schubert                         if (fd != -1)
316*7f2fe78bSCy Schubert                             f = fdopen(fd, append ? "a" : "w");
317*7f2fe78bSCy Schubert                         if (fd == -1 || f == NULL) {
318*7f2fe78bSCy Schubert                             fprintf(stderr,"Couldn't open log file %s: %s\n",
319*7f2fe78bSCy Schubert                                     &cp[5], error_message(errno));
320*7f2fe78bSCy Schubert                             continue;
321*7f2fe78bSCy Schubert                         }
322*7f2fe78bSCy Schubert                         set_cloexec_file(f);
323*7f2fe78bSCy Schubert                         log_control.log_entries[i].lfu_filep = f;
324*7f2fe78bSCy Schubert                         log_control.log_entries[i].log_type = K_LOG_FILE;
325*7f2fe78bSCy Schubert                         log_control.log_entries[i].lfu_fname = &cp[5];
326*7f2fe78bSCy Schubert                     }
327*7f2fe78bSCy Schubert                 }
328*7f2fe78bSCy Schubert                 /*
329*7f2fe78bSCy Schubert                  * Is this a syslog?
330*7f2fe78bSCy Schubert                  */
331*7f2fe78bSCy Schubert                 else if (!strncasecmp(cp, "SYSLOG", 6)) {
332*7f2fe78bSCy Schubert                     error = 0;
333*7f2fe78bSCy Schubert                     log_control.log_entries[i].lsu_facility = LOG_AUTH;
334*7f2fe78bSCy Schubert                     /*
335*7f2fe78bSCy Schubert                      * Is there a severify (which is now ignored) specified?
336*7f2fe78bSCy Schubert                      */
337*7f2fe78bSCy Schubert                     if (cp[6] == ':') {
338*7f2fe78bSCy Schubert                         /*
339*7f2fe78bSCy Schubert                          * Find the end of the severity.
340*7f2fe78bSCy Schubert                          */
341*7f2fe78bSCy Schubert                         cp2 = strchr(&cp[7], ':');
342*7f2fe78bSCy Schubert                         if (cp2) {
343*7f2fe78bSCy Schubert                             savec = *cp2;
344*7f2fe78bSCy Schubert                             *cp2 = '\0';
345*7f2fe78bSCy Schubert                             cp2++;
346*7f2fe78bSCy Schubert                         }
347*7f2fe78bSCy Schubert 
348*7f2fe78bSCy Schubert                         /*
349*7f2fe78bSCy Schubert                          * If there is a facility present, then parse that.
350*7f2fe78bSCy Schubert                          */
351*7f2fe78bSCy Schubert                         if (cp2) {
352*7f2fe78bSCy Schubert                             static const struct {
353*7f2fe78bSCy Schubert                                 const char *name;
354*7f2fe78bSCy Schubert                                 int value;
355*7f2fe78bSCy Schubert                             } facilities[] = {
356*7f2fe78bSCy Schubert                                 { "AUTH",       LOG_AUTH        },
357*7f2fe78bSCy Schubert #ifdef  LOG_AUTHPRIV
358*7f2fe78bSCy Schubert                                 { "AUTHPRIV",   LOG_AUTHPRIV    },
359*7f2fe78bSCy Schubert #endif  /* LOG_AUTHPRIV */
360*7f2fe78bSCy Schubert #ifdef  LOG_KERN
361*7f2fe78bSCy Schubert                                 { "KERN",       LOG_KERN        },
362*7f2fe78bSCy Schubert #endif  /* LOG_KERN */
363*7f2fe78bSCy Schubert #ifdef  LOG_USER
364*7f2fe78bSCy Schubert                                 { "USER",       LOG_USER        },
365*7f2fe78bSCy Schubert #endif  /* LOG_USER */
366*7f2fe78bSCy Schubert #ifdef  LOG_MAIL
367*7f2fe78bSCy Schubert                                 { "MAIL",       LOG_MAIL        },
368*7f2fe78bSCy Schubert #endif  /* LOG_MAIL */
369*7f2fe78bSCy Schubert #ifdef  LOG_DAEMON
370*7f2fe78bSCy Schubert                                 { "DAEMON",     LOG_DAEMON      },
371*7f2fe78bSCy Schubert #endif  /* LOG_DAEMON */
372*7f2fe78bSCy Schubert #ifdef  LOG_FTP
373*7f2fe78bSCy Schubert                                 { "FTP",        LOG_FTP         },
374*7f2fe78bSCy Schubert #endif  /* LOG_FTP */
375*7f2fe78bSCy Schubert #ifdef  LOG_LPR
376*7f2fe78bSCy Schubert                                 { "LPR",        LOG_LPR         },
377*7f2fe78bSCy Schubert #endif  /* LOG_LPR */
378*7f2fe78bSCy Schubert #ifdef  LOG_NEWS
379*7f2fe78bSCy Schubert                                 { "NEWS",       LOG_NEWS        },
380*7f2fe78bSCy Schubert #endif  /* LOG_NEWS */
381*7f2fe78bSCy Schubert #ifdef  LOG_UUCP
382*7f2fe78bSCy Schubert                                 { "UUCP",       LOG_UUCP        },
383*7f2fe78bSCy Schubert #endif  /* LOG_UUCP */
384*7f2fe78bSCy Schubert #ifdef  LOG_CRON
385*7f2fe78bSCy Schubert                                 { "CRON",       LOG_CRON        },
386*7f2fe78bSCy Schubert #endif  /* LOG_CRON */
387*7f2fe78bSCy Schubert #ifdef  LOG_LOCAL0
388*7f2fe78bSCy Schubert                                 { "LOCAL0",     LOG_LOCAL0      },
389*7f2fe78bSCy Schubert #endif  /* LOG_LOCAL0 */
390*7f2fe78bSCy Schubert #ifdef  LOG_LOCAL1
391*7f2fe78bSCy Schubert                                 { "LOCAL1",     LOG_LOCAL1      },
392*7f2fe78bSCy Schubert #endif  /* LOG_LOCAL1 */
393*7f2fe78bSCy Schubert #ifdef  LOG_LOCAL2
394*7f2fe78bSCy Schubert                                 { "LOCAL2",     LOG_LOCAL2      },
395*7f2fe78bSCy Schubert #endif  /* LOG_LOCAL2 */
396*7f2fe78bSCy Schubert #ifdef  LOG_LOCAL3
397*7f2fe78bSCy Schubert                                 { "LOCAL3",     LOG_LOCAL3      },
398*7f2fe78bSCy Schubert #endif  /* LOG_LOCAL3 */
399*7f2fe78bSCy Schubert #ifdef  LOG_LOCAL4
400*7f2fe78bSCy Schubert                                 { "LOCAL4",     LOG_LOCAL4      },
401*7f2fe78bSCy Schubert #endif  /* LOG_LOCAL4 */
402*7f2fe78bSCy Schubert #ifdef  LOG_LOCAL5
403*7f2fe78bSCy Schubert                                 { "LOCAL5",     LOG_LOCAL5      },
404*7f2fe78bSCy Schubert #endif  /* LOG_LOCAL5 */
405*7f2fe78bSCy Schubert #ifdef  LOG_LOCAL6
406*7f2fe78bSCy Schubert                                 { "LOCAL6",     LOG_LOCAL6      },
407*7f2fe78bSCy Schubert #endif  /* LOG_LOCAL6 */
408*7f2fe78bSCy Schubert #ifdef  LOG_LOCAL7
409*7f2fe78bSCy Schubert                                 { "LOCAL7",     LOG_LOCAL7      },
410*7f2fe78bSCy Schubert #endif  /* LOG_LOCAL7 */
411*7f2fe78bSCy Schubert                             };
412*7f2fe78bSCy Schubert                             unsigned int j;
413*7f2fe78bSCy Schubert 
414*7f2fe78bSCy Schubert                             for (j = 0; j < sizeof(facilities)/sizeof(facilities[0]); j++)
415*7f2fe78bSCy Schubert                                 if (!strcasecmp(cp2, facilities[j].name)) {
416*7f2fe78bSCy Schubert                                     log_control.log_entries[i].lsu_facility = facilities[j].value;
417*7f2fe78bSCy Schubert                                     break;
418*7f2fe78bSCy Schubert                                 }
419*7f2fe78bSCy Schubert                             cp2--;
420*7f2fe78bSCy Schubert                             *cp2 = savec;
421*7f2fe78bSCy Schubert                         }
422*7f2fe78bSCy Schubert                     }
423*7f2fe78bSCy Schubert                     if (!error) {
424*7f2fe78bSCy Schubert                         log_control.log_entries[i].log_type = K_LOG_SYSLOG;
425*7f2fe78bSCy Schubert                         do_openlog = 1;
426*7f2fe78bSCy Schubert                         log_facility = log_control.log_entries[i].lsu_facility;
427*7f2fe78bSCy Schubert                     }
428*7f2fe78bSCy Schubert                 }
429*7f2fe78bSCy Schubert                 /*
430*7f2fe78bSCy Schubert                  * Is this a standard error specification?
431*7f2fe78bSCy Schubert                  */
432*7f2fe78bSCy Schubert                 else if (!strcasecmp(cp, "STDERR")) {
433*7f2fe78bSCy Schubert                     log_control.log_entries[i].lfu_filep =
434*7f2fe78bSCy Schubert                         fdopen(fileno(stderr), "w");
435*7f2fe78bSCy Schubert                     if (log_control.log_entries[i].lfu_filep) {
436*7f2fe78bSCy Schubert                         log_control.log_entries[i].log_type = K_LOG_STDERR;
437*7f2fe78bSCy Schubert                         log_control.log_entries[i].lfu_fname =
438*7f2fe78bSCy Schubert                             "standard error";
439*7f2fe78bSCy Schubert                     }
440*7f2fe78bSCy Schubert                 }
441*7f2fe78bSCy Schubert                 /*
442*7f2fe78bSCy Schubert                  * Is this a specification of the console?
443*7f2fe78bSCy Schubert                  */
444*7f2fe78bSCy Schubert                 else if (!strcasecmp(cp, "CONSOLE")) {
445*7f2fe78bSCy Schubert                     log_control.log_entries[i].ldu_filep =
446*7f2fe78bSCy Schubert                         CONSOLE_OPEN("a+");
447*7f2fe78bSCy Schubert                     if (log_control.log_entries[i].ldu_filep) {
448*7f2fe78bSCy Schubert                         set_cloexec_file(log_control.log_entries[i].ldu_filep);
449*7f2fe78bSCy Schubert                         log_control.log_entries[i].log_type = K_LOG_CONSOLE;
450*7f2fe78bSCy Schubert                         log_control.log_entries[i].ldu_devname = "console";
451*7f2fe78bSCy Schubert                     }
452*7f2fe78bSCy Schubert                 }
453*7f2fe78bSCy Schubert                 /*
454*7f2fe78bSCy Schubert                  * Is this a specification of a device?
455*7f2fe78bSCy Schubert                  */
456*7f2fe78bSCy Schubert                 else if (!strncasecmp(cp, "DEVICE", 6)) {
457*7f2fe78bSCy Schubert                     /*
458*7f2fe78bSCy Schubert                      * We handle devices very similarly to files.
459*7f2fe78bSCy Schubert                      */
460*7f2fe78bSCy Schubert                     if (cp[6] == '=') {
461*7f2fe78bSCy Schubert                         log_control.log_entries[i].ldu_filep =
462*7f2fe78bSCy Schubert                             DEVICE_OPEN(&cp[7], "w");
463*7f2fe78bSCy Schubert                         if (log_control.log_entries[i].ldu_filep) {
464*7f2fe78bSCy Schubert                             set_cloexec_file(log_control.log_entries[i].ldu_filep);
465*7f2fe78bSCy Schubert                             log_control.log_entries[i].log_type = K_LOG_DEVICE;
466*7f2fe78bSCy Schubert                             log_control.log_entries[i].ldu_devname = &cp[7];
467*7f2fe78bSCy Schubert                         }
468*7f2fe78bSCy Schubert                     }
469*7f2fe78bSCy Schubert                 }
470*7f2fe78bSCy Schubert                 /*
471*7f2fe78bSCy Schubert                  * See if we successfully parsed this specification.
472*7f2fe78bSCy Schubert                  */
473*7f2fe78bSCy Schubert                 if (log_control.log_entries[i].log_type == K_LOG_NONE) {
474*7f2fe78bSCy Schubert                     fprintf(stderr, lspec_parse_err_1, whoami, cp);
475*7f2fe78bSCy Schubert                     fprintf(stderr, lspec_parse_err_2, whoami);
476*7f2fe78bSCy Schubert                 }
477*7f2fe78bSCy Schubert                 else
478*7f2fe78bSCy Schubert                     ngood++;
479*7f2fe78bSCy Schubert             }
480*7f2fe78bSCy Schubert         }
481*7f2fe78bSCy Schubert         /*
482*7f2fe78bSCy Schubert          * If we didn't find anything, then free our lists.
483*7f2fe78bSCy Schubert          */
484*7f2fe78bSCy Schubert         if (ngood == 0) {
485*7f2fe78bSCy Schubert             for (i=0; i<log_control.log_nentries; i++)
486*7f2fe78bSCy Schubert                 free(logging_specs[i]);
487*7f2fe78bSCy Schubert         }
488*7f2fe78bSCy Schubert         free(logging_specs);
489*7f2fe78bSCy Schubert     }
490*7f2fe78bSCy Schubert     /*
491*7f2fe78bSCy Schubert      * If we didn't find anything, go for the default which is to log to
492*7f2fe78bSCy Schubert      * the system log.
493*7f2fe78bSCy Schubert      */
494*7f2fe78bSCy Schubert     if (ngood == 0) {
495*7f2fe78bSCy Schubert         if (log_control.log_entries)
496*7f2fe78bSCy Schubert             free(log_control.log_entries);
497*7f2fe78bSCy Schubert         log_control.log_entries = &def_log_entry;
498*7f2fe78bSCy Schubert         log_control.log_entries->log_type = K_LOG_SYSLOG;
499*7f2fe78bSCy Schubert         log_control.log_entries->log_2free = (krb5_pointer) NULL;
500*7f2fe78bSCy Schubert         log_facility = log_control.log_entries->lsu_facility = LOG_AUTH;
501*7f2fe78bSCy Schubert         do_openlog = 1;
502*7f2fe78bSCy Schubert         log_control.log_nentries = 1;
503*7f2fe78bSCy Schubert     }
504*7f2fe78bSCy Schubert     if (log_control.log_nentries) {
505*7f2fe78bSCy Schubert         log_control.log_whoami = strdup(whoami);
506*7f2fe78bSCy Schubert         log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1);
507*7f2fe78bSCy Schubert         if (log_control.log_hostname) {
508*7f2fe78bSCy Schubert             if (gethostname(log_control.log_hostname, MAXHOSTNAMELEN) == -1) {
509*7f2fe78bSCy Schubert                 free(log_control.log_hostname);
510*7f2fe78bSCy Schubert                 log_control.log_hostname = NULL;
511*7f2fe78bSCy Schubert             } else
512*7f2fe78bSCy Schubert                 log_control.log_hostname[MAXHOSTNAMELEN] = '\0';
513*7f2fe78bSCy Schubert         }
514*7f2fe78bSCy Schubert         if (do_openlog) {
515*7f2fe78bSCy Schubert             openlog(whoami, LOG_NDELAY|LOG_PID, log_facility);
516*7f2fe78bSCy Schubert             log_control.log_opened = 1;
517*7f2fe78bSCy Schubert         }
518*7f2fe78bSCy Schubert         if (do_com_err)
519*7f2fe78bSCy Schubert             (void) set_com_err_hook(klog_com_err_proc);
520*7f2fe78bSCy Schubert     }
521*7f2fe78bSCy Schubert     return((log_control.log_nentries) ? 0 : ENOENT);
522*7f2fe78bSCy Schubert }
523*7f2fe78bSCy Schubert 
524*7f2fe78bSCy Schubert /* Reset the context used by the com_err hook to retrieve error messages. */
525*7f2fe78bSCy Schubert void
krb5_klog_set_context(krb5_context kcontext)526*7f2fe78bSCy Schubert krb5_klog_set_context(krb5_context kcontext)
527*7f2fe78bSCy Schubert {
528*7f2fe78bSCy Schubert     err_context = kcontext;
529*7f2fe78bSCy Schubert }
530*7f2fe78bSCy Schubert 
531*7f2fe78bSCy Schubert /*
532*7f2fe78bSCy Schubert  * krb5_klog_close()    - Close the logging context and free all data.
533*7f2fe78bSCy Schubert  */
534*7f2fe78bSCy Schubert void
krb5_klog_close(krb5_context kcontext)535*7f2fe78bSCy Schubert krb5_klog_close(krb5_context kcontext)
536*7f2fe78bSCy Schubert {
537*7f2fe78bSCy Schubert     int lindex;
538*7f2fe78bSCy Schubert     (void) reset_com_err_hook();
539*7f2fe78bSCy Schubert     for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
540*7f2fe78bSCy Schubert         switch (log_control.log_entries[lindex].log_type) {
541*7f2fe78bSCy Schubert         case K_LOG_FILE:
542*7f2fe78bSCy Schubert         case K_LOG_STDERR:
543*7f2fe78bSCy Schubert             /*
544*7f2fe78bSCy Schubert              * Files/standard error.
545*7f2fe78bSCy Schubert              */
546*7f2fe78bSCy Schubert             fclose(log_control.log_entries[lindex].lfu_filep);
547*7f2fe78bSCy Schubert             break;
548*7f2fe78bSCy Schubert         case K_LOG_CONSOLE:
549*7f2fe78bSCy Schubert         case K_LOG_DEVICE:
550*7f2fe78bSCy Schubert             /*
551*7f2fe78bSCy Schubert              * Devices (may need special handling)
552*7f2fe78bSCy Schubert              */
553*7f2fe78bSCy Schubert             DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep);
554*7f2fe78bSCy Schubert             break;
555*7f2fe78bSCy Schubert         case K_LOG_SYSLOG:
556*7f2fe78bSCy Schubert             /*
557*7f2fe78bSCy Schubert              * System log.
558*7f2fe78bSCy Schubert              */
559*7f2fe78bSCy Schubert             break;
560*7f2fe78bSCy Schubert         default:
561*7f2fe78bSCy Schubert             break;
562*7f2fe78bSCy Schubert         }
563*7f2fe78bSCy Schubert         if (log_control.log_entries[lindex].log_2free)
564*7f2fe78bSCy Schubert             free(log_control.log_entries[lindex].log_2free);
565*7f2fe78bSCy Schubert     }
566*7f2fe78bSCy Schubert     if (log_control.log_entries != &def_log_entry)
567*7f2fe78bSCy Schubert         free(log_control.log_entries);
568*7f2fe78bSCy Schubert     log_control.log_entries = (struct log_entry *) NULL;
569*7f2fe78bSCy Schubert     log_control.log_nentries = 0;
570*7f2fe78bSCy Schubert     if (log_control.log_whoami)
571*7f2fe78bSCy Schubert         free(log_control.log_whoami);
572*7f2fe78bSCy Schubert     log_control.log_whoami = (char *) NULL;
573*7f2fe78bSCy Schubert     if (log_control.log_hostname)
574*7f2fe78bSCy Schubert         free(log_control.log_hostname);
575*7f2fe78bSCy Schubert     log_control.log_hostname = (char *) NULL;
576*7f2fe78bSCy Schubert     if (log_control.log_opened)
577*7f2fe78bSCy Schubert         closelog();
578*7f2fe78bSCy Schubert }
579*7f2fe78bSCy Schubert 
580*7f2fe78bSCy Schubert /*
581*7f2fe78bSCy Schubert  * severity2string()    - Convert a severity to a string.
582*7f2fe78bSCy Schubert  */
583*7f2fe78bSCy Schubert static const char *
severity2string(int severity)584*7f2fe78bSCy Schubert severity2string(int severity)
585*7f2fe78bSCy Schubert {
586*7f2fe78bSCy Schubert     int s;
587*7f2fe78bSCy Schubert     const char *ss;
588*7f2fe78bSCy Schubert 
589*7f2fe78bSCy Schubert     s = severity & LOG_PRIMASK;
590*7f2fe78bSCy Schubert     ss = log_ufo_string;
591*7f2fe78bSCy Schubert     switch (s) {
592*7f2fe78bSCy Schubert     case LOG_EMERG:
593*7f2fe78bSCy Schubert         ss = log_emerg_string;
594*7f2fe78bSCy Schubert         break;
595*7f2fe78bSCy Schubert     case LOG_ALERT:
596*7f2fe78bSCy Schubert         ss = log_alert_string;
597*7f2fe78bSCy Schubert         break;
598*7f2fe78bSCy Schubert     case LOG_CRIT:
599*7f2fe78bSCy Schubert         ss = log_crit_string;
600*7f2fe78bSCy Schubert         break;
601*7f2fe78bSCy Schubert     case LOG_ERR:
602*7f2fe78bSCy Schubert         ss = log_err_string;
603*7f2fe78bSCy Schubert         break;
604*7f2fe78bSCy Schubert     case LOG_WARNING:
605*7f2fe78bSCy Schubert         ss = log_warning_string;
606*7f2fe78bSCy Schubert         break;
607*7f2fe78bSCy Schubert     case LOG_NOTICE:
608*7f2fe78bSCy Schubert         ss = log_notice_string;
609*7f2fe78bSCy Schubert         break;
610*7f2fe78bSCy Schubert     case LOG_INFO:
611*7f2fe78bSCy Schubert         ss = log_info_string;
612*7f2fe78bSCy Schubert         break;
613*7f2fe78bSCy Schubert     case LOG_DEBUG:
614*7f2fe78bSCy Schubert         ss = log_debug_string;
615*7f2fe78bSCy Schubert         break;
616*7f2fe78bSCy Schubert     }
617*7f2fe78bSCy Schubert     return(ss);
618*7f2fe78bSCy Schubert }
619*7f2fe78bSCy Schubert 
620*7f2fe78bSCy Schubert /*
621*7f2fe78bSCy Schubert  * krb5_klog_syslog()   - Simulate the calling sequence of syslog(3), while
622*7f2fe78bSCy Schubert  *                        also performing the logging redirection as specified
623*7f2fe78bSCy Schubert  *                        by krb5_klog_init().
624*7f2fe78bSCy Schubert  */
625*7f2fe78bSCy Schubert static int
626*7f2fe78bSCy Schubert klog_vsyslog(int priority, const char *format, va_list arglist)
627*7f2fe78bSCy Schubert #if !defined(__cplusplus) && (__GNUC__ > 2)
628*7f2fe78bSCy Schubert     __attribute__((__format__(__printf__, 2, 0)))
629*7f2fe78bSCy Schubert #endif
630*7f2fe78bSCy Schubert     ;
631*7f2fe78bSCy Schubert 
632*7f2fe78bSCy Schubert static int
klog_vsyslog(int priority,const char * format,va_list arglist)633*7f2fe78bSCy Schubert klog_vsyslog(int priority, const char *format, va_list arglist)
634*7f2fe78bSCy Schubert {
635*7f2fe78bSCy Schubert     char        outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
636*7f2fe78bSCy Schubert     int         lindex;
637*7f2fe78bSCy Schubert     char        *syslogp;
638*7f2fe78bSCy Schubert     char        *cp;
639*7f2fe78bSCy Schubert     time_t      now;
640*7f2fe78bSCy Schubert     size_t      soff;
641*7f2fe78bSCy Schubert     struct tm  *tm;
642*7f2fe78bSCy Schubert 
643*7f2fe78bSCy Schubert     /*
644*7f2fe78bSCy Schubert      * Format a syslog-esque message of the format:
645*7f2fe78bSCy Schubert      *
646*7f2fe78bSCy Schubert      * (verbose form)
647*7f2fe78bSCy Schubert      *          <date> <hostname> <id>[<pid>](<priority>): <message>
648*7f2fe78bSCy Schubert      *
649*7f2fe78bSCy Schubert      * (short form)
650*7f2fe78bSCy Schubert      *          <date> <message>
651*7f2fe78bSCy Schubert      */
652*7f2fe78bSCy Schubert     cp = outbuf;
653*7f2fe78bSCy Schubert     (void) time(&now);
654*7f2fe78bSCy Schubert 
655*7f2fe78bSCy Schubert     /*
656*7f2fe78bSCy Schubert      * Format the date: mon dd hh:mm:ss
657*7f2fe78bSCy Schubert      */
658*7f2fe78bSCy Schubert     tm = localtime(&now);
659*7f2fe78bSCy Schubert     if (tm == NULL)
660*7f2fe78bSCy Schubert         return(-1);
661*7f2fe78bSCy Schubert     soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", tm);
662*7f2fe78bSCy Schubert     if (soff > 0)
663*7f2fe78bSCy Schubert         cp += soff;
664*7f2fe78bSCy Schubert     else
665*7f2fe78bSCy Schubert         return(-1);
666*7f2fe78bSCy Schubert 
667*7f2fe78bSCy Schubert #ifdef VERBOSE_LOGS
668*7f2fe78bSCy Schubert     snprintf(cp, sizeof(outbuf) - (cp-outbuf), " %s %s[%ld](%s): ",
669*7f2fe78bSCy Schubert              log_control.log_hostname ? log_control.log_hostname : "",
670*7f2fe78bSCy Schubert              log_control.log_whoami ? log_control.log_whoami : "",
671*7f2fe78bSCy Schubert              (long) getpid(),
672*7f2fe78bSCy Schubert              severity2string(priority));
673*7f2fe78bSCy Schubert #else
674*7f2fe78bSCy Schubert     snprintf(cp, sizeof(outbuf) - (cp-outbuf), " ");
675*7f2fe78bSCy Schubert #endif
676*7f2fe78bSCy Schubert     syslogp = &outbuf[strlen(outbuf)];
677*7f2fe78bSCy Schubert 
678*7f2fe78bSCy Schubert     /* Now format the actual message */
679*7f2fe78bSCy Schubert     vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist);
680*7f2fe78bSCy Schubert 
681*7f2fe78bSCy Schubert     /*
682*7f2fe78bSCy Schubert      * If the user did not use krb5_klog_init() instead of dropping
683*7f2fe78bSCy Schubert      * the request on the floor, syslog it - if it exists
684*7f2fe78bSCy Schubert      */
685*7f2fe78bSCy Schubert     if (log_control.log_nentries == 0) {
686*7f2fe78bSCy Schubert         /* Log the message with our header trimmed off */
687*7f2fe78bSCy Schubert         syslog(priority, "%s", syslogp);
688*7f2fe78bSCy Schubert     }
689*7f2fe78bSCy Schubert 
690*7f2fe78bSCy Schubert     /*
691*7f2fe78bSCy Schubert      * Now that we have the message formatted, perform the output to each
692*7f2fe78bSCy Schubert      * logging specification.
693*7f2fe78bSCy Schubert      */
694*7f2fe78bSCy Schubert     for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
695*7f2fe78bSCy Schubert         /* Omit LOG_DEBUG messages for non-syslog outputs unless we are
696*7f2fe78bSCy Schubert          * configured to include them. */
697*7f2fe78bSCy Schubert         if (priority == LOG_DEBUG && !log_control.log_debug &&
698*7f2fe78bSCy Schubert             log_control.log_entries[lindex].log_type != K_LOG_SYSLOG)
699*7f2fe78bSCy Schubert             continue;
700*7f2fe78bSCy Schubert 
701*7f2fe78bSCy Schubert         switch (log_control.log_entries[lindex].log_type) {
702*7f2fe78bSCy Schubert         case K_LOG_FILE:
703*7f2fe78bSCy Schubert         case K_LOG_STDERR:
704*7f2fe78bSCy Schubert             /*
705*7f2fe78bSCy Schubert              * Files/standard error.
706*7f2fe78bSCy Schubert              */
707*7f2fe78bSCy Schubert             if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
708*7f2fe78bSCy Schubert                         outbuf) < 0) {
709*7f2fe78bSCy Schubert                 /* Attempt to report error */
710*7f2fe78bSCy Schubert                 fprintf(stderr, log_file_err, log_control.log_whoami,
711*7f2fe78bSCy Schubert                         log_control.log_entries[lindex].lfu_fname);
712*7f2fe78bSCy Schubert             }
713*7f2fe78bSCy Schubert             else {
714*7f2fe78bSCy Schubert                 fflush(log_control.log_entries[lindex].lfu_filep);
715*7f2fe78bSCy Schubert             }
716*7f2fe78bSCy Schubert             break;
717*7f2fe78bSCy Schubert         case K_LOG_CONSOLE:
718*7f2fe78bSCy Schubert         case K_LOG_DEVICE:
719*7f2fe78bSCy Schubert             /*
720*7f2fe78bSCy Schubert              * Devices (may need special handling)
721*7f2fe78bSCy Schubert              */
722*7f2fe78bSCy Schubert             if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
723*7f2fe78bSCy Schubert                              outbuf) < 0) {
724*7f2fe78bSCy Schubert                 /* Attempt to report error */
725*7f2fe78bSCy Schubert                 fprintf(stderr, log_device_err, log_control.log_whoami,
726*7f2fe78bSCy Schubert                         log_control.log_entries[lindex].ldu_devname);
727*7f2fe78bSCy Schubert             }
728*7f2fe78bSCy Schubert             break;
729*7f2fe78bSCy Schubert         case K_LOG_SYSLOG:
730*7f2fe78bSCy Schubert             /*
731*7f2fe78bSCy Schubert              * System log.
732*7f2fe78bSCy Schubert              */
733*7f2fe78bSCy Schubert 
734*7f2fe78bSCy Schubert             /* Log the message with our header trimmed off */
735*7f2fe78bSCy Schubert             syslog(priority, "%s", syslogp);
736*7f2fe78bSCy Schubert             break;
737*7f2fe78bSCy Schubert         default:
738*7f2fe78bSCy Schubert             break;
739*7f2fe78bSCy Schubert         }
740*7f2fe78bSCy Schubert     }
741*7f2fe78bSCy Schubert     return(0);
742*7f2fe78bSCy Schubert }
743*7f2fe78bSCy Schubert 
744*7f2fe78bSCy Schubert int
krb5_klog_syslog(int priority,const char * format,...)745*7f2fe78bSCy Schubert krb5_klog_syslog(int priority, const char *format, ...)
746*7f2fe78bSCy Schubert {
747*7f2fe78bSCy Schubert     int         retval;
748*7f2fe78bSCy Schubert     va_list     pvar;
749*7f2fe78bSCy Schubert 
750*7f2fe78bSCy Schubert     va_start(pvar, format);
751*7f2fe78bSCy Schubert     retval = klog_vsyslog(priority, format, pvar);
752*7f2fe78bSCy Schubert     va_end(pvar);
753*7f2fe78bSCy Schubert     return(retval);
754*7f2fe78bSCy Schubert }
755*7f2fe78bSCy Schubert 
756*7f2fe78bSCy Schubert /*
757*7f2fe78bSCy Schubert  * krb5_klog_reopen() - Close and reopen any open (non-syslog) log files.
758*7f2fe78bSCy Schubert  *                      This function is called when a SIGHUP is received
759*7f2fe78bSCy Schubert  *                      so that external log-archival utilities may
760*7f2fe78bSCy Schubert  *                      alert the Kerberos daemons that they should get
761*7f2fe78bSCy Schubert  *                      a new file descriptor for the give filename.
762*7f2fe78bSCy Schubert  */
763*7f2fe78bSCy Schubert void
krb5_klog_reopen(krb5_context kcontext)764*7f2fe78bSCy Schubert krb5_klog_reopen(krb5_context kcontext)
765*7f2fe78bSCy Schubert {
766*7f2fe78bSCy Schubert     int lindex;
767*7f2fe78bSCy Schubert     FILE *f;
768*7f2fe78bSCy Schubert 
769*7f2fe78bSCy Schubert     /*
770*7f2fe78bSCy Schubert      * Only logs which are actually files need to be closed
771*7f2fe78bSCy Schubert      * and reopened in response to a SIGHUP
772*7f2fe78bSCy Schubert      */
773*7f2fe78bSCy Schubert     for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
774*7f2fe78bSCy Schubert         if (log_control.log_entries[lindex].log_type == K_LOG_FILE) {
775*7f2fe78bSCy Schubert             fclose(log_control.log_entries[lindex].lfu_filep);
776*7f2fe78bSCy Schubert             /*
777*7f2fe78bSCy Schubert              * In case the old logfile did not get moved out of the
778*7f2fe78bSCy Schubert              * way, open for append to prevent squashing the old logs.
779*7f2fe78bSCy Schubert              */
780*7f2fe78bSCy Schubert             f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
781*7f2fe78bSCy Schubert             if (f) {
782*7f2fe78bSCy Schubert                 set_cloexec_file(f);
783*7f2fe78bSCy Schubert                 log_control.log_entries[lindex].lfu_filep = f;
784*7f2fe78bSCy Schubert             } else {
785*7f2fe78bSCy Schubert                 fprintf(stderr, _("Couldn't open log file %s: %s\n"),
786*7f2fe78bSCy Schubert                         log_control.log_entries[lindex].lfu_fname,
787*7f2fe78bSCy Schubert                         error_message(errno));
788*7f2fe78bSCy Schubert             }
789*7f2fe78bSCy Schubert         }
790*7f2fe78bSCy Schubert     }
791*7f2fe78bSCy Schubert }
792