"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/dynamic-preprocessors/appid/service_plugins/service_snmp.c" (16 Oct 2020, 17915 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "service_snmp.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.9.16.1_vs_2.9.17.
1 /*
2 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
3 ** Copyright (C) 2005-2013 Sourcefire, Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License Version 2 as
7 ** published by the Free Software Foundation. You may not use, modify or
8 ** distribute this program under any other version of the GNU General
9 ** Public License.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21
22 #include <ctype.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28
29 #include "appIdApi.h"
30 #include "appInfoTable.h"
31 #include "flow.h"
32 #include "service_api.h"
33
34 #define SNMP_PORT 161
35
36 #define SNMP_VERSION_1 0
37 #define SNMP_VERSION_2c 1
38 #define SNMP_VERSION_2u 2
39 #define SNMP_VERSION_3 3
40
41 #define SNMP_VENDOR_STR "SNMP"
42 #define SNMP_VERSION_STR_1 "v1"
43 #define SNMP_VERSION_STR_2c "v2c"
44 #define SNMP_VERSION_STR_2u "v2u"
45 #define SNMP_VERSION_STR_3 "v3"
46
47 typedef enum
48 {
49 SNMP_STATE_CONNECTION,
50 SNMP_STATE_RESPONSE,
51 SNMP_STATE_REQUEST,
52 SNMP_STATE_R_RESPONSE,
53 SNMP_STATE_R_REQUEST,
54 SNMP_STATE_ERROR
55 } SNMPState;
56
57 typedef struct _SERVICE_SNMP_DATA
58 {
59 SNMPState state;
60 } ServiceSNMPData;
61
62 typedef enum
63 {
64 SNMP_PDU_GET_REQUEST,
65 SNMP_PDU_GET_NEXT_REQUEST,
66 SNMP_PDU_GET_RESPONSE,
67 SNMP_PDU_SET_REQUEST,
68 SNMP_PDU_TRAP,
69 SNMP_PDU_GET_BULK_REQUEST,
70 SNMP_PDU_INFORM_REQUEST,
71 SNMP_PDU_TRAPV2
72 } SNMPPDUType;
73
74 #pragma pack(1)
75
76 typedef struct _SERVICE_SNMP_HEADER
77 {
78 uint16_t opcode;
79 union
80 {
81 uint16_t block;
82 uint16_t errorcode;
83 } d;
84 } ServiceSNMPHeader;
85
86 #pragma pack()
87
88 static int snmp_init(const InitServiceAPI * const init_api);
89 static int snmp_validate(ServiceValidationArgs* args);
90
91 static tRNAServiceElement svc_element =
92 {
93 .next = NULL,
94 .validate = &snmp_validate,
95 .detectorType = DETECTOR_TYPE_DECODER,
96 .name = "snmp",
97 .ref_count = 1,
98 .current_ref_count = 1,
99 };
100
101 static RNAServiceValidationPort pp[] =
102 {
103 {&snmp_validate, SNMP_PORT, IPPROTO_TCP},
104 {&snmp_validate, SNMP_PORT, IPPROTO_UDP},
105 {&snmp_validate, 162, IPPROTO_UDP},
106 {NULL, 0, 0}
107 };
108
109 tRNAServiceValidationModule snmp_service_mod =
110 {
111 "SNMP",
112 &snmp_init,
113 pp
114 };
115
116 static uint8_t SNMP_PATTERN_2[] = {0x02, 0x01, 0x00, 0x04};
117 static uint8_t SNMP_PATTERN_3[] = {0x02, 0x01, 0x01, 0x04};
118 static uint8_t SNMP_PATTERN_4[] = {0x02, 0x01, 0x03, 0x30};
119
120 static tAppRegistryEntry appIdRegistry[] =
121 {
122 {APP_ID_SNMP, APPINFO_FLAG_SERVICE_UDP_REVERSED|APPINFO_FLAG_SERVICE_ADDITIONAL}
123 };
124
125 static int16_t app_id = 0;
126
127 static int snmp_init(const InitServiceAPI * const init_api)
128 {
129 #ifdef TARGET_BASED
130 app_id = init_api->dpd->addProtocolReference("snmp");
131 #endif
132
133 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_2, sizeof(SNMP_PATTERN_2), 2, "snmp", init_api->pAppidConfig);
134 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_3, sizeof(SNMP_PATTERN_3), 2, "snmp", init_api->pAppidConfig);
135 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_4, sizeof(SNMP_PATTERN_4), 2, "snmp", init_api->pAppidConfig);
136 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_2, sizeof(SNMP_PATTERN_2), 3, "snmp", init_api->pAppidConfig);
137 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_3, sizeof(SNMP_PATTERN_3), 3, "snmp", init_api->pAppidConfig);
138 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_4, sizeof(SNMP_PATTERN_4), 3, "snmp", init_api->pAppidConfig);
139 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_2, sizeof(SNMP_PATTERN_2), 4, "snmp", init_api->pAppidConfig);
140 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_3, sizeof(SNMP_PATTERN_3), 4, "snmp", init_api->pAppidConfig);
141 init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_4, sizeof(SNMP_PATTERN_4), 4, "snmp", init_api->pAppidConfig);
142 unsigned i;
143 for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
144 {
145 _dpd.debugMsg(DEBUG_LOG,"registering appId: %d\n",appIdRegistry[i].appId);
146 init_api->RegisterAppId(&snmp_validate, appIdRegistry[i].appId, appIdRegistry[i].additionalInfo, init_api->pAppidConfig);
147 }
148
149 return 0;
150 }
151
152 static int snmp_ans1_length(const uint8_t * * const data,
153 const uint8_t * const end,
154 uint32_t * const length)
155 {
156 *length = 0;
157 if (**data == 0x80) return -1;
158 if (**data < 0x80)
159 {
160 *length = (uint32_t)**data;
161 (*data)++;
162 }
163 else
164 {
165 int cnt = (**data) & 0x7F;
166 (*data)++;
167 for (; *data<end && cnt; cnt--, (*data)++)
168 {
169 *length <<= 8;
170 *length |= **data;
171 }
172 if (cnt) return -1;
173 }
174 return 0;
175 }
176
177 static int snmp_verify_packet(const uint8_t * * const data,
178 const uint8_t * const end, uint8_t * const pdu,
179 uint8_t * version_ret)
180 {
181 uint32_t overall_length;
182 uint32_t community_length;
183 uint32_t global_length;
184 uint32_t length;
185 uint8_t version;
186 uint8_t cls;
187 const uint8_t *p;
188
189 if (**data != 0x30) return -1;
190 (*data)++;
191 if (*data >= end) return -1;
192 if (snmp_ans1_length(data, end, &overall_length)) return -1;
193 if (overall_length < 3 || (int)overall_length > end-(*data)) return -1;
194 if (**data != 0x02) return -1;
195 (*data)++;
196 if (**data != 0x01) return -1;
197 (*data)++;
198 version = **data;
199 (*data)++;
200 overall_length -= 3;
201 if (!overall_length) return -1;
202 switch (version)
203 {
204 case SNMP_VERSION_1:
205 case SNMP_VERSION_2c:
206 if (**data != 0x04) return -1;
207 (*data)++;
208 overall_length--;
209 if (!overall_length) return -1;
210 p = *data;
211 if (snmp_ans1_length(data, *data+overall_length, &community_length))
212 return -1;
213 overall_length -= *data - p;
214 if (overall_length < community_length)
215 return -1;
216 for (;
217 community_length;
218 (*data)++, community_length--, overall_length--)
219 {
220 if (!isprint(**data)) return -1;
221 }
222 break;
223 case SNMP_VERSION_2u:
224 if (**data != 0x04) return -1;
225 (*data)++;
226 overall_length--;
227 if (!overall_length) return -1;
228 p = *data;
229 if (snmp_ans1_length(data, *data+overall_length, &community_length))
230 return -1;
231 overall_length -= *data - p;
232 if (!community_length || overall_length < community_length)
233 return -1;
234 if (**data != 1) return -1;
235 *data += community_length;
236 overall_length -= community_length;
237 break;
238 case SNMP_VERSION_3:
239 /* Global header */
240 if (**data != 0x30) return -1;
241 (*data)++;
242 overall_length--;
243 if (!overall_length) return -1;
244 p = *data;
245 if (snmp_ans1_length(data, *data+overall_length, &global_length))
246 return -1;
247 overall_length -= *data - p;
248 if (global_length < 2 || overall_length < global_length) return -1;
249
250 /* Message id */
251 if (**data != 0x02) return -1;
252 (*data)++;
253 global_length--;
254 overall_length --;
255 p = *data;
256 if (snmp_ans1_length(data, *data+global_length, &length)) return -1;
257 global_length -= *data - p;
258 overall_length -= *data - p;
259 if (global_length < length || length > sizeof(uint32_t)) return -1;
260 *data += length;
261 global_length -= length;
262 overall_length -= length;
263
264 /* Max message size */
265 if (global_length < 2) return -1;
266 if (**data != 0x02) return -1;
267 (*data)++;
268 global_length--;
269 overall_length --;
270 p = *data;
271 if (snmp_ans1_length(data, *data+global_length, &length)) return -1;
272 global_length -= *data - p;
273 overall_length -= *data - p;
274 if (global_length < length || length > sizeof(uint32_t)) return -1;
275 *data += length;
276 global_length -= length;
277 overall_length -= length;
278
279 /* Message flags */
280 if (global_length < 2) return -1;
281 if (**data != 0x04) return -1;
282 (*data)++;
283 global_length--;
284 overall_length --;
285 p = *data;
286 if (snmp_ans1_length(data, *data+global_length, &length))
287 return -1;
288 global_length -= *data - p;
289 overall_length -= *data - p;
290 if (length != 1 || global_length < length) return -1;
291 (*data)++;
292 global_length--;
293 overall_length--;
294
295 /* Security model */
296 if (global_length < 2) return -1;
297 if (**data != 0x02) return -1;
298 (*data)++;
299 global_length--;
300 overall_length --;
301 p = *data;
302 if (snmp_ans1_length(data, *data+global_length, &length))
303 return -1;
304 global_length -= *data - p;
305 overall_length -= *data - p;
306 if (global_length < length || length > sizeof(uint32_t)) return -1;
307 *data += length;
308 global_length -= length;
309 overall_length -= length;
310
311 /* Security Parameters */
312 if (overall_length < 2) return -1;
313 if (**data != 0x04) return -1;
314 (*data)++;
315 overall_length --;
316 p = *data;
317 if (snmp_ans1_length(data, *data+overall_length, &global_length))
318 return -1;
319 overall_length -= *data - p;
320 if (overall_length < global_length) return -1;
321 *data += global_length;
322 overall_length -= global_length;
323
324 /* Message */
325 if (overall_length < 2) return -1;
326 if (**data != 0x30) return -1;
327 (*data)++;
328 overall_length --;
329 p = *data;
330 if (snmp_ans1_length(data, *data+overall_length, &global_length))
331 return -1;
332 overall_length -= *data - p;
333 if (overall_length < global_length) return -1;
334
335 /* Context Engine ID */
336 if (global_length < 2) return -1;
337 if (**data != 0x04) return -1;
338 (*data)++;
339 global_length--;
340 overall_length --;
341 p = *data;
342 if (snmp_ans1_length(data, *data+global_length, &length))
343 return -1;
344 global_length -= *data - p;
345 overall_length -= *data - p;
346 if (global_length < length) return -1;
347 *data += length;
348 global_length -= length;
349 overall_length -= length;
350
351 /* Context Name */
352 if (global_length < 2) return -1;
353 if (**data != 0x04) return -1;
354 (*data)++;
355 global_length--;
356 overall_length --;
357 p = *data;
358 if (snmp_ans1_length(data, *data+global_length, &length))
359 return -1;
360 global_length -= *data - p;
361 overall_length -= *data - p;
362 if (global_length < length) return -1;
363 *data += length;
364 global_length -= length;
365 overall_length -= length;
366 break;
367 default:
368 return -1;
369 }
370 if (!overall_length) return -1;
371 cls = (**data) & 0xC0;
372 if (cls != 0x80 && cls != 0x40) return -1;
373 *pdu = (**data) & 0x1F;
374 *version_ret = version;
375 return 0;
376 }
377
378 static int snmp_validate(ServiceValidationArgs* args)
379 {
380 ServiceSNMPData *sd;
381 ServiceSNMPData *tmp_sd;
382 tAppIdData *pf;
383 uint8_t pdu;
384 sfaddr_t *sip;
385 sfaddr_t *dip;
386 uint8_t version;
387 const char *version_str = NULL;
388 tAppIdData *flowp = args->flowp;
389 const uint8_t *data = args->data;
390 SFSnortPacket *pkt = args->pkt;
391 const int dir = args->dir;
392 uint16_t size = args->size;
393 bool app_id_debug_session_flag = args->app_id_debug_session_flag;
394 char* app_id_debug_session = args->app_id_debug_session;
395
396 if (!size)
397 goto inprocess;
398
399 sd = snmp_service_mod.api->data_get(flowp, snmp_service_mod.flow_data_index);
400 if (!sd)
401 {
402 sd = calloc(1, sizeof(*sd));
403 if (!sd)
404 return SERVICE_ENOMEM;
405 if (snmp_service_mod.api->data_add(flowp, sd, snmp_service_mod.flow_data_index, &free))
406 {
407 free(sd);
408 return SERVICE_ENOMEM;
409 }
410 sd->state = SNMP_STATE_CONNECTION;
411 }
412
413 if (snmp_verify_packet(&data, data+size, &pdu, &version))
414 {
415 if (app_id_debug_session_flag)
416 _dpd.logMsg("AppIdDbg %s snmp payload verify failed\n", app_id_debug_session);
417 if (getAppIdFlag(flowp, APPID_SESSION_UDP_REVERSED))
418 {
419 if (dir == APP_ID_FROM_RESPONDER) goto bail;
420 else goto fail;
421 }
422 else
423 {
424 if (dir == APP_ID_FROM_RESPONDER) goto fail;
425 else goto bail;
426 }
427 }
428
429 if (app_id_debug_session_flag)
430 _dpd.logMsg("AppIdDbg %s snmp state %d\n", app_id_debug_session, sd->state);
431
432 switch (sd->state)
433 {
434 case SNMP_STATE_CONNECTION:
435 if (pdu != SNMP_PDU_GET_RESPONSE && dir == APP_ID_FROM_RESPONDER)
436 {
437 sd->state = SNMP_STATE_R_RESPONSE;
438 setAppIdFlag(flowp, APPID_SESSION_UDP_REVERSED);
439 break;
440 }
441 if (pdu == SNMP_PDU_GET_RESPONSE && dir == APP_ID_FROM_INITIATOR)
442 {
443 sd->state = SNMP_STATE_R_REQUEST;
444 setAppIdFlag(flowp, APPID_SESSION_UDP_REVERSED);
445 break;
446 }
447
448 if (dir == APP_ID_FROM_RESPONDER)
449 {
450 sd->state = SNMP_STATE_REQUEST;
451 break;
452 }
453
454 if (pdu == SNMP_PDU_TRAP || pdu == SNMP_PDU_TRAPV2)
455 {
456 setAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_NOT_A_SERVICE);
457 clearAppIdFlag(flowp, APPID_SESSION_CONTINUE);
458 flowp->serviceAppId = APP_ID_SNMP;
459 break;
460 }
461 sd->state = SNMP_STATE_RESPONSE;
462
463 /*adding expected connection in case the server doesn't send from 161*/
464 dip = GET_DST_IP(pkt);
465 sip = GET_SRC_IP(pkt);
466 pf = snmp_service_mod.api->flow_new(flowp, pkt, dip, 0, sip, pkt->src_port, flowp->proto, app_id, 0);
467 if (pf)
468 {
469 tmp_sd = calloc(1, sizeof(ServiceSNMPData));
470 if (tmp_sd == NULL) return SERVICE_ENOMEM;
471 tmp_sd->state = SNMP_STATE_RESPONSE;
472
473 if (snmp_service_mod.api->data_add(pf, tmp_sd, snmp_service_mod.flow_data_index, &free))
474 {
475 free(tmp_sd);
476 return SERVICE_ENOMEM;
477 }
478 if (snmp_service_mod.api->data_add_id(pf, pkt->dst_port, &svc_element))
479 {
480 setAppIdFlag(pf, APPID_SESSION_SERVICE_DETECTED);
481 clearAppIdFlag(pf, APPID_SESSION_CONTINUE);
482 tmp_sd->state = SNMP_STATE_ERROR;
483 return SERVICE_ENULL;
484 }
485 PopulateExpectedFlow(flowp, pf, APPID_SESSION_EXPECTED_EVALUATE, APP_ID_APPID_SESSION_DIRECTION_MAX);
486 pf->rnaServiceState = RNA_STATE_STATEFUL;
487 pf->scan_flags |= SCAN_HOST_PORT_FLAG;
488 sfaddr_copy_to_raw(&pf->common.initiator_ip, sip);
489 }
490 break;
491 case SNMP_STATE_RESPONSE:
492 if (pdu == SNMP_PDU_GET_RESPONSE)
493 {
494 if (dir == APP_ID_FROM_RESPONDER) goto success;
495 goto fail;
496 }
497 if (dir == APP_ID_FROM_RESPONDER) goto fail;
498 break;
499 case SNMP_STATE_REQUEST:
500 if (pdu != SNMP_PDU_GET_RESPONSE)
501 {
502 if (dir == APP_ID_FROM_INITIATOR) goto success;
503 goto fail;
504 }
505 if (dir == APP_ID_FROM_INITIATOR) goto fail;
506 break;
507 case SNMP_STATE_R_RESPONSE:
508 if (pdu == SNMP_PDU_GET_RESPONSE)
509 {
510 if (dir == APP_ID_FROM_INITIATOR) goto success;
511 goto fail;
512 }
513 if (dir == APP_ID_FROM_INITIATOR) goto fail;
514 break;
515 case SNMP_STATE_R_REQUEST:
516 if (pdu != SNMP_PDU_GET_RESPONSE)
517 {
518 if (dir == APP_ID_FROM_RESPONDER) goto success;
519 goto fail;
520 }
521 if (dir == APP_ID_FROM_RESPONDER) goto fail;
522 break;
523 default:
524 if (dir == APP_ID_FROM_RESPONDER) goto fail;
525 else goto bail;
526 }
527
528 inprocess:
529 snmp_service_mod.api->service_inprocess(flowp, pkt, dir, &svc_element, NULL);
530 return SERVICE_INPROCESS;
531
532 success:
533 switch (version)
534 {
535 case SNMP_VERSION_1:
536 version_str = SNMP_VERSION_STR_1;
537 break;
538 case SNMP_VERSION_2c:
539 version_str = SNMP_VERSION_STR_2c;
540 break;
541 case SNMP_VERSION_2u:
542 version_str = SNMP_VERSION_STR_2u;
543 break;
544 case SNMP_VERSION_3:
545 version_str = SNMP_VERSION_STR_3;
546 break;
547 default:
548 version_str = NULL;
549 break;
550 }
551 snmp_service_mod.api->add_service(flowp, pkt, dir, &svc_element,
552 APP_ID_SNMP,
553 SNMP_VENDOR_STR, version_str, NULL, NULL);
554 return SERVICE_SUCCESS;
555
556 bail:
557 snmp_service_mod.api->incompatible_data(flowp, pkt, dir, &svc_element,
558 snmp_service_mod.flow_data_index,
559 args->pConfig, NULL);
560 return SERVICE_NOT_COMPATIBLE;
561
562 fail:
563 snmp_service_mod.api->fail_service(flowp, pkt, dir, &svc_element,
564 snmp_service_mod.flow_data_index,
565 args->pConfig, NULL);
566 return SERVICE_NOMATCH;
567 }
568