1 /* $OpenBSD: parsemsg.c,v 1.1 2022/01/13 10:34:07 martijn Exp $ */ 2 3 /* 4 * Copyright (c) 2022 Martijn van Duren <martijn@openbsd> 5 * Copyright (c) 2014-2021 Alexander Bluhm <bluhm@genua.de> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <ctype.h> 21 #include <limits.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <syslog.h> 26 27 #include "parsemsg.h" 28 #include "syslogd.h" 29 30 size_t parsemsg_timestamp_bsd(const char *, char *); 31 size_t parsemsg_timestamp_v1(const char *, char *); 32 size_t parsemsg_prog(const char *, char *); 33 34 struct msg * 35 parsemsg(const char *msgstr, struct msg *msg) 36 { 37 size_t n; 38 39 msg->m_pri = -1; 40 msgstr += parsemsg_priority(msgstr, &msg->m_pri); 41 if (msg->m_pri &~ (LOG_FACMASK|LOG_PRIMASK)) 42 msg->m_pri = -1; 43 44 if ((n = parsemsg_timestamp_bsd(msgstr, msg->m_timestamp)) == 0) 45 n = parsemsg_timestamp_v1(msgstr, msg->m_timestamp); 46 msgstr += n; 47 48 while (isspace(msgstr[0])) 49 msgstr++; 50 51 parsemsg_prog(msgstr, msg->m_prog); 52 53 strlcpy(msg->m_msg, msgstr, sizeof(msg->m_msg)); 54 55 return msg; 56 } 57 58 /* 59 * Parse a priority code of the form "<123>" into pri, and return the 60 * length of the priority code including the surrounding angle brackets. 61 */ 62 size_t 63 parsemsg_priority(const char *msg, int *pri) 64 { 65 size_t nlen; 66 char buf[11]; 67 const char *errstr; 68 int maybepri; 69 70 if (*msg++ == '<') { 71 nlen = strspn(msg, "1234567890"); 72 if (nlen > 0 && nlen < sizeof(buf) && msg[nlen] == '>') { 73 strlcpy(buf, msg, nlen + 1); 74 maybepri = strtonum(buf, 0, INT_MAX, &errstr); 75 if (errstr == NULL) { 76 *pri = maybepri; 77 return nlen + 2; 78 } 79 } 80 } 81 82 return 0; 83 } 84 85 size_t 86 parsemsg_timestamp_bsd(const char *msg, char *timestamp) 87 { 88 size_t i; 89 90 timestamp[0] = '\0'; 91 for (i = 0; i < 16; i++) { 92 if (msg[i] == '\0') 93 return 0; 94 } 95 96 if (msg[3] == ' ' && msg[6] == ' ' && msg[9] == ':' && msg[12] == ':' && 97 msg[15] == ' ') { 98 /* BSD syslog TIMESTAMP, RFC 3164 */ 99 if (!ZuluTime) 100 strlcpy(timestamp, msg, 16); 101 return 16; 102 } 103 104 return 0; 105 } 106 107 size_t 108 parsemsg_timestamp_v1(const char *msgstr, char *timestamp) 109 { 110 const char *msg; 111 size_t msglen, i; 112 113 for (msglen = 0; msglen < 33; msglen++) { 114 if(msgstr[msglen] == '\0') 115 break; 116 } 117 118 msg = msgstr; 119 timestamp[0] = '\0'; 120 121 if (msglen >= 20 && 122 isdigit(msg[0]) && isdigit(msg[1]) && isdigit(msg[2]) && 123 isdigit(msg[3]) && msg[4] == '-' && 124 isdigit(msg[5]) && isdigit(msg[6]) && msg[7] == '-' && 125 isdigit(msg[8]) && isdigit(msg[9]) && msg[10] == 'T' && 126 isdigit(msg[11]) && isdigit(msg[12]) && msg[13] == ':' && 127 isdigit(msg[14]) && isdigit(msg[15]) && msg[16] == ':' && 128 isdigit(msg[17]) && isdigit(msg[18]) && (msg[19] == '.' || 129 msg[19] == 'Z' || msg[19] == '+' || msg[19] == '-')) { 130 /* FULL-DATE "T" FULL-TIME, RFC 5424 */ 131 strlcpy(timestamp, msg, 33); 132 msg += 19; 133 msglen -= 19; 134 i = 0; 135 if (msglen >= 3 && msg[0] == '.' && isdigit(msg[1])) { 136 /* TIME-SECFRAC */ 137 msg += 2; 138 msglen -= 2; 139 i += 2; 140 while(i < 7 && msglen >= 1 && isdigit(msg[0])) { 141 msg++; 142 msglen--; 143 i++; 144 } 145 } 146 if (msglen >= 2 && msg[0] == 'Z' && msg[1] == ' ') { 147 /* "Z" */ 148 timestamp[20+i] = '\0'; 149 msg += 2; 150 } else if (msglen >= 7 && 151 (msg[0] == '+' || msg[0] == '-') && 152 isdigit(msg[1]) && isdigit(msg[2]) && 153 msg[3] == ':' && 154 isdigit(msg[4]) && isdigit(msg[5]) && 155 msg[6] == ' ') { 156 /* TIME-NUMOFFSET */ 157 timestamp[25+i] = '\0'; 158 msg += 7; 159 } else { 160 /* invalid time format, roll back */ 161 timestamp[0] = '\0'; 162 return 0; 163 } 164 } else if (msglen >= 2 && msg[0] == '-' && msg[1] == ' ') { 165 /* NILVALUE, RFC 5424 */ 166 msg += 2; 167 } 168 169 return msg - msgstr; 170 } 171 172 size_t 173 parsemsg_prog(const char *msg, char *prog) 174 { 175 size_t i; 176 177 for (i = 0; i < NAME_MAX; i++) { 178 if (!isalnum((unsigned char)msg[i]) && 179 msg[i] != '-' && msg[i] != '.' && msg[i] != '_') 180 break; 181 prog[i] = msg[i]; 182 } 183 prog[i] = '\0'; 184 185 return i; 186 } 187