GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ssh/lib/../log.c Lines: 17 131 13.0 %
Date: 2017-11-13 Branches: 1 62 1.6 %

Line Branch Exec Source
1
/* $OpenBSD: log.c,v 1.50 2017/05/17 01:24:17 djm Exp $ */
2
/*
3
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5
 *                    All rights reserved
6
 *
7
 * As far as I am concerned, the code I have written for this software
8
 * can be used freely for any purpose.  Any derived versions of this
9
 * software must be clearly marked as such, and if the derived work is
10
 * incompatible with the protocol description in the RFC file, it must be
11
 * called by a name other than "ssh" or "Secure Shell".
12
 */
13
/*
14
 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
15
 *
16
 * Redistribution and use in source and binary forms, with or without
17
 * modification, are permitted provided that the following conditions
18
 * are met:
19
 * 1. Redistributions of source code must retain the above copyright
20
 *    notice, this list of conditions and the following disclaimer.
21
 * 2. Redistributions in binary form must reproduce the above copyright
22
 *    notice, this list of conditions and the following disclaimer in the
23
 *    documentation and/or other materials provided with the distribution.
24
 *
25
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
 */
36
37
#include <sys/types.h>
38
39
#include <fcntl.h>
40
#include <stdarg.h>
41
#include <stdio.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <syslog.h>
45
#include <unistd.h>
46
#include <errno.h>
47
#include <vis.h>
48
49
#include "log.h"
50
51
static LogLevel log_level = SYSLOG_LEVEL_INFO;
52
static int log_on_stderr = 1;
53
static int log_stderr_fd = STDERR_FILENO;
54
static int log_facility = LOG_AUTH;
55
static char *argv0;
56
static log_handler_fn *log_handler;
57
static void *log_handler_ctx;
58
59
extern char *__progname;
60
61
/* textual representation of log-facilities/levels */
62
63
static struct {
64
	const char *name;
65
	SyslogFacility val;
66
} log_facilities[] = {
67
	{ "DAEMON",	SYSLOG_FACILITY_DAEMON },
68
	{ "USER",	SYSLOG_FACILITY_USER },
69
	{ "AUTH",	SYSLOG_FACILITY_AUTH },
70
	{ "LOCAL0",	SYSLOG_FACILITY_LOCAL0 },
71
	{ "LOCAL1",	SYSLOG_FACILITY_LOCAL1 },
72
	{ "LOCAL2",	SYSLOG_FACILITY_LOCAL2 },
73
	{ "LOCAL3",	SYSLOG_FACILITY_LOCAL3 },
74
	{ "LOCAL4",	SYSLOG_FACILITY_LOCAL4 },
75
	{ "LOCAL5",	SYSLOG_FACILITY_LOCAL5 },
76
	{ "LOCAL6",	SYSLOG_FACILITY_LOCAL6 },
77
	{ "LOCAL7",	SYSLOG_FACILITY_LOCAL7 },
78
	{ NULL,		SYSLOG_FACILITY_NOT_SET }
79
};
80
81
static struct {
82
	const char *name;
83
	LogLevel val;
84
} log_levels[] =
85
{
86
	{ "QUIET",	SYSLOG_LEVEL_QUIET },
87
	{ "FATAL",	SYSLOG_LEVEL_FATAL },
88
	{ "ERROR",	SYSLOG_LEVEL_ERROR },
89
	{ "INFO",	SYSLOG_LEVEL_INFO },
90
	{ "VERBOSE",	SYSLOG_LEVEL_VERBOSE },
91
	{ "DEBUG",	SYSLOG_LEVEL_DEBUG1 },
92
	{ "DEBUG1",	SYSLOG_LEVEL_DEBUG1 },
93
	{ "DEBUG2",	SYSLOG_LEVEL_DEBUG2 },
94
	{ "DEBUG3",	SYSLOG_LEVEL_DEBUG3 },
95
	{ NULL,		SYSLOG_LEVEL_NOT_SET }
96
};
97
98
SyslogFacility
99
log_facility_number(char *name)
100
{
101
	int i;
102
103
	if (name != NULL)
104
		for (i = 0; log_facilities[i].name; i++)
105
			if (strcasecmp(log_facilities[i].name, name) == 0)
106
				return log_facilities[i].val;
107
	return SYSLOG_FACILITY_NOT_SET;
108
}
109
110
const char *
111
log_facility_name(SyslogFacility facility)
112
{
113
	u_int i;
114
115
	for (i = 0;  log_facilities[i].name; i++)
116
		if (log_facilities[i].val == facility)
117
			return log_facilities[i].name;
118
	return NULL;
119
}
120
121
LogLevel
122
log_level_number(char *name)
123
{
124
	int i;
125
126
	if (name != NULL)
127
		for (i = 0; log_levels[i].name; i++)
128
			if (strcasecmp(log_levels[i].name, name) == 0)
129
				return log_levels[i].val;
130
	return SYSLOG_LEVEL_NOT_SET;
131
}
132
133
const char *
134
log_level_name(LogLevel level)
135
{
136
	u_int i;
137
138
	for (i = 0; log_levels[i].name != NULL; i++)
139
		if (log_levels[i].val == level)
140
			return log_levels[i].name;
141
	return NULL;
142
}
143
144
/* Error messages that should be logged. */
145
146
void
147
error(const char *fmt,...)
148
{
149
	va_list args;
150
151
	va_start(args, fmt);
152
	do_log(SYSLOG_LEVEL_ERROR, fmt, args);
153
	va_end(args);
154
}
155
156
void
157
sigdie(const char *fmt,...)
158
{
159
	va_list args;
160
161
	va_start(args, fmt);
162
	do_log(SYSLOG_LEVEL_FATAL, fmt, args);
163
	va_end(args);
164
	_exit(1);
165
}
166
167
void
168
logdie(const char *fmt,...)
169
{
170
	va_list args;
171
172
	va_start(args, fmt);
173
	do_log(SYSLOG_LEVEL_INFO, fmt, args);
174
	va_end(args);
175
	cleanup_exit(255);
176
}
177
178
/* Log this message (information that usually should go to the log). */
179
180
void
181
logit(const char *fmt,...)
182
{
183
	va_list args;
184
185
	va_start(args, fmt);
186
	do_log(SYSLOG_LEVEL_INFO, fmt, args);
187
	va_end(args);
188
}
189
190
/* More detailed messages (information that does not need to go to the log). */
191
192
void
193
verbose(const char *fmt,...)
194
{
195
	va_list args;
196
197
	va_start(args, fmt);
198
	do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
199
	va_end(args);
200
}
201
202
/* Debugging messages that should not be logged during normal operation. */
203
204
void
205
debug(const char *fmt,...)
206
{
207
57488
	va_list args;
208
209
28744
	va_start(args, fmt);
210
28744
	do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
211
28744
	va_end(args);
212
28744
}
213
214
void
215
debug2(const char *fmt,...)
216
{
217
28744
	va_list args;
218
219
14372
	va_start(args, fmt);
220
14372
	do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
221
14372
	va_end(args);
222
14372
}
223
224
void
225
debug3(const char *fmt,...)
226
{
227
	va_list args;
228
229
	va_start(args, fmt);
230
	do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
231
	va_end(args);
232
}
233
234
/*
235
 * Initialize the log.
236
 */
