Skip to content

Commit 48049c6

Browse files
committed
Add support for Cisco syslog events
1 parent 2491548 commit 48049c6

File tree

2 files changed

+285
-0
lines changed

2 files changed

+285
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
package org.graylog2.syslog4j.server.impl.event;
2+
3+
import java.net.InetAddress;
4+
import java.time.ZoneOffset;
5+
import java.time.ZonedDateTime;
6+
import java.time.format.DateTimeFormatter;
7+
import java.time.format.DateTimeParseException;
8+
import java.util.Calendar;
9+
import java.util.Date;
10+
import java.util.Locale;
11+
12+
/**
13+
* CiscoSyslogServerEvent provides an implementation of the
14+
* SyslogServerEventIF interface that supports receiving of
15+
* Cisco syslog messages.
16+
*
17+
* @see <a href="http://www.ciscopress.com/articles/article.asp?p=426638">An Overview of the syslog Protocol</a>
18+
*/
19+
public class CiscoSyslogServerEvent extends SyslogServerEvent {
20+
private static final DateTimeFormatter DEFAULT_FORMATTER =
21+
DateTimeFormatter
22+
.ofPattern("yyyy MMM ppd HH:mm:ss[.SSS][ zzz]", Locale.ROOT)
23+
.withZone(ZoneOffset.UTC);
24+
private int sequenceNumber = 0;
25+
26+
public CiscoSyslogServerEvent(final byte[] message, int length, InetAddress inetAddress) {
27+
super();
28+
29+
initialize(message, length, inetAddress);
30+
parse();
31+
}
32+
33+
public CiscoSyslogServerEvent(final String message, InetAddress inetAddress) {
34+
super();
35+
36+
initialize(message, inetAddress);
37+
parse();
38+
}
39+
40+
@Override
41+
protected void parsePriority() {
42+
if (this.message.charAt(0) == '<') {
43+
int i = this.message.indexOf(">");
44+
45+
if (i <= 4 && i > -1) {
46+
String priorityStr = this.message.substring(1, i);
47+
48+
int priority = 0;
49+
try {
50+
priority = Integer.parseInt(priorityStr);
51+
this.facility = priority >> 3;
52+
this.level = priority - (this.facility << 3);
53+
54+
this.message = this.message.substring(i + 1);
55+
56+
parseSequenceNumber();
57+
parseDate();
58+
} catch (NumberFormatException nfe) {
59+
//
60+
}
61+
62+
parseHost();
63+
}
64+
}
65+
}
66+
67+
private void parseSequenceNumber() {
68+
int i = this.message.indexOf(':');
69+
if (i > -1) {
70+
String sequenceNumberStr = this.message.substring(0, i);
71+
if (sequenceNumberStr.isEmpty()) {
72+
this.message = this.message.substring(i + 1);
73+
} else {
74+
try {
75+
this.sequenceNumber = Integer.parseInt(sequenceNumberStr);
76+
this.message = this.message.substring(i + 1);
77+
} catch (NumberFormatException nfe) {
78+
//
79+
}
80+
}
81+
}
82+
}
83+
84+
@Override
85+
protected void parseHost() {
86+
if (message.indexOf('%') < 1) {
87+
this.host = "";
88+
} else {
89+
int i = this.message.indexOf(' ');
90+
if (i > -1) {
91+
this.host = this.message.substring(0, i).trim();
92+
93+
// Skip ' ' and ':' characters
94+
char c = message.charAt(i);
95+
while (c == ' ' || c == ':') {
96+
c = message.charAt(++i);
97+
}
98+
99+
this.message = this.message.substring(i);
100+
}
101+
}
102+
}
103+
104+
@Override
105+
protected void parseDate() {
106+
// Skip leading spaces
107+
while (message.charAt(0) == ' ') {
108+
message = message.substring(1);
109+
}
110+
111+
// Skip leading asterisk
112+
if (message.charAt(0) == '*') {
113+
message = message.substring(1);
114+
}
115+
116+
int dateLength = message.indexOf(": ");
117+
if (this.message.length() > dateLength) {
118+
boolean isYearMissing = Character.isLetter(message.charAt(0));
119+
String originalDate = this.message.substring(0, dateLength);
120+
DateTimeFormatter formatter = DEFAULT_FORMATTER;
121+
122+
// Hacky override for: "Mar 06 2016 12:53:10 DEVICENAME :"
123+
if (Character.isDigit(message.charAt(7))
124+
&& Character.isDigit(message.charAt(8))
125+
&& Character.isDigit(message.charAt(9))
126+
&& Character.isDigit(message.charAt(10))) {
127+
dateLength = 20;
128+
isYearMissing = false;
129+
originalDate = this.message.substring(0, dateLength);
130+
formatter = DateTimeFormatter
131+
.ofPattern("MMM ppd yyyy HH:mm:ss", Locale.ROOT)
132+
.withZone(ZoneOffset.UTC);
133+
}
134+
135+
try {
136+
if (isYearMissing) {
137+
String year = Integer.toString(Calendar.getInstance().get(Calendar.YEAR));
138+
String modifiedDate = year + " " + originalDate;
139+
final ZonedDateTime dateTime = ZonedDateTime.parse(modifiedDate, formatter);
140+
this.date = Date.from(dateTime.toInstant());
141+
} else {
142+
final ZonedDateTime dateTime = ZonedDateTime.parse(originalDate, formatter);
143+
this.date = Date.from(dateTime.toInstant());
144+
}
145+
146+
this.message = this.message.substring(dateLength + 1);
147+
148+
} catch (DateTimeParseException pe) {
149+
this.date = new Date();
150+
}
151+
}
152+
}
153+
154+
public int getSequenceNumber() {
155+
return sequenceNumber;
156+
}
157+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package org.graylog2.syslog4j.server.impl.event;
2+
3+
import org.junit.Test;
4+
5+
import java.net.InetAddress;
6+
import java.net.InetSocketAddress;
7+
import java.time.ZoneId;
8+
import java.time.ZonedDateTime;
9+
import java.util.Date;
10+
11+
import static java.time.ZoneOffset.UTC;
12+
import static org.assertj.core.api.Assertions.assertThat;
13+
import static org.junit.Assert.assertEquals;
14+
15+
16+
public class CiscoSyslogServerEventTest {
17+
private static final InetAddress INET_ADDR = new InetSocketAddress(514).getAddress();
18+
private static final ZoneId CET = ZoneId.of("CET");
19+
private static final int YEAR = ZonedDateTime.now().getYear();
20+
21+
private CiscoSyslogServerEvent buildEvent(String message) {
22+
return new CiscoSyslogServerEvent(message, INET_ADDR);
23+
}
24+
25+
@Test
26+
public void testCisco1() throws Exception {
27+
final String message = "<166>Mar 06 2016 12:53:10 DEVICENAME : %ASA-6-302013: Built inbound TCP connection 723494125 for FRONTEND:IP/11288 (IP/11288) to BACKEND:IP/27180 (IP/27180)";
28+
29+
final CiscoSyslogServerEvent event = buildEvent(message);
30+
31+
assertThat(toZonedDateTime(event.getDate(), UTC)).isEqualTo(ZonedDateTime.of(2016, 3, 6, 12, 53, 10, 0, UTC));
32+
assertThat(event.getFacility()).isEqualTo(20);
33+
assertThat(event.getLevel()).isEqualTo(6);
34+
assertThat(event.getSequenceNumber()).isEqualTo(0);
35+
assertThat(event.getHost()).isEqualTo("DEVICENAME");
36+
assertThat(event.getMessage()).isEqualTo("%ASA-6-302013: Built inbound TCP connection 723494125 for FRONTEND:IP/11288 (IP/11288) to BACKEND:IP/27180 (IP/27180)");
37+
}
38+
39+
@Test
40+
public void testCisco2() throws Exception {
41+
final String message = "<186>1541800: Feb 27 06:08:59.485: %HARDWARE-2-FAN_ERROR: Fan Failure";
42+
43+
final CiscoSyslogServerEvent event = buildEvent(message);
44+
45+
assertThat(toZonedDateTime(event.getDate(), UTC)).isEqualTo(ZonedDateTime.of(YEAR, 2, 27, 6, 8, 59, 485_000_000, UTC));
46+
assertThat(event.getFacility()).isEqualTo(23);
47+
assertThat(event.getLevel()).isEqualTo(2);
48+
assertThat(event.getSequenceNumber()).isEqualTo(1541800);
49+
assertThat(event.getHost()).isEmpty();
50+
assertThat(event.getMessage()).isEqualTo("%HARDWARE-2-FAN_ERROR: Fan Failure");
51+
}
52+
53+
@Test
54+
public void testCisco3() throws Exception {
55+
final String message = "<187>148094: Feb 27 06:07:29.716: %LINK-3-UPDOWN: Interface GigabitEthernet1/0/15, changed state to down";
56+
57+
final CiscoSyslogServerEvent event = buildEvent(message);
58+
59+
assertThat(toZonedDateTime(event.getDate(), UTC)).isEqualTo(ZonedDateTime.of(YEAR, 2, 27, 6, 7, 29, 716_000_000, UTC));
60+
assertThat(event.getFacility()).isEqualTo(23);
61+
assertThat(event.getLevel()).isEqualTo(3);
62+
assertThat(event.getSequenceNumber()).isEqualTo(148094);
63+
assertThat(event.getHost()).isEmpty();
64+
assertEquals("%LINK-3-UPDOWN: Interface GigabitEthernet1/0/15, changed state to down", event.getMessage());
65+
}
66+
67+
@Test
68+
public void testCisco4() throws Exception {
69+
final String message = "<190>530470: *Sep 28 17:13:35.098: %SEC-6-IPACCESSLOGP: list MGMT_IN denied udp IP(49964) -> IP(161), 11 packets";
70+
71+
final CiscoSyslogServerEvent event = buildEvent(message);
72+
73+
assertThat(toZonedDateTime(event.getDate(), UTC)).isEqualTo(ZonedDateTime.of(YEAR, 9, 28, 17, 13, 35, 98_000_000, UTC));
74+
assertThat(event.getFacility()).isEqualTo(23);
75+
assertThat(event.getLevel()).isEqualTo(6);
76+
assertThat(event.getSequenceNumber()).isEqualTo(530470);
77+
assertThat(event.getHost()).isEmpty();
78+
assertEquals("%SEC-6-IPACCESSLOGP: list MGMT_IN denied udp IP(49964) -> IP(161), 11 packets", event.getMessage());
79+
}
80+
81+
@Test
82+
public void testCisco5() throws Exception {
83+
final String message = "<190>: 2016 Mar 06 09:22:34 CET: %AUTHPRIV-6-SYSTEM_MSG: START: rsync pid=4311 from=::ffff:IP - xinetd[6219]";
84+
85+
final CiscoSyslogServerEvent event = buildEvent(message);
86+
87+
assertThat(toZonedDateTime(event.getDate(), CET)).isEqualTo(ZonedDateTime.of(2016, 3, 6, 9, 22, 34, 0, CET));
88+
assertThat(event.getFacility()).isEqualTo(23);
89+
assertThat(event.getLevel()).isEqualTo(6);
90+
assertThat(event.getSequenceNumber()).isEqualTo(0);
91+
assertThat(event.getHost()).isEmpty();
92+
assertThat(event.getMessage()).isEqualTo("%AUTHPRIV-6-SYSTEM_MSG: START: rsync pid=4311 from=::ffff:IP - xinetd[6219]");
93+
}
94+
95+
@Test
96+
public void testCisco6() throws Exception {
97+
final String message = "<134>: 2016 Mar 6 12:53:10 UTC: %POLICY_ENGINE-6-POLICY_LOOKUP_EVENT: policy=POLICYNAME rule=RULENAME action=Permit direction=egress src.net.ip-address=IP src.net.port=38321 dst.net.ip-address=IP dst.net.port=5666 net.protocol=6 net.ethertype=800 net.service=\"protocol 6 port 5666\"";
98+
99+
final CiscoSyslogServerEvent event = buildEvent(message);
100+
101+
assertThat(toZonedDateTime(event.getDate(), UTC)).isEqualTo(ZonedDateTime.of(2016, 3, 6, 12, 53, 10, 0, UTC));
102+
assertThat(event.getFacility()).isEqualTo(16);
103+
assertThat(event.getLevel()).isEqualTo(6);
104+
assertThat(event.getSequenceNumber()).isEqualTo(0);
105+
assertThat(event.getHost()).isEmpty();
106+
assertThat(event.getMessage()).isEqualTo("%POLICY_ENGINE-6-POLICY_LOOKUP_EVENT: policy=POLICYNAME rule=RULENAME action=Permit direction=egress src.net.ip-address=IP src.net.port=38321 dst.net.ip-address=IP dst.net.port=5666 net.protocol=6 net.ethertype=800 net.service=\"protocol 6 port 5666\"");
107+
}
108+
109+
@Test
110+
public void testCisco7() throws Exception {
111+
final String message = "<166>%ASA-6-302015: Built inbound UDP connection 23631055 for inside:192.168.19.91/44764 (192.168.19.91/44764) to identity:192.168.249.33/161 (192.168.249.33/161)";
112+
113+
final CiscoSyslogServerEvent event = buildEvent(message);
114+
115+
assertThat(event.getDate())
116+
.isInThePast()
117+
.isInSameMinuteWindowAs(new Date());
118+
assertThat(event.getFacility()).isEqualTo(20);
119+
assertThat(event.getLevel()).isEqualTo(6);
120+
assertThat(event.getSequenceNumber()).isEqualTo(0);
121+
assertThat(event.getHost()).isEmpty();
122+
assertThat(event.getMessage()).isEqualTo("%ASA-6-302015: Built inbound UDP connection 23631055 for inside:192.168.19.91/44764 (192.168.19.91/44764) to identity:192.168.249.33/161 (192.168.249.33/161)");
123+
}
124+
125+
private ZonedDateTime toZonedDateTime(Date date, ZoneId zoneId) {
126+
return ZonedDateTime.ofInstant(date.toInstant(), zoneId);
127+
}
128+
}

0 commit comments

Comments
 (0)