/src/suricata7/src/app-layer-rfb.c
Line | Count | Source |
1 | | /* Copyright (C) 2020 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | /** |
19 | | * \file |
20 | | * |
21 | | * \author Sascha Steinbiss <sascha.steinbiss@dcso.de> |
22 | | * |
23 | | * RFB (VNC) application layer detector and parser. |
24 | | * |
25 | | */ |
26 | | |
27 | | #include "suricata-common.h" |
28 | | |
29 | | #include "util-unittest.h" |
30 | | |
31 | | #include "app-layer-detect-proto.h" |
32 | | #include "app-layer-parser.h" |
33 | | #include "app-layer-rfb.h" |
34 | | |
35 | | #include "rust.h" |
36 | | |
37 | | static int RFBRegisterPatternsForProtocolDetection(void) |
38 | 34 | { |
39 | 34 | if (AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_RFB, |
40 | 34 | "RFB ", 4, 0, STREAM_TOCLIENT) < 0) |
41 | 0 | { |
42 | 0 | return -1; |
43 | 0 | } |
44 | 34 | if (AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_RFB, |
45 | 34 | "RFB ", 4, 0, STREAM_TOSERVER) < 0) |
46 | 0 | { |
47 | 0 | return -1; |
48 | 0 | } |
49 | 34 | return 0; |
50 | 34 | } |
51 | | |
52 | | void RFBParserRegisterTests(void); |
53 | | |
54 | | void RegisterRFBParsers(void) |
55 | 34 | { |
56 | 34 | rs_rfb_register_parser(); |
57 | 34 | if (RFBRegisterPatternsForProtocolDetection() < 0 ) |
58 | 0 | return; |
59 | | #ifdef UNITTESTS |
60 | | AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_RFB, |
61 | | RFBParserRegisterTests); |
62 | | #endif |
63 | 34 | } |
64 | | |
65 | | |
66 | | #ifdef UNITTESTS |
67 | | |
68 | | #include "stream-tcp.h" |
69 | | #include "util-unittest-helper.h" |
70 | | |
71 | | static int RFBParserTest(void) |
72 | | { |
73 | | uint64_t ret[4]; |
74 | | AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); |
75 | | FAIL_IF_NULL(alp_tctx); |
76 | | |
77 | | StreamTcpInitConfig(true); |
78 | | TcpSession ssn; |
79 | | memset(&ssn, 0, sizeof(ssn)); |
80 | | |
81 | | Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 59001, 5900); |
82 | | FAIL_IF_NULL(f); |
83 | | f->protoctx = &ssn; |
84 | | f->proto = IPPROTO_TCP; |
85 | | f->alproto = ALPROTO_RFB; |
86 | | f->flags |= FLOW_SGH_TOCLIENT | FLOW_SGH_TOSERVER; |
87 | | |
88 | | static const unsigned char rfb_version_str[12] = { |
89 | | 0x52, 0x46, 0x42, 0x20, 0x30, 0x30, 0x33, 0x2e, 0x30, 0x30, 0x37, 0x0a |
90 | | }; |
91 | | |
92 | | // the RFB server sending the first handshake message |
93 | | int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_RFB, STREAM_TOCLIENT | STREAM_START, |
94 | | (uint8_t *)rfb_version_str, sizeof(rfb_version_str)); |
95 | | FAIL_IF_NOT(r == 0); |
96 | | |
97 | | r = AppLayerParserParse( |
98 | | NULL, alp_tctx, f, ALPROTO_RFB, STREAM_TOSERVER, (uint8_t *)rfb_version_str, sizeof(rfb_version_str)); |
99 | | FAIL_IF_NOT(r == 0); |
100 | | |
101 | | static const unsigned char security_types[3] = { |
102 | | 0x02, 0x01, 0x02 |
103 | | }; |
104 | | r = AppLayerParserParse( |
105 | | NULL, alp_tctx, f, ALPROTO_RFB, STREAM_TOCLIENT, (uint8_t *)security_types, sizeof(security_types)); |
106 | | FAIL_IF_NOT(r == 0); |
107 | | |
108 | | static const unsigned char type_selection[1] = { |
109 | | 0x01 |
110 | | }; |
111 | | r = AppLayerParserParse( |
112 | | NULL, alp_tctx, f, ALPROTO_RFB, STREAM_TOSERVER, (uint8_t *)type_selection, sizeof(type_selection)); |
113 | | FAIL_IF_NOT(r == 0); |
114 | | |
115 | | static const unsigned char client_init[1] = { |
116 | | 0x01 |
117 | | }; |
118 | | r = AppLayerParserParse( |
119 | | NULL, alp_tctx, f, ALPROTO_RFB, STREAM_TOSERVER, (uint8_t *)client_init, sizeof(client_init)); |
120 | | FAIL_IF_NOT(r == 0); |
121 | | |
122 | | static const unsigned char server_init[] = { |
123 | | 0x05, 0x00, 0x03, 0x20, 0x20, 0x18, 0x00, 0x01, |
124 | | 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x10, 0x08, |
125 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, |
126 | | 0x61, 0x6e, 0x65, 0x61, 0x67, 0x6c, 0x65, 0x73, |
127 | | 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, |
128 | | 0x73, 0x74, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, |
129 | | 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e |
130 | | }; |
131 | | |
132 | | r = AppLayerParserParse( |
133 | | NULL, alp_tctx, f, ALPROTO_RFB, STREAM_TOCLIENT, (uint8_t *)server_init, sizeof(server_init)); |
134 | | FAIL_IF_NOT(r == 0); |
135 | | |
136 | | AppLayerParserTransactionsCleanup(f, STREAM_TOCLIENT); |
137 | | UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]); |
138 | | FAIL_IF_NOT(ret[0] == 1); // inspect_id[0] |
139 | | FAIL_IF_NOT(ret[1] == 1); // inspect_id[1] |
140 | | FAIL_IF_NOT(ret[2] == 1); // log_id |
141 | | FAIL_IF_NOT(ret[3] == 1); // min_id |
142 | | |
143 | | AppLayerParserTransactionsCleanup(f, STREAM_TOCLIENT); |
144 | | AppLayerParserThreadCtxFree(alp_tctx); |
145 | | StreamTcpFreeConfig(true); |
146 | | UTHFreeFlow(f); |
147 | | |
148 | | PASS; |
149 | | } |
150 | | |
151 | | void RFBParserRegisterTests(void) |
152 | | { |
153 | | UtRegisterTest("RFBParserTest", RFBParserTest); |
154 | | } |
155 | | |
156 | | #endif |