xref: /freebsd/crypto/heimdal/lib/krb5/log.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov  * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6*ae771770SStanislav Sedov  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7*ae771770SStanislav Sedov  *
8b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
9b528cefcSMark Murray  * modification, are permitted provided that the following conditions
10b528cefcSMark Murray  * are met:
11b528cefcSMark Murray  *
12b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
13b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
14b528cefcSMark Murray  *
15b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
16b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
17b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
18b528cefcSMark Murray  *
19b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
20b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
21b528cefcSMark Murray  *    without specific prior written permission.
22b528cefcSMark Murray  *
23b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33b528cefcSMark Murray  * SUCH DAMAGE.
34b528cefcSMark Murray  */
35b528cefcSMark Murray 
36b528cefcSMark Murray #include "krb5_locl.h"
37*ae771770SStanislav Sedov #include <vis.h>
38b528cefcSMark Murray 
39b528cefcSMark Murray struct facility {
40b528cefcSMark Murray     int min;
41b528cefcSMark Murray     int max;
42c19800e8SDoug Rabson     krb5_log_log_func_t log_func;
43c19800e8SDoug Rabson     krb5_log_close_func_t close_func;
44b528cefcSMark Murray     void *data;
45b528cefcSMark Murray };
46b528cefcSMark Murray 
47b528cefcSMark Murray static struct facility*
log_realloc(krb5_log_facility * f)48b528cefcSMark Murray log_realloc(krb5_log_facility *f)
49b528cefcSMark Murray {
50b528cefcSMark Murray     struct facility *fp;
51c19800e8SDoug Rabson     fp = realloc(f->val, (f->len + 1) * sizeof(*f->val));
52b528cefcSMark Murray     if(fp == NULL)
53b528cefcSMark Murray 	return NULL;
54c19800e8SDoug Rabson     f->len++;
55b528cefcSMark Murray     f->val = fp;
56b528cefcSMark Murray     fp += f->len - 1;
57b528cefcSMark Murray     return fp;
58b528cefcSMark Murray }
59b528cefcSMark Murray 
60b528cefcSMark Murray struct s2i {
618373020dSJacques Vidrine     const char *s;
62b528cefcSMark Murray     int val;
63b528cefcSMark Murray };
64b528cefcSMark Murray 
65b528cefcSMark Murray #define L(X) { #X, LOG_ ## X }
66b528cefcSMark Murray 
675e9cd1aeSAssar Westerlund static struct s2i syslogvals[] = {
68b528cefcSMark Murray     L(EMERG),
69b528cefcSMark Murray     L(ALERT),
70b528cefcSMark Murray     L(CRIT),
71b528cefcSMark Murray     L(ERR),
72b528cefcSMark Murray     L(WARNING),
73b528cefcSMark Murray     L(NOTICE),
74b528cefcSMark Murray     L(INFO),
75b528cefcSMark Murray     L(DEBUG),
76b528cefcSMark Murray 
77b528cefcSMark Murray     L(AUTH),
78b528cefcSMark Murray #ifdef LOG_AUTHPRIV
79b528cefcSMark Murray     L(AUTHPRIV),
80b528cefcSMark Murray #endif
81b528cefcSMark Murray #ifdef LOG_CRON
82b528cefcSMark Murray     L(CRON),
83b528cefcSMark Murray #endif
84b528cefcSMark Murray     L(DAEMON),
85b528cefcSMark Murray #ifdef LOG_FTP
86b528cefcSMark Murray     L(FTP),
87b528cefcSMark Murray #endif
88b528cefcSMark Murray     L(KERN),
89b528cefcSMark Murray     L(LPR),
90b528cefcSMark Murray     L(MAIL),
91b528cefcSMark Murray #ifdef LOG_NEWS
92b528cefcSMark Murray     L(NEWS),
93b528cefcSMark Murray #endif
94b528cefcSMark Murray     L(SYSLOG),
95b528cefcSMark Murray     L(USER),
96b528cefcSMark Murray #ifdef LOG_UUCP
97b528cefcSMark Murray     L(UUCP),
98b528cefcSMark Murray #endif
99b528cefcSMark Murray     L(LOCAL0),
100b528cefcSMark Murray     L(LOCAL1),
101b528cefcSMark Murray     L(LOCAL2),
102b528cefcSMark Murray     L(LOCAL3),
103b528cefcSMark Murray     L(LOCAL4),
104b528cefcSMark Murray     L(LOCAL5),
105b528cefcSMark Murray     L(LOCAL6),
106b528cefcSMark Murray     L(LOCAL7),
107b528cefcSMark Murray     { NULL, -1 }
108b528cefcSMark Murray };
109b528cefcSMark Murray 
110b528cefcSMark Murray static int
find_value(const char * s,struct s2i * table)111b528cefcSMark Murray find_value(const char *s, struct s2i *table)
112b528cefcSMark Murray {
113b528cefcSMark Murray     while(table->s && strcasecmp(table->s, s))
114b528cefcSMark Murray 	table++;
115b528cefcSMark Murray     return table->val;
116b528cefcSMark Murray }
117b528cefcSMark Murray 
118*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_initlog(krb5_context context,const char * program,krb5_log_facility ** fac)119b528cefcSMark Murray krb5_initlog(krb5_context context,
120b528cefcSMark Murray 	     const char *program,
121b528cefcSMark Murray 	     krb5_log_facility **fac)
122b528cefcSMark Murray {
123b528cefcSMark Murray     krb5_log_facility *f = calloc(1, sizeof(*f));
124adb0ddaeSAssar Westerlund     if(f == NULL) {
125*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
126*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
127b528cefcSMark Murray 	return ENOMEM;
128adb0ddaeSAssar Westerlund     }
129b528cefcSMark Murray     f->program = strdup(program);
130b528cefcSMark Murray     if(f->program == NULL){
131b528cefcSMark Murray 	free(f);
132*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
133*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
134b528cefcSMark Murray 	return ENOMEM;
135b528cefcSMark Murray     }
136b528cefcSMark Murray     *fac = f;
137b528cefcSMark Murray     return 0;
138b528cefcSMark Murray }
139b528cefcSMark Murray 
140*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_addlog_func(krb5_context context,krb5_log_facility * fac,int min,int max,krb5_log_log_func_t log_func,krb5_log_close_func_t close_func,void * data)141b528cefcSMark Murray krb5_addlog_func(krb5_context context,
142b528cefcSMark Murray 		 krb5_log_facility *fac,
143b528cefcSMark Murray 		 int min,
144b528cefcSMark Murray 		 int max,
145c19800e8SDoug Rabson 		 krb5_log_log_func_t log_func,
146c19800e8SDoug Rabson 		 krb5_log_close_func_t close_func,
147b528cefcSMark Murray 		 void *data)
148b528cefcSMark Murray {
149b528cefcSMark Murray     struct facility *fp = log_realloc(fac);
150adb0ddaeSAssar Westerlund     if(fp == NULL) {
151*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
152*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
153b528cefcSMark Murray 	return ENOMEM;
154adb0ddaeSAssar Westerlund     }
155b528cefcSMark Murray     fp->min = min;
156b528cefcSMark Murray     fp->max = max;
157c19800e8SDoug Rabson     fp->log_func = log_func;
158c19800e8SDoug Rabson     fp->close_func = close_func;
159b528cefcSMark Murray     fp->data = data;
160b528cefcSMark Murray     return 0;
161b528cefcSMark Murray }
162b528cefcSMark Murray 
163b528cefcSMark Murray 
1648373020dSJacques Vidrine struct _heimdal_syslog_data{
165b528cefcSMark Murray     int priority;
166b528cefcSMark Murray };
167b528cefcSMark Murray 
168*ae771770SStanislav Sedov static void KRB5_CALLCONV
log_syslog(const char * timestr,const char * msg,void * data)169c19800e8SDoug Rabson log_syslog(const char *timestr,
170b528cefcSMark Murray 	   const char *msg,
171b528cefcSMark Murray 	   void *data)
172b528cefcSMark Murray 
173b528cefcSMark Murray {
1748373020dSJacques Vidrine     struct _heimdal_syslog_data *s = data;
175b528cefcSMark Murray     syslog(s->priority, "%s", msg);
176b528cefcSMark Murray }
177b528cefcSMark Murray 
178*ae771770SStanislav Sedov static void KRB5_CALLCONV
close_syslog(void * data)179b528cefcSMark Murray close_syslog(void *data)
180b528cefcSMark Murray {
181b528cefcSMark Murray     free(data);
182b528cefcSMark Murray     closelog();
183b528cefcSMark Murray }
184b528cefcSMark Murray 
185b528cefcSMark Murray static krb5_error_code
open_syslog(krb5_context context,krb5_log_facility * facility,int min,int max,const char * sev,const char * fac)186b528cefcSMark Murray open_syslog(krb5_context context,
187b528cefcSMark Murray 	    krb5_log_facility *facility, int min, int max,
188b528cefcSMark Murray 	    const char *sev, const char *fac)
189b528cefcSMark Murray {
1908373020dSJacques Vidrine     struct _heimdal_syslog_data *sd = malloc(sizeof(*sd));
191b528cefcSMark Murray     int i;
192b528cefcSMark Murray 
193adb0ddaeSAssar Westerlund     if(sd == NULL) {
194*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
195*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
196b528cefcSMark Murray 	return ENOMEM;
197adb0ddaeSAssar Westerlund     }
198b528cefcSMark Murray     i = find_value(sev, syslogvals);
199b528cefcSMark Murray     if(i == -1)
200b528cefcSMark Murray 	i = LOG_ERR;
201b528cefcSMark Murray     sd->priority = i;
202b528cefcSMark Murray     i = find_value(fac, syslogvals);
203b528cefcSMark Murray     if(i == -1)
204b528cefcSMark Murray 	i = LOG_AUTH;
205b528cefcSMark Murray     sd->priority |= i;
206b528cefcSMark Murray     roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i);
207b528cefcSMark Murray     return krb5_addlog_func(context, facility, min, max,
208b528cefcSMark Murray 			    log_syslog, close_syslog, sd);
209b528cefcSMark Murray }
210b528cefcSMark Murray 
211b528cefcSMark Murray struct file_data{
2128373020dSJacques Vidrine     const char *filename;
2138373020dSJacques Vidrine     const char *mode;
214b528cefcSMark Murray     FILE *fd;
215b528cefcSMark Murray     int keep_open;
216b528cefcSMark Murray };
217b528cefcSMark Murray 
218*ae771770SStanislav Sedov static void KRB5_CALLCONV
log_file(const char * timestr,const char * msg,void * data)219c19800e8SDoug Rabson log_file(const char *timestr,
220b528cefcSMark Murray 	 const char *msg,
221b528cefcSMark Murray 	 void *data)
222b528cefcSMark Murray {
223b528cefcSMark Murray     struct file_data *f = data;
224*ae771770SStanislav Sedov     char *msgclean;
225*ae771770SStanislav Sedov     size_t len = strlen(msg);
226b528cefcSMark Murray     if(f->keep_open == 0)
227b528cefcSMark Murray 	f->fd = fopen(f->filename, f->mode);
228b528cefcSMark Murray     if(f->fd == NULL)
229b528cefcSMark Murray 	return;
230*ae771770SStanislav Sedov     /* make sure the log doesn't contain special chars */
231*ae771770SStanislav Sedov     msgclean = malloc((len + 1) * 4);
232*ae771770SStanislav Sedov     if (msgclean == NULL)
233*ae771770SStanislav Sedov 	goto out;
234*ae771770SStanislav Sedov     strvisx(msgclean, rk_UNCONST(msg), len, VIS_OCTAL);
235*ae771770SStanislav Sedov     fprintf(f->fd, "%s %s\n", timestr, msgclean);
236*ae771770SStanislav Sedov     free(msgclean);
237*ae771770SStanislav Sedov  out:
238c19800e8SDoug Rabson     if(f->keep_open == 0) {
239b528cefcSMark Murray 	fclose(f->fd);
240c19800e8SDoug Rabson 	f->fd = NULL;
241c19800e8SDoug Rabson     }
242b528cefcSMark Murray }
243b528cefcSMark Murray 
244*ae771770SStanislav Sedov static void KRB5_CALLCONV
close_file(void * data)245b528cefcSMark Murray close_file(void *data)
246b528cefcSMark Murray {
247b528cefcSMark Murray     struct file_data *f = data;
248b528cefcSMark Murray     if(f->keep_open && f->filename)
249b528cefcSMark Murray 	fclose(f->fd);
250b528cefcSMark Murray     free(data);
251b528cefcSMark Murray }
252b528cefcSMark Murray 
253b528cefcSMark Murray static krb5_error_code
open_file(krb5_context context,krb5_log_facility * fac,int min,int max,const char * filename,const char * mode,FILE * f,int keep_open)254b528cefcSMark Murray open_file(krb5_context context, krb5_log_facility *fac, int min, int max,
2558373020dSJacques Vidrine 	  const char *filename, const char *mode, FILE *f, int keep_open)
256b528cefcSMark Murray {
257b528cefcSMark Murray     struct file_data *fd = malloc(sizeof(*fd));
258adb0ddaeSAssar Westerlund     if(fd == NULL) {
259*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
260*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
261b528cefcSMark Murray 	return ENOMEM;
262adb0ddaeSAssar Westerlund     }
263b528cefcSMark Murray     fd->filename = filename;
264b528cefcSMark Murray     fd->mode = mode;
265b528cefcSMark Murray     fd->fd = f;
266b528cefcSMark Murray     fd->keep_open = keep_open;
267b528cefcSMark Murray 
268b528cefcSMark Murray     return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd);
269b528cefcSMark Murray }
270b528cefcSMark Murray 
271b528cefcSMark Murray 
272b528cefcSMark Murray 
273*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_addlog_dest(krb5_context context,krb5_log_facility * f,const char * orig)274adb0ddaeSAssar Westerlund krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
275b528cefcSMark Murray {
276b528cefcSMark Murray     krb5_error_code ret = 0;
277b528cefcSMark Murray     int min = 0, max = -1, n;
278b528cefcSMark Murray     char c;
279adb0ddaeSAssar Westerlund     const char *p = orig;
280adb0ddaeSAssar Westerlund 
281b528cefcSMark Murray     n = sscanf(p, "%d%c%d/", &min, &c, &max);
282b528cefcSMark Murray     if(n == 2){
283b528cefcSMark Murray 	if(c == '/') {
284b528cefcSMark Murray 	    if(min < 0){
285b528cefcSMark Murray 		max = -min;
286b528cefcSMark Murray 		min = 0;
287b528cefcSMark Murray 	    }else{
288b528cefcSMark Murray 		max = min;
289b528cefcSMark Murray 	    }
290b528cefcSMark Murray 	}
291b528cefcSMark Murray     }
292b528cefcSMark Murray     if(n){
293b528cefcSMark Murray 	p = strchr(p, '/');
294adb0ddaeSAssar Westerlund 	if(p == NULL) {
295*ae771770SStanislav Sedov 	    krb5_set_error_message(context, HEIM_ERR_LOG_PARSE,
296*ae771770SStanislav Sedov 				   N_("failed to parse \"%s\"", ""), orig);
297adb0ddaeSAssar Westerlund 	    return HEIM_ERR_LOG_PARSE;
298adb0ddaeSAssar Westerlund 	}
299b528cefcSMark Murray 	p++;
300b528cefcSMark Murray     }
301b528cefcSMark Murray     if(strcmp(p, "STDERR") == 0){
302b528cefcSMark Murray 	ret = open_file(context, f, min, max, NULL, NULL, stderr, 1);
303b528cefcSMark Murray     }else if(strcmp(p, "CONSOLE") == 0){
304b528cefcSMark Murray 	ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0);
305c19800e8SDoug Rabson     }else if(strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')){
306b528cefcSMark Murray 	char *fn;
307b528cefcSMark Murray 	FILE *file = NULL;
308b528cefcSMark Murray 	int keep_open = 0;
309b528cefcSMark Murray 	fn = strdup(p + 5);
310adb0ddaeSAssar Westerlund 	if(fn == NULL) {
311*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ENOMEM,
312*ae771770SStanislav Sedov 				   N_("malloc: out of memory", ""));
313b528cefcSMark Murray 	    return ENOMEM;
314adb0ddaeSAssar Westerlund 	}
315b528cefcSMark Murray 	if(p[4] == '='){
316b528cefcSMark Murray 	    int i = open(fn, O_WRONLY | O_CREAT |
317b528cefcSMark Murray 			 O_TRUNC | O_APPEND, 0666);
318adb0ddaeSAssar Westerlund 	    if(i < 0) {
319adb0ddaeSAssar Westerlund 		ret = errno;
320*ae771770SStanislav Sedov 		krb5_set_error_message(context, ret,
321*ae771770SStanislav Sedov 				       N_("open(%s) logile: %s", ""), fn,
322adb0ddaeSAssar Westerlund 				       strerror(ret));
323c19800e8SDoug Rabson 		free(fn);
324adb0ddaeSAssar Westerlund 		return ret;
325adb0ddaeSAssar Westerlund 	    }
326*ae771770SStanislav Sedov 	    rk_cloexec(i);
327b528cefcSMark Murray 	    file = fdopen(i, "a");
328b528cefcSMark Murray 	    if(file == NULL){
329adb0ddaeSAssar Westerlund 		ret = errno;
330b528cefcSMark Murray 		close(i);
331*ae771770SStanislav Sedov 		krb5_set_error_message(context, ret,
332*ae771770SStanislav Sedov 				       N_("fdopen(%s) logfile: %s", ""),
333*ae771770SStanislav Sedov 				       fn, strerror(ret));
334c19800e8SDoug Rabson 		free(fn);
335adb0ddaeSAssar Westerlund 		return ret;
336b528cefcSMark Murray 	    }
337b528cefcSMark Murray 	    keep_open = 1;
338b528cefcSMark Murray 	}
339b528cefcSMark Murray 	ret = open_file(context, f, min, max, fn, "a", file, keep_open);
340c19800e8SDoug Rabson     }else if(strncmp(p, "DEVICE", 6) == 0 && (p[6] == ':' || p[6] == '=')){
341b528cefcSMark Murray 	ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0);
3428373020dSJacques Vidrine     }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){
3438373020dSJacques Vidrine 	char severity[128] = "";
3448373020dSJacques Vidrine 	char facility[128] = "";
3458373020dSJacques Vidrine 	p += 6;
3468373020dSJacques Vidrine 	if(*p != '\0')
3478373020dSJacques Vidrine 	    p++;
3488373020dSJacques Vidrine 	if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1)
3498373020dSJacques Vidrine 	    strsep_copy(&p, ":", facility, sizeof(facility));
3508373020dSJacques Vidrine 	if(*severity == '\0')
3518373020dSJacques Vidrine 	    strlcpy(severity, "ERR", sizeof(severity));
3528373020dSJacques Vidrine  	if(*facility == '\0')
3538373020dSJacques Vidrine 	    strlcpy(facility, "AUTH", sizeof(facility));
354b528cefcSMark Murray 	ret = open_syslog(context, f, min, max, severity, facility);
355b528cefcSMark Murray     }else{
356b528cefcSMark Murray 	ret = HEIM_ERR_LOG_PARSE; /* XXX */
357*ae771770SStanislav Sedov 	krb5_set_error_message (context, ret,
358*ae771770SStanislav Sedov 				N_("unknown log type: %s", ""), p);
359b528cefcSMark Murray     }
360b528cefcSMark Murray     return ret;
361b528cefcSMark Murray }
362b528cefcSMark Murray 
363b528cefcSMark Murray 
364*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_openlog(krb5_context context,const char * program,krb5_log_facility ** fac)365b528cefcSMark Murray krb5_openlog(krb5_context context,
366b528cefcSMark Murray 	     const char *program,
367b528cefcSMark Murray 	     krb5_log_facility **fac)
368b528cefcSMark Murray {
369b528cefcSMark Murray     krb5_error_code ret;
370b528cefcSMark Murray     char **p, **q;
371b528cefcSMark Murray 
372b528cefcSMark Murray     ret = krb5_initlog(context, program, fac);
373b528cefcSMark Murray     if(ret)
374b528cefcSMark Murray 	return ret;
375b528cefcSMark Murray 
376b528cefcSMark Murray     p = krb5_config_get_strings(context, NULL, "logging", program, NULL);
377b528cefcSMark Murray     if(p == NULL)
378b528cefcSMark Murray 	p = krb5_config_get_strings(context, NULL, "logging", "default", NULL);
379b528cefcSMark Murray     if(p){
380*ae771770SStanislav Sedov 	for(q = p; *q && ret == 0; q++)
381b528cefcSMark Murray 	    ret = krb5_addlog_dest(context, *fac, *q);
382b528cefcSMark Murray 	krb5_config_free_strings(p);
383b528cefcSMark Murray     }else
384b528cefcSMark Murray 	ret = krb5_addlog_dest(context, *fac, "SYSLOG");
385*ae771770SStanislav Sedov     return ret;
386b528cefcSMark Murray }
387b528cefcSMark Murray 
388*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_closelog(krb5_context context,krb5_log_facility * fac)389b528cefcSMark Murray krb5_closelog(krb5_context context,
390b528cefcSMark Murray 	      krb5_log_facility *fac)
391b528cefcSMark Murray {
392b528cefcSMark Murray     int i;
393b528cefcSMark Murray     for(i = 0; i < fac->len; i++)
394c19800e8SDoug Rabson 	(*fac->val[i].close_func)(fac->val[i].data);
395c19800e8SDoug Rabson     free(fac->val);
396c19800e8SDoug Rabson     free(fac->program);
397c19800e8SDoug Rabson     fac->val = NULL;
398c19800e8SDoug Rabson     fac->len = 0;
399c19800e8SDoug Rabson     fac->program = NULL;
400c19800e8SDoug Rabson     free(fac);
401b528cefcSMark Murray     return 0;
402b528cefcSMark Murray }
403b528cefcSMark Murray 
404b528cefcSMark Murray #undef __attribute__
405b528cefcSMark Murray #define __attribute__(X)
406b528cefcSMark Murray 
407*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_vlog_msg(krb5_context context,krb5_log_facility * fac,char ** reply,int level,const char * fmt,va_list ap)408b528cefcSMark Murray krb5_vlog_msg(krb5_context context,
409b528cefcSMark Murray 	      krb5_log_facility *fac,
410b528cefcSMark Murray 	      char **reply,
411b528cefcSMark Murray 	      int level,
412b528cefcSMark Murray 	      const char *fmt,
413b528cefcSMark Murray 	      va_list ap)
414b528cefcSMark Murray      __attribute__((format (printf, 5, 0)))
415b528cefcSMark Murray {
4160cadf2f4SJacques Vidrine 
4170cadf2f4SJacques Vidrine     char *msg = NULL;
4180cadf2f4SJacques Vidrine     const char *actual = NULL;
419b528cefcSMark Murray     char buf[64];
4200cadf2f4SJacques Vidrine     time_t t = 0;
421b528cefcSMark Murray     int i;
422b528cefcSMark Murray 
4230cadf2f4SJacques Vidrine     for(i = 0; fac && i < fac->len; i++)
4240cadf2f4SJacques Vidrine 	if(fac->val[i].min <= level &&
4250cadf2f4SJacques Vidrine 	   (fac->val[i].max < 0 || fac->val[i].max >= level)) {
4260cadf2f4SJacques Vidrine 	    if(t == 0) {
427b528cefcSMark Murray 		t = time(NULL);
4285e9cd1aeSAssar Westerlund 		krb5_format_time(context, t, buf, sizeof(buf), TRUE);
4290cadf2f4SJacques Vidrine 	    }
4300cadf2f4SJacques Vidrine 	    if(actual == NULL) {
431*ae771770SStanislav Sedov 		int ret = vasprintf(&msg, fmt, ap);
432*ae771770SStanislav Sedov 		if(ret < 0 || msg == NULL)
4330cadf2f4SJacques Vidrine 		    actual = fmt;
4340cadf2f4SJacques Vidrine 		else
4350cadf2f4SJacques Vidrine 		    actual = msg;
4360cadf2f4SJacques Vidrine 	    }
437c19800e8SDoug Rabson 	    (*fac->val[i].log_func)(buf, actual, fac->val[i].data);
4380cadf2f4SJacques Vidrine 	}
4390cadf2f4SJacques Vidrine     if(reply == NULL)
4400cadf2f4SJacques Vidrine 	free(msg);
4410cadf2f4SJacques Vidrine     else
442b528cefcSMark Murray 	*reply = msg;
443b528cefcSMark Murray     return 0;
444b528cefcSMark Murray }
445b528cefcSMark Murray 
446*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_vlog(krb5_context context,krb5_log_facility * fac,int level,const char * fmt,va_list ap)447b528cefcSMark Murray krb5_vlog(krb5_context context,
448b528cefcSMark Murray 	  krb5_log_facility *fac,
449b528cefcSMark Murray 	  int level,
450b528cefcSMark Murray 	  const char *fmt,
451b528cefcSMark Murray 	  va_list ap)
452b528cefcSMark Murray      __attribute__((format (printf, 4, 0)))
453b528cefcSMark Murray {
4540cadf2f4SJacques Vidrine     return krb5_vlog_msg(context, fac, NULL, level, fmt, ap);
455b528cefcSMark Murray }
456b528cefcSMark Murray 
457*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_log_msg(krb5_context context,krb5_log_facility * fac,int level,char ** reply,const char * fmt,...)458b528cefcSMark Murray krb5_log_msg(krb5_context context,
459b528cefcSMark Murray 	     krb5_log_facility *fac,
460b528cefcSMark Murray 	     int level,
461b528cefcSMark Murray 	     char **reply,
462b528cefcSMark Murray 	     const char *fmt,
463b528cefcSMark Murray 	     ...)
464b528cefcSMark Murray      __attribute__((format (printf, 5, 6)))
465b528cefcSMark Murray {
466b528cefcSMark Murray     va_list ap;
467b528cefcSMark Murray     krb5_error_code ret;
468b528cefcSMark Murray 
469b528cefcSMark Murray     va_start(ap, fmt);
470b528cefcSMark Murray     ret = krb5_vlog_msg(context, fac, reply, level, fmt, ap);
471b528cefcSMark Murray     va_end(ap);
472b528cefcSMark Murray     return ret;
473b528cefcSMark Murray }
474b528cefcSMark Murray 
475b528cefcSMark Murray 
476*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_log(krb5_context context,krb5_log_facility * fac,int level,const char * fmt,...)477b528cefcSMark Murray krb5_log(krb5_context context,
478b528cefcSMark Murray 	 krb5_log_facility *fac,
479b528cefcSMark Murray 	 int level,
480b528cefcSMark Murray 	 const char *fmt,
481b528cefcSMark Murray 	 ...)
482b528cefcSMark Murray      __attribute__((format (printf, 4, 5)))
483b528cefcSMark Murray {
484b528cefcSMark Murray     va_list ap;
485b528cefcSMark Murray     krb5_error_code ret;
486b528cefcSMark Murray 
487b528cefcSMark Murray     va_start(ap, fmt);
488b528cefcSMark Murray     ret = krb5_vlog(context, fac, level, fmt, ap);
489b528cefcSMark Murray     va_end(ap);
490b528cefcSMark Murray     return ret;
491b528cefcSMark Murray }
492b528cefcSMark Murray 
493*ae771770SStanislav Sedov void KRB5_LIB_FUNCTION
_krb5_debug(krb5_context context,int level,const char * fmt,...)494*ae771770SStanislav Sedov _krb5_debug(krb5_context context,
495*ae771770SStanislav Sedov 	    int level,
496*ae771770SStanislav Sedov 	    const char *fmt,
497*ae771770SStanislav Sedov 	    ...)
498*ae771770SStanislav Sedov     __attribute__((format (printf, 3, 4)))
499*ae771770SStanislav Sedov {
500*ae771770SStanislav Sedov     va_list ap;
501*ae771770SStanislav Sedov 
502*ae771770SStanislav Sedov     if (context == NULL || context->debug_dest == NULL)
503*ae771770SStanislav Sedov 	return;
504*ae771770SStanislav Sedov 
505*ae771770SStanislav Sedov     va_start(ap, fmt);
506*ae771770SStanislav Sedov     krb5_vlog(context, context->debug_dest, level, fmt, ap);
507*ae771770SStanislav Sedov     va_end(ap);
508*ae771770SStanislav Sedov }
509*ae771770SStanislav Sedov 
510*ae771770SStanislav Sedov krb5_boolean KRB5_LIB_FUNCTION
_krb5_have_debug(krb5_context context,int level)511*ae771770SStanislav Sedov _krb5_have_debug(krb5_context context, int level)
512*ae771770SStanislav Sedov {
513*ae771770SStanislav Sedov     if (context == NULL || context->debug_dest == NULL)
514*ae771770SStanislav Sedov 	return 0 ;
515*ae771770SStanislav Sedov     return 1;
516*ae771770SStanislav Sedov }
517