237
238
void
239
log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
240
{
241
	argv0 = av0;
242
243
	if (log_change_level(level) != 0) {
244
		fprintf(stderr, "Unrecognized internal syslog level code %d\n",
245
		    (int) level);
246
		exit(1);
247
	}
248
249
	log_handler = NULL;
250
	log_handler_ctx = NULL;
251
252
	log_on_stderr = on_stderr;
253
	if (on_stderr)
254
		return;
255
256
	switch (facility) {
257
	case SYSLOG_FACILITY_DAEMON:
258
		log_facility = LOG_DAEMON;
259
		break;
260
	case SYSLOG_FACILITY_USER:
261
		log_facility = LOG_USER;
262
		break;
263
	case SYSLOG_FACILITY_AUTH:
264
		log_facility = LOG_AUTH;
265
		break;
266
	case SYSLOG_FACILITY_LOCAL0:
267
		log_facility = LOG_LOCAL0;
268
		break;
269
	case SYSLOG_FACILITY_LOCAL1:
270
		log_facility = LOG_LOCAL1;
271
		break;
272
	case SYSLOG_FACILITY_LOCAL2:
273
		log_facility = LOG_LOCAL2;
274
		break;
275
	case SYSLOG_FACILITY_LOCAL3:
276
		log_facility = LOG_LOCAL3;
277
		break;
278
	case SYSLOG_FACILITY_LOCAL4:
279
		log_facility = LOG_LOCAL4;
280
		break;
281
	case SYSLOG_FACILITY_LOCAL5:
282
		log_facility = LOG_LOCAL5;
283
		break;
284
	case SYSLOG_FACILITY_LOCAL6:
285
		log_facility = LOG_LOCAL6;
286
		break;
287
	case SYSLOG_FACILITY_LOCAL7:
288
		log_facility = LOG_LOCAL7;
289
		break;
290
	default:
291
		fprintf(stderr,
292
		    "Unrecognized internal syslog facility code %d\n",
293
		    (int) facility);
294
		exit(1);
295
	}
296
}
297
298
int
299
log_change_level(LogLevel new_log_level)
300
{
301
	/* no-op if log_init has not been called */
302
	if (argv0 == NULL)
303
		return 0;
304
305
	switch (new_log_level) {
306
	case SYSLOG_LEVEL_QUIET:
307
	case SYSLOG_LEVEL_FATAL:
308
	case SYSLOG_LEVEL_ERROR:
309
	case SYSLOG_LEVEL_INFO:
310
	case SYSLOG_LEVEL_VERBOSE:
311
	case SYSLOG_LEVEL_DEBUG1:
312
	case SYSLOG_LEVEL_DEBUG2:
313
	case SYSLOG_LEVEL_DEBUG3:
314
		log_level = new_log_level;
315
		return 0;
316
	default:
317
		return -1;
318
	}
319
}
320
321
int
322
log_is_on_stderr(void)
323
{
324
	return log_on_stderr && log_stderr_fd == STDERR_FILENO;
325
}
326
327
/* redirect what would usually get written to stderr to specified file */
328
void
329
log_redirect_stderr_to(const char *logfile)
330
{
331
	int fd;
332
333
	if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
334
		fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile,
335
		     strerror(errno));
336
		exit(1);
337
	}
338
	log_stderr_fd = fd;
339
}
340
341
#define MSGBUFSIZ 1024
342
343
void
344
set_log_handler(log_handler_fn *handler, void *ctx)
345
{
346
	log_handler = handler;
347
	log_handler_ctx = ctx;
348
}
349
350
void
351
do_log2(LogLevel level, const char *fmt,...)
352
{
353
	va_list args;
354
355
	va_start(args, fmt);
356
	do_log(level, fmt, args);
357
	va_end(args);
358
}
359
360
void
361
do_log(LogLevel level, const char *fmt, va_list args)
362
{
363
86232
	struct syslog_data sdata = SYSLOG_DATA_INIT;
364
43116
	char msgbuf[MSGBUFSIZ];
365
43116
	char fmtbuf[MSGBUFSIZ];
366
	char *txt = NULL;
367
	int pri = LOG_INFO;
368
43116
	int saved_errno = errno;
369
	log_handler_fn *tmp_handler;
370
371
43116
	if (level > log_level)
372
43116
		return;
373
374
	switch (level) {
375
	case SYSLOG_LEVEL_FATAL:
376
		if (!log_on_stderr)
377
			txt = "fatal";
378
		pri = LOG_CRIT;
379
		break;
380
	case SYSLOG_LEVEL_ERROR:
381
		if (!log_on_stderr)
382
			txt = "error";
383
		pri = LOG_ERR;
384
		break;
385
	case SYSLOG_LEVEL_INFO:
386
		pri = LOG_INFO;
387
		break;
388
	case SYSLOG_LEVEL_VERBOSE:
389
		pri = LOG_INFO;
390
		break;
391
	case SYSLOG_LEVEL_DEBUG1:
392
		txt = "debug1";
393
		pri = LOG_DEBUG;
394
		break;
395
	case SYSLOG_LEVEL_DEBUG2:
396
		txt = "debug2";
397
		pri = LOG_DEBUG;
398
		break;
399
	case SYSLOG_LEVEL_DEBUG3:
400
		txt = "debug3";
401
		pri = LOG_DEBUG;
402
		break;
403
	default:
404
		txt = "internal error";
405
		pri = LOG_ERR;
406
		break;
407
	}
408
	if (txt != NULL && log_handler == NULL) {
409
		snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
410
		vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
411
	} else {
412
		vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
413
	}
414
	strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), VIS_SAFE|VIS_OCTAL);
415
	if (log_handler != NULL) {
416
		/* Avoid recursion */
417
		tmp_handler = log_handler;
418
		log_handler = NULL;
419
		tmp_handler(level, fmtbuf, log_handler_ctx);
420
		log_handler = tmp_handler;
421
	} else if (log_on_stderr) {
422
		snprintf(msgbuf, sizeof msgbuf, "%.*s\r\n",
423
		    (int)sizeof msgbuf - 3, fmtbuf);
424
		(void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
425
	} else {
426
		openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
427
		syslog_r(pri, &sdata, "%.500s", fmtbuf);
428
		closelog_r(&sdata);
429
	}
430
	errno = saved_errno;
431
43116
}