[BACK]Return to parsemsg.c CVS log [TXT][DIR] Up to [local] / src / usr.sbin / syslogd

File: [local] / src / usr.sbin / syslogd / parsemsg.c (download)

Revision 1.1, Thu Jan 13 10:34:07 2022 UTC (2 years, 4 months ago) by martijn
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, HEAD

Move parsing of incoming syslog messages to their own section.
This should make it more manageable.

No functional change intended, debugging output slightly changed.

help from and OK bluhm@

/*	$OpenBSD: parsemsg.c,v 1.1 2022/01/13 10:34:07 martijn Exp $	*/

/*
 * Copyright (c) 2022 Martijn van Duren <martijn@openbsd>
 * Copyright (c) 2014-2021 Alexander Bluhm <bluhm@genua.de>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>

#include "parsemsg.h"
#include "syslogd.h"

size_t parsemsg_timestamp_bsd(const char *, char *);
size_t parsemsg_timestamp_v1(const char *, char *);
size_t parsemsg_prog(const char *, char *);

struct msg *
parsemsg(const char *msgstr, struct msg *msg)
{
	size_t n;

	msg->m_pri = -1;
	msgstr += parsemsg_priority(msgstr, &msg->m_pri);
	if (msg->m_pri &~ (LOG_FACMASK|LOG_PRIMASK))
		msg->m_pri = -1;

	if ((n = parsemsg_timestamp_bsd(msgstr, msg->m_timestamp)) == 0)
		n = parsemsg_timestamp_v1(msgstr, msg->m_timestamp);
	msgstr += n;

	while (isspace(msgstr[0]))
		msgstr++;

	parsemsg_prog(msgstr, msg->m_prog);

	strlcpy(msg->m_msg, msgstr, sizeof(msg->m_msg));

	return msg;
}

/*
 * Parse a priority code of the form "<123>" into pri, and return the
 * length of the priority code including the surrounding angle brackets.
 */
size_t
parsemsg_priority(const char *msg, int *pri)
{
	size_t nlen;
	char buf[11];
	const char *errstr;
	int maybepri;

	if (*msg++ == '<') {
		nlen = strspn(msg, "1234567890");
		if (nlen > 0 && nlen < sizeof(buf) && msg[nlen] == '>') {
			strlcpy(buf, msg, nlen + 1);
			maybepri = strtonum(buf, 0, INT_MAX, &errstr);
			if (errstr == NULL) {
				*pri = maybepri;
				return nlen + 2;
			}
		}
	}

	return 0;
}

size_t
parsemsg_timestamp_bsd(const char *msg, char *timestamp)
{
	size_t i;

	timestamp[0] = '\0';
	for (i = 0; i < 16; i++) {
		if (msg[i] == '\0')
			return 0;
	}

	if (msg[3] == ' ' && msg[6] == ' ' && msg[9] == ':' && msg[12] == ':' &&
	    msg[15] == ' ') {
		/* BSD syslog TIMESTAMP, RFC 3164 */
		if (!ZuluTime)
			strlcpy(timestamp, msg, 16);
		return 16;
	}

	return 0;
}

size_t
parsemsg_timestamp_v1(const char *msgstr, char *timestamp)
{
	const char *msg;
	size_t msglen, i;

	for (msglen = 0; msglen < 33; msglen++) {
		if(msgstr[msglen] == '\0')
			break;
	}

	msg = msgstr;
	timestamp[0] = '\0';

	if (msglen >= 20 &&
	    isdigit(msg[0]) && isdigit(msg[1]) && isdigit(msg[2]) &&
	    isdigit(msg[3]) && msg[4] == '-' &&
	    isdigit(msg[5]) && isdigit(msg[6]) && msg[7] == '-' &&
	    isdigit(msg[8]) && isdigit(msg[9]) && msg[10] == 'T' &&
	    isdigit(msg[11]) && isdigit(msg[12]) && msg[13] == ':' &&
	    isdigit(msg[14]) && isdigit(msg[15]) && msg[16] == ':' &&
	    isdigit(msg[17]) && isdigit(msg[18]) && (msg[19] == '.' ||
	    msg[19] == 'Z' || msg[19] == '+' || msg[19] == '-')) {
		/* FULL-DATE "T" FULL-TIME, RFC 5424 */
		strlcpy(timestamp, msg, 33);
		msg += 19;
		msglen -= 19;
		i = 0;
		if (msglen >= 3 && msg[0] == '.' && isdigit(msg[1])) {
			/* TIME-SECFRAC */
			msg += 2;
			msglen -= 2;
			i += 2;
			while(i < 7 && msglen >= 1 && isdigit(msg[0])) {
				msg++;
				msglen--;
				i++;
			}
		}
		if (msglen >= 2 && msg[0] == 'Z' && msg[1] == ' ') {
			/* "Z" */
			timestamp[20+i] = '\0';
			msg += 2;
		} else if (msglen >= 7 &&
		    (msg[0] == '+' || msg[0] == '-') &&
		    isdigit(msg[1]) && isdigit(msg[2]) &&
		    msg[3] == ':' &&
		    isdigit(msg[4]) && isdigit(msg[5]) &&
		    msg[6] == ' ') {
			/* TIME-NUMOFFSET */
			timestamp[25+i] = '\0';
			msg += 7;
		} else {
			/* invalid time format, roll back */
			timestamp[0] = '\0';
			return 0;
		}
	} else if (msglen >= 2 && msg[0] == '-' && msg[1] == ' ') {
		/* NILVALUE, RFC 5424 */
		msg += 2;
	}

	return msg - msgstr;
}

size_t
parsemsg_prog(const char *msg, char *prog)
{
	size_t i;

	for (i = 0; i < NAME_MAX; i++) {
		if (!isalnum((unsigned char)msg[i]) &&
		    msg[i] != '-' && msg[i] != '.' && msg[i] != '_')
			break;
		prog[i] = msg[i];
	}
	prog[i] = '\0';

	return i;
}