1 /*
2 ** SNMPv1/2C Community String Checking Medusa Module
3 **
4 ** ------------------------------------------------------------------------
5 ** Copyright (C) 2009 Joe Mondloch
6 ** JoMo-Kun / jmk@foofus.net
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License version 2,
10 ** as published by the Free Software Foundation
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** http://www.gnu.org/licenses/gpl.txt
18 **
19 ** This program is released under the GPL with the additional exemption
20 ** that compiling, linking, and/or using OpenSSL is allowed.
21 **
22 ** ------------------------------------------------------------------------
23 **
24 ** Based on ideas from:
25 ** Hydra 5.2 [van Hauser <vh@thc.org>]
26 ** onesixtyone [solareclipse@phreedom.org]
27 **
28 */
29
30 #include <sys/types.h>
31 #include <libgen.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include "module.h"
36
37 #define MODULE_NAME "snmp.mod"
38 #define MODULE_AUTHOR "JoMo-Kun <jmk@foofus.net>"
39 #define MODULE_SUMMARY_USAGE "Brute force module for SNMP Community Strings"
40 #define MODULE_VERSION "2.1"
41 #define MODULE_VERSION_SVN "$Id: snmp.c 9217 2015-05-07 18:07:03Z jmk $"
42 #define MODULE_SUMMARY_FORMAT "%s : version %s"
43 #define MODULE_SUMMARY_FORMAT_WARN "%s : version %s (%s)"
44
45 #define PORT_SNMP 161
46
47 #define SNMP_VER_V1 1
48 #define SNMP_VER_V2C 2
49 #define SNMP_READ 1
50 #define SNMP_WRITE 2
51 #define SNMP_SUCCESS_READ 1
52 #define SNMP_SUCCESS_WRITE 2
53
54 #define SEND_DELAY 200 /* Delay between sending SNMP requests (usec) */
55 #define RECEIVE_DELAY 5*1000000 /* Response wait time (usec) */
56
57 typedef struct __SNMP_DATA {
58 int nVersion;
59 int nReadWrite;
60 int nReadTimeout;
61 int nSendDelay;
62 } _SNMP_DATA;
63
64 // Tells us whether we are to continue processing or not
65 enum MODULE_STATE
66 {
67 MSTATE_NEW,
68 MSTATE_RUNNING,
69 MSTATE_EXITING,
70 MSTATE_COMPLETE,
71 MSTATE_FAILURE
72 };
73
74 // Forward declarations
75 int sendRead(int hSocket, _SNMP_DATA* _psSessionData, char* szPassword);
76 int sendWrite(int hSocket, _SNMP_DATA* _psSessionData, char* szPassword, char* szLocation);
77 int receiveRequest(int hSocket, _SNMP_DATA* _psSessionData, int* nPassCount, char*** arrszPassList, char** szLocation);
78 int initModule(sLogin* login, _SNMP_DATA *_psSessionData);
79
80 // Tell medusa how many parameters this module allows
getParamNumber()81 int getParamNumber()
82 {
83 return 0; // we don't need no stinking parameters
84 }
85
86 // Displays information about the module and how it must be used
summaryUsage(char ** ppszSummary)87 void summaryUsage(char **ppszSummary)
88 {
89 // Memory for ppszSummary will be allocated here - caller is responsible for freeing it
90 int iLength = 0;
91
92 if (*ppszSummary == NULL)
93 {
94 iLength = strlen(MODULE_SUMMARY_USAGE) + strlen(MODULE_VERSION) + strlen(MODULE_SUMMARY_FORMAT) + 1;
95 *ppszSummary = (char*)malloc(iLength);
96 memset(*ppszSummary, 0, iLength);
97 snprintf(*ppszSummary, iLength, MODULE_SUMMARY_FORMAT, MODULE_SUMMARY_USAGE, MODULE_VERSION);
98 }
99 else
100 {
101 writeError(ERR_ERROR, "%s reports an error in summaryUsage() : ppszSummary must be NULL when called", MODULE_NAME);
102 }
103 }
104
105 /* Display module usage information */
showUsage()106 void showUsage()
107 {
108 writeVerbose(VB_NONE, "%s (%s) %s :: %s\n", MODULE_NAME, MODULE_VERSION, MODULE_AUTHOR, MODULE_SUMMARY_USAGE);
109 writeVerbose(VB_NONE, "Available module options:");
110 writeVerbose(VB_NONE, " TIMEOUT:? ");
111 writeVerbose(VB_NONE, " Sets the number of seconds to wait for the UDP responses (default: 5 sec).");
112 writeVerbose(VB_NONE, " SEND_DELAY:? ");
113 writeVerbose(VB_NONE, " Sets the number of microseconds to wait between sending queries (default: 200 usec).");
114 writeVerbose(VB_NONE, " VERSION:? (1*, 2C)");
115 writeVerbose(VB_NONE, " Set the SNMP client version.");
116 writeVerbose(VB_NONE, " ACCESS:? (READ*, WRITE)");
117 writeVerbose(VB_NONE, " Set level of access to test for with the community string.");
118 writeVerbose(VB_NONE, "");
119 writeVerbose(VB_NONE, "(*) Default value");
120 writeVerbose(VB_NONE, "");
121 writeVerbose(VB_NONE, "It should be noted that when testing for WRITE capability, the module will read");
122 writeVerbose(VB_NONE, "the current value of sysLocation and then write that same value back to the system.");
123 writeVerbose(VB_NONE, "");
124 writeVerbose(VB_NONE, "Since SNMP is a UDP-based protocol, there is no handshaking between sending and ");
125 writeVerbose(VB_NONE, "receiving transport-layer entities. Due to this connectionless communication, about");
126 writeVerbose(VB_NONE, "the only time we know a SNMP service exists, is if we send the correct community");
127 writeVerbose(VB_NONE, "string and the server sends a response. All other queries result in no response");
128 writeVerbose(VB_NONE, "whatsoever. The approach we use here is to initially just send all of our SNMP GET");
129 writeVerbose(VB_NONE, "requests. After that completes, we wait TIMEOUT seconds for any responses. If we");
130 writeVerbose(VB_NONE, "get any responses back, we examine them to see which community strings were successful.");
131 writeVerbose(VB_NONE, "If ACCESS:WRITE was specified, we check for write access on each of the previously");
132 writeVerbose(VB_NONE, "successful values. This techique should allow for quick brute forcing. However, one");
133 writeVerbose(VB_NONE, "should take care with the TIMEOUT and SEND_DELAY values as to avoid causing issues");
134 writeVerbose(VB_NONE, "with the target service or missing response data.");
135 writeVerbose(VB_NONE, "");
136 writeVerbose(VB_NONE, " Usage example: \"-M snmp -m TIMEOUT:2 -m ACCESS:WRITE\"");
137 writeVerbose(VB_NONE, "");
138 }
139
140 // The "main" of the medusa module world - this is what gets called to actually do the work
go(sLogin * logins,int argc,char * argv[])141 int go(sLogin* logins, int argc, char *argv[])
142 {
143 int i;
144 char *strtok_ptr, *pOpt, *pOptTmp;
145 _SNMP_DATA *psSessionData;
146
147 psSessionData = malloc(sizeof(_SNMP_DATA));
148 memset(psSessionData, 0, sizeof(_SNMP_DATA));
149
150 psSessionData->nVersion = SNMP_VER_V1;
151 psSessionData->nReadWrite = SNMP_READ;
152 psSessionData->nReadTimeout = RECEIVE_DELAY;
153 psSessionData->nSendDelay = SEND_DELAY;
154
155 if ((argc < 0) || (argc > 4))
156 {
157 writeError(ERR_ERROR, "%s: Incorrect number of parameters passed to module (%d). Use \"-q\" option to display module usage.", MODULE_NAME, argc);
158 return FAILURE;
159 }
160 else
161 {
162 writeError(ERR_DEBUG_MODULE, "OMG teh %s module has been called!!", MODULE_NAME);
163
164 for (i=0; i<argc; i++) {
165 pOptTmp = malloc( strlen(argv[i]) + 1);
166 memset(pOptTmp, 0, strlen(argv[i]) + 1);
167 strncpy(pOptTmp, argv[i], strlen(argv[i]));
168 writeError(ERR_DEBUG_MODULE, "Processing complete option (%d/%d): %s", i+1, argc, pOptTmp);
169 pOpt = strtok_r(pOptTmp, ":", &strtok_ptr);
170 writeError(ERR_DEBUG_MODULE, "Processing option: %s", pOpt);
171
172 if (strcmp(pOpt, "TIMEOUT") == 0)
173 {
174 pOpt = strtok_r(NULL, "\0", &strtok_ptr);
175 writeError(ERR_DEBUG_MODULE, "Processing option parameter: %s", pOpt);
176
177 if ( pOpt )
178 psSessionData->nReadTimeout = atoi(pOpt) * 1000000;
179 else
180 writeError(ERR_WARNING, "Method TIMEOUT requires value to be set.");
181 }
182 else if (strcmp(pOpt, "SEND_DELAY") == 0)
183 {
184 pOpt = strtok_r(NULL, "\0", &strtok_ptr);
185 writeError(ERR_DEBUG_MODULE, "Processing option parameter: %s", pOpt);
186
187 if ( pOpt )
188 psSessionData->nSendDelay = atoi(pOpt);
189 else
190 writeError(ERR_WARNING, "Method TIMEOUT requires value to be set.");
191 }
192 else if (strcmp(pOpt, "VERSION") == 0)
193 {
194 pOpt = strtok_r(NULL, "\0", &strtok_ptr);
195 writeError(ERR_DEBUG_MODULE, "Processing option parameter: %s", pOpt);
196
197 if (pOpt == NULL)
198 writeError(ERR_WARNING, "Method VERSION requires value to be set.");
199 else if ( strcmp(pOpt, "1") == 0 )
200 psSessionData->nVersion = SNMP_VER_V1;
201 else if ( strcmp(pOpt, "2C") == 0 )
202 psSessionData->nVersion = SNMP_VER_V2C;
203 else
204 writeError(ERR_WARNING, "Method VERSION requires a value of either \"1\" or \"2C\" to be set.");
205 }
206 else if (strcmp(pOpt, "ACCESS") == 0)
207 {
208 pOpt = strtok_r(NULL, "\0", &strtok_ptr);
209 writeError(ERR_DEBUG_MODULE, "Processing option parameter: %s", pOpt);
210
211 if (pOpt == NULL)
212 writeError(ERR_WARNING, "Method ACCESS requires value to be set.");
213 else if ( strcmp(pOpt, "READ") == 0 )
214 psSessionData->nReadWrite = SNMP_READ;
215 else if ( strcmp(pOpt, "WRITE") == 0 )
216 psSessionData->nReadWrite = SNMP_WRITE;
217 else
218 writeError(ERR_WARNING, "Method ACCESS requires value of \"READ\" or \"WRITE\" to be set.");
219 }
220 else
221 writeError(ERR_WARNING, "Invalid method: %s.", pOpt);
222
223 free(pOptTmp);
224 }
225
226 initModule(logins, psSessionData);
227 }
228
229 FREE(psSessionData);
230 return SUCCESS;
231 }
232
initModule(sLogin * psLogin,_SNMP_DATA * _psSessionData)233 int initModule(sLogin* psLogin, _SNMP_DATA *_psSessionData)
234 {
235 int hSocket = -1;
236 enum MODULE_STATE nState = MSTATE_NEW;
237 int i = 0, nPassCount, nPassCountWrite;
238 char **arrszPassList = NULL;
239 char **arrszPassListWrite = NULL;
240 char *szLocation = NULL;
241 sCredentialSet *psCredSet = NULL;
242 sUser *psUser = NULL;
243 sConnectParams params;
244
245 psCredSet = malloc( sizeof(sCredentialSet) );
246 memset(psCredSet, 0, sizeof(sCredentialSet));
247
248 if (getNextCredSet(psLogin, psCredSet) == FAILURE)
249 {
250 writeError(ERR_ERROR, "[%s] Error retrieving next credential set to test.", MODULE_NAME);
251 nState = MSTATE_COMPLETE;
252 }
253 else if (psCredSet->psUser)
254 {
255 writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s user: %s", MODULE_NAME, psLogin->psServer->pHostIP, psCredSet->psUser->pUser);
256 }
257 else
258 {
259 writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s - no more available users to test.", MODULE_NAME);
260 nState = MSTATE_COMPLETE;
261 }
262
263 memset(¶ms, 0, sizeof(sConnectParams));
264 params.nPort = PORT_SNMP;
265 initConnectionParams(psLogin, ¶ms);
266
267 writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s", MODULE_NAME, psLogin->psServer->pHostIP);
268
269 while (nState != MSTATE_COMPLETE)
270 {
271 switch (nState)
272 {
273 case MSTATE_NEW:
274 if (hSocket > 0)
275 medusaDisconnect(hSocket);
276
277 hSocket = medusaConnectUDP(¶ms);
278 if (hSocket < 0)
279 {
280 writeError(ERR_NOTICE, "%s: failed to connect, port %d was not open on %s", MODULE_NAME, params.nPort, psLogin->psServer->pHostIP);
281 psLogin->iResult = LOGIN_RESULT_UNKNOWN;
282 return FAILURE;
283 }
284
285 writeError(ERR_DEBUG_MODULE, "Connected");
286 nState = MSTATE_RUNNING;
287 break;
288 case MSTATE_RUNNING:
289 nState = sendRead(hSocket, _psSessionData, psCredSet->pPass);
290 if (nState == MSTATE_FAILURE)
291 {
292 psLogin->iResult = LOGIN_RESULT_UNKNOWN;
293 return FAILURE;
294 }
295
296 /* don't want to overwhelm the device being tested */
297 writeError(ERR_DEBUG_MODULE, "Delaying %d microseconds before sending next query.", _psSessionData->nSendDelay);
298 usleep(_psSessionData->nSendDelay);
299
300 /* initially set all passwords as invalid -- we don't know their validity yet */
301 psLogin->iResult = LOGIN_RESULT_FAIL;
302 setPassResult(psLogin, psCredSet->pPass);
303
304 if (psLogin->iResult != LOGIN_RESULT_UNKNOWN)
305 {
306 if (getNextCredSet(psLogin, psCredSet) == FAILURE)
307 {
308 writeError(ERR_ERROR, "[%s] Error retrieving next credential set to test.", MODULE_NAME);
309 nState = MSTATE_EXITING;
310 }
311 else
312 {
313 if (psCredSet->iStatus == CREDENTIAL_DONE)
314 {
315 writeError(ERR_DEBUG_MODULE, "[%s] No more available credential sets to test.", MODULE_NAME);
316
317 /* Medusa has exhausted all credential sets and reset psLogin->psUser to NULL. This
318 creates issues as we haven't actually received the responses yet from our SNMP
319 queries. Our solution is to create a temporary sUser structure, which allows us
320 to report on successful community strings via normal methods. */
321 psUser = malloc(sizeof(sUser));
322 memset(psUser, 0, sizeof(sUser));
323 psLogin->psUser = psUser;
324
325 nState = MSTATE_EXITING;
326 }
327 else if (psCredSet->iStatus == CREDENTIAL_NEW_USER)
328 {
329 writeError(ERR_DEBUG_MODULE, "[%s] Starting testing for new user: %s.", MODULE_NAME, psCredSet->psUser->pUser);
330 nState = MSTATE_RUNNING;
331 }
332 else
333 writeError(ERR_DEBUG_MODULE, "[%s] Next credential set - user: %s password: %s", MODULE_NAME, psCredSet->psUser->pUser, psCredSet->pPass);
334 }
335 }
336 break;
337 case MSTATE_EXITING:
338 nState = MSTATE_COMPLETE;
339 break;
340 default:
341 writeError(ERR_CRITICAL, "Unknown %s module state %d", MODULE_NAME, nState);
342 if (hSocket > 0)
343 medusaDisconnect(hSocket);
344 hSocket = -1;
345 psLogin->iResult = LOGIN_RESULT_UNKNOWN;
346 return FAILURE;
347 }
348 }
349
350 /* check if server responded to GET queries */
351 writeError(ERR_DEBUG_MODULE, "[%s] Checking for server responses.", MODULE_NAME);
352 if (receiveRequest(hSocket, _psSessionData, &nPassCount, &arrszPassList, &szLocation) == FAILURE)
353 {
354 writeError(ERR_DEBUG_MODULE, "[%s] Failed to find valid READ community string.", MODULE_NAME);
355 return SUCCESS;
356 }
357
358 for (i=0; i < nPassCount; i++)
359 {
360 writeError(ERR_DEBUG_MODULE, "[%s] Located valid community string (%d/%d): %s.", MODULE_NAME, i+1, nPassCount, arrszPassList[i]);
361
362 if (_psSessionData->nReadWrite == SNMP_WRITE)
363 {
364 writeError(ERR_DEBUG_MODULE, "[%s] Checking if community string has WRITE access.", MODULE_NAME);
365
366 /* send SET request to server */
367 if (sendWrite(hSocket, _psSessionData, arrszPassList[i], szLocation))
368 {
369 writeError(ERR_ERROR, "[%s] Failed to send SET request.", MODULE_NAME);
370 return FAILURE;
371 }
372 FREE(szLocation);
373
374 /* check if community string has WRITE access */
375 if (receiveRequest(hSocket, _psSessionData, &nPassCountWrite, &arrszPassListWrite, &szLocation) == SUCCESS)
376 {
377 writeError(ERR_DEBUG_MODULE, "[%s] Located valid WRITE community string: %s.", MODULE_NAME, arrszPassList[i]);
378 psLogin->iResult = LOGIN_RESULT_SUCCESS;
379 setPassResult(psLogin, arrszPassList[i]);
380 }
381 else
382 {
383 writeError(ERR_ERROR, "[%s] Community string appears to have only READ access.", MODULE_NAME);
384 psLogin->iResult = LOGIN_RESULT_ERROR;
385 setPassResult(psLogin, arrszPassList[i]);
386 }
387 FREE(arrszPassListWrite);
388 }
389 else
390 {
391 writeError(ERR_DEBUG_MODULE, "[%s] Located valid READ community string: %s.", MODULE_NAME, arrszPassList[i]);
392 psLogin->iResult = LOGIN_RESULT_SUCCESS;
393 setPassResult(psLogin, arrszPassList[i]);
394 }
395
396 FREE(arrszPassList[i]);
397 FREE(szLocation);
398 }
399
400 if (hSocket > 0)
401 medusaDisconnect(hSocket);
402
403 FREE(psUser);
404 FREE(psCredSet);
405 FREE(arrszPassList);
406 FREE(arrszPassListWrite);
407 return SUCCESS;
408 }
409
410 /* Module Specific Functions */
411
412 /*
413 http://book.opensourceproject.org.cn/embedded/tcpipembedded/opensource/0061.html
414
415 The first TLV in the request is called sequence and is used to identify the length of the following TLVs.
416 The sequence type is 0x30 and the next octet is used to decode the length of this TLV. If the length octet
417 has the high-order bit set (0x80), then the length octet masked with 0x7f yields the number of bytes that
418 follow that will make up the value length (in big-endian order). If the high-order bit is not set, then
419 this octet is the length (no length octets follow).
420
421 Example: 0x30 0x2f 0x02 0x01 0x00
422 Sequence: 0x30 0x2f
423 Version: 0x02 0x01 0x00
424
425 Example: 0x30 0x82 0x00 0x2f 0x02 0x01 0x00
426 Sequence: 0x30 0x82 0x00 0x2f
427 Version: 0x02 0x01 0x00
428 */
parseLength(unsigned char * bufReceive)429 int parseLength(unsigned char* bufReceive)
430 {
431 int nLength = 0;
432 int nOctets = 0;
433
434 if (bufReceive[0] == 0x30)
435 {
436 if (bufReceive[1] & 0x80) /* multi-octet mode */
437 {
438 nOctets = bufReceive[1] & 0x7f;
439
440 /* limited to 4 octets worth of length data */
441 if (nOctets == 1)
442 nLength = bufReceive[2];
443 else if (nOctets == 2)
444 nLength = (bufReceive[2] << 8) + bufReceive[3];
445 else if (nOctets == 3)
446 nLength = (bufReceive[2] << 16) + (bufReceive[3] << 8) + bufReceive[4];
447 else if (nOctets == 4)
448 nLength = (bufReceive[2] << 24) + (bufReceive[3] << 16) + (bufReceive[4] << 8) + bufReceive[5];
449
450 if ((nLength > 0) && ((bufReceive[2+nOctets] == 0x02) && (bufReceive[2+nOctets+1] == 0x01)))
451 writeError(ERR_DEBUG_MODULE, "[%s] Multi-octet mode length: %d", MODULE_NAME, nLength);
452 else
453 {
454 writeError(ERR_ERROR, "[%s] Failed to parse length or SNMP version (multi-octet mode).", MODULE_NAME);
455 nLength = -1;
456 }
457 }
458 else if ((bufReceive[2] == 0x02) && (bufReceive[3] == 0x01)) /* single octet mode, version check */
459 {
460 nLength = bufReceive[1];
461 writeError(ERR_DEBUG_MODULE, "[%s] Single octet mode length: %d", MODULE_NAME, nLength);
462 }
463 else
464 {
465 writeError(ERR_ERROR, "[%s] Failed to parse length or SNMP version.", MODULE_NAME);
466 nLength = -1;
467 }
468 }
469
470 return nLength;
471 }
472
473
countResponses(int nReceiveBufferSize,unsigned char * bufReceive)474 int countResponses(int nReceiveBufferSize, unsigned char* bufReceive)
475 {
476 int i = 0;
477 int nLength = 0;
478 int nResponseCount = 0;
479
480 for (i = 0; i < nReceiveBufferSize; i++) {
481 if (bufReceive[i] == 0x30)
482 {
483 nLength = parseLength(&bufReceive[i]);
484 if (nLength > 0)
485 {
486 writeError(ERR_DEBUG_MODULE, "[%s] Located start of SNMP response (%d bytes).", MODULE_NAME, nLength);
487 nResponseCount++;
488 i += nLength;
489 }
490 }
491 }
492
493 return nResponseCount;
494 }
495
processResponse(int nReceiveBufferSize,unsigned char * bufReceive,int * nSNMPLength,char ** szPassword,char ** szLocation)496 int processResponse(int nReceiveBufferSize, unsigned char* bufReceive, int *nSNMPLength, char** szPassword, char** szLocation)
497 {
498 int i;
499 writeError(ERR_DEBUG_MODULE, "[%s] Parsing SNMP response data.", MODULE_NAME);
500
501 for (i = 0; i < nReceiveBufferSize; i++) {
502 *nSNMPLength = parseLength(&bufReceive[i]);
503 if (*nSNMPLength > 0)
504 {
505 writeError(ERR_DEBUG_MODULE, "[%s] Located start of SNMP response (%d bytes).", MODULE_NAME, *nSNMPLength);
506
507 for (; i < nReceiveBufferSize; i++) {
508 if (bufReceive[i] == 0x04) {
509 writeError(ERR_DEBUG_MODULE, "[%s] Located start of SNMP community string.", MODULE_NAME);
510 if (bufReceive[i+1] > 0)
511 {
512 writeError(ERR_DEBUG_MODULE, "[%s] Located SNMP community string size: %d.", MODULE_NAME, bufReceive[i+1]);
513 *szPassword = malloc(bufReceive[i+1] + 1);
514 memset(*szPassword, 0, bufReceive[i+1] + 1);
515 memcpy(*szPassword, bufReceive + i + 2, bufReceive[i+1]);
516 writeError(ERR_DEBUG_MODULE, "[%s] Located community string: %s.", MODULE_NAME, *szPassword);
517 }
518 else
519 {
520 writeError(ERR_DEBUG_MODULE, "[%s] Failed to locate community string.", MODULE_NAME);
521 return FAILURE;
522 }
523
524 for (i = i + bufReceive[i + 1]; i + 2 < nReceiveBufferSize; i++) { /* skip community string */
525 if (bufReceive[i] == 0xa2) {
526 writeError(ERR_DEBUG_MODULE, "[%s] Located PDU Response.", MODULE_NAME);
527 for (; i + 2 < nReceiveBufferSize; i++) {
528 if (bufReceive[i] == 0x02) {
529 writeError(ERR_DEBUG_MODULE, "[%s] Located ID.", MODULE_NAME);
530 for (i = i + (bufReceive[i + 1]); i + 2 < nReceiveBufferSize; i++) { /* skip Request ID */
531 if ((bufReceive[i] == 0x02) && (bufReceive[i + 1] == 0x01) && (bufReceive[i + 2] == 0x00)) {
532 writeError(ERR_DEBUG_MODULE, "[%s] Located success status flag.", MODULE_NAME);
533
534 *szLocation = malloc(bufReceive[i + 6 + 14 + 1] + 1);
535 memset(*szLocation, 0, bufReceive[i + 6 + 14 + 1] + 1);
536 memcpy(*szLocation, bufReceive + i + 6 + 14 + 2, bufReceive[i + 6 + 14 + 1]);
537
538 writeError(ERR_DEBUG_MODULE, "[%s] sysLocation: %s.", MODULE_NAME, *szLocation);
539 return(SUCCESS);
540 }
541 }
542 }
543 }
544 }
545 }
546 }
547 }
548 }
549 }
550
551 return FAILURE;
552 }
553
sendRead(int hSocket,_SNMP_DATA * _psSessionData,char * szPassword)554 int sendRead(int hSocket, _SNMP_DATA* _psSessionData, char* szPassword)
555 {
556 unsigned char* bufSend;
557 int nSendBufferSize = 0;
558
559 struct _SNMPV1_A {
560 char ID;
561 char len;
562 char ver[3];
563 char comid;
564 char comlen;
565 } snmpv1_a = {
566 .ID = '\x30',
567 .len = '\x00',
568 .ver = "\x02\x01\x00", /* \x02\x01\x01 for snmp v2c */
569 .comid = '\x04',
570 .comlen = '\x00'
571 };
572
573 struct _SNMPV1_R {
574 char type[2];
575 char identid[2];
576 char ident[4];
577 char errstat[3];
578 char errind[3];
579 char objectid[2];
580 char object[12];
581 char value[3];
582 } snmpv1_r = {
583 .type = "\xa0\x1c", /* GET */
584 .identid = "\x02\x04",
585 .ident = "\x6f\x67\x4e\xe1", /* request id - doesn't matter */
586 .errstat = "\x02\x01\x00", /* no error */
587 .errind = "\x02\x01\x00", /* error index 0 */
588 .objectid = "\x30\x0e",
589 .object = "\x30\x0c\x06\x08\x2b\x06\x01\x02\x01\x01\x06\x00", /* sysLocation */
590 .value = "\x05\x00" /* we just read, so value = 0 */
591 };
592
593 if (_psSessionData->nVersion == SNMP_VER_V2C)
594 snmpv1_a.ver[2] = '\x01';
595
596 /* GET system.sysLocation */
597 nSendBufferSize = sizeof(snmpv1_a) + sizeof(snmpv1_r) + strlen(szPassword);
598 snmpv1_a.comlen = (char) strlen(szPassword);
599 snmpv1_a.len = nSendBufferSize - 3;
600
601 bufSend = malloc(nSendBufferSize);
602 memset(bufSend, 0, nSendBufferSize);
603 memcpy(bufSend, &snmpv1_a, sizeof(snmpv1_a));
604 memcpy(bufSend + sizeof(snmpv1_a), szPassword, strlen(szPassword));
605 memcpy(bufSend + sizeof(snmpv1_a) + strlen(szPassword), &snmpv1_r, sizeof(snmpv1_r));
606
607 writeError(ERR_DEBUG_MODULE, "[%s] Sending GET request for system.sysLocation.", MODULE_NAME);
608 if (medusaSend(hSocket, bufSend, nSendBufferSize - 1, 0) < 0)
609 {
610 writeError(ERR_ERROR, "%s failed: medusaSend was not successful", MODULE_NAME);
611 free(bufSend);
612 return(MSTATE_FAILURE);
613 }
614 free(bufSend);
615
616 return(MSTATE_RUNNING);
617 }
618
sendWrite(int hSocket,_SNMP_DATA * _psSessionData,char * szPassword,char * szLocation)619 int sendWrite(int hSocket, _SNMP_DATA* _psSessionData, char* szPassword, char* szLocation)
620 {
621 unsigned char* bufSend;
622 int nSendBufferSize = 0;
623
624 struct _SNMPV1_A {
625 char ID;
626 char len;
627 char ver[3];
628 char comid;
629 char comlen;
630 } snmpv1_a = {
631 .ID = '\x30',
632 .len = '\x00',
633 .ver = "\x02\x01\x00", /* \x02\x01\x01 for snmp v2c */
634 .comid = '\x04',
635 .comlen = '\x00'
636 };
637
638 struct _SNMPV1_W {
639 char type[2];
640 char identid[2];
641 char ident[4];
642 char errstat[3];
643 char errind[3];
644 char objectid[2];
645 char object[12];
646 char value[2];
647 } snmpv1_w = {
648 .type = "\xa3\x20", /* SET */
649 .identid = "\x02\x04",
650 .ident = "\x6f\x67\x4e\xe1", /* request id - doesn't matter */
651 .errstat = "\x02\x01\x00", /* no error */
652 .errind = "\x02\x01\x00", /* error index 0 */
653 .objectid = "\x30\x0c",
654 .object = "\x30\x0c\x06\x08\x2b\x06\x01\x02\x01\x01\x06\x00", /* sysLocation */
655 .value = "\x04\x00" /* write value */
656 };
657
658 if (_psSessionData->nVersion == SNMP_VER_V2C)
659 snmpv1_a.ver[2] = '\x01';
660
661 if (szLocation == NULL)
662 szLocation = "";
663
664 nSendBufferSize = sizeof(snmpv1_a) + sizeof(snmpv1_w) + strlen(szPassword) + strlen(szLocation) + 1;
665 snmpv1_a.comlen = (char) strlen(szPassword);
666 snmpv1_a.len = nSendBufferSize - 3;
667
668 bufSend = malloc(nSendBufferSize);
669 memset(bufSend, 0, nSendBufferSize);
670 memcpy(bufSend, &snmpv1_a, sizeof(snmpv1_a));
671 memcpy(bufSend + sizeof(snmpv1_a), szPassword, strlen(szPassword));
672 memcpy(bufSend + sizeof(snmpv1_a) + strlen(szPassword), &snmpv1_w, sizeof(snmpv1_w));
673 memset(bufSend + sizeof(snmpv1_a) + strlen(szPassword) + 1, 28 + strlen(szLocation), 1); /* set length remaining */
674 memset(bufSend + sizeof(snmpv1_a) + strlen(szPassword) + 15, 14 + strlen(szLocation), 1); /* set length remaining */
675 memset(bufSend + sizeof(snmpv1_a) + strlen(szPassword) + 17, 12 + strlen(szLocation), 1); /* set length remaining */
676 memset(bufSend + sizeof(snmpv1_a) + strlen(szPassword) + sizeof(snmpv1_w) - 1, strlen(szLocation), 1);
677 strncpy((char *)bufSend + sizeof(snmpv1_a) + strlen(szPassword) + sizeof(snmpv1_w), szLocation, strlen(szLocation));
678
679 writeError(ERR_DEBUG_MODULE, "[%s] Sending SET request for system.sysLocation.", MODULE_NAME);
680 if (medusaSend(hSocket, bufSend, nSendBufferSize - 1, 0) < 0)
681 {
682 writeError(ERR_ERROR, "%s failed: medusaSend was not successful", MODULE_NAME);
683 free(bufSend);
684 return(FAILURE);
685 }
686 free(bufSend);
687
688 return(SUCCESS);
689 }
690
receiveRequest(int hSocket,_SNMP_DATA * _psSessionData,int * nPassCount,char *** arrszPassList,char ** szLocation)691 int receiveRequest(int hSocket, _SNMP_DATA* _psSessionData, int* nPassCount, char*** arrszPassList, char** szLocation)
692 {
693 unsigned char *bufReceive = NULL;
694 unsigned char *bufReceiveTmp = NULL;
695 int i, nReceiveBufferSize, nReceiveBufferSizeTmp;
696 int nResponse = FAILURE;
697 int nSNMPLength;
698
699 nReceiveBufferSize = 0;
700 bufReceive = medusaReceiveRawDelay(hSocket, &nReceiveBufferSize, _psSessionData->nReadTimeout, _psSessionData->nReadTimeout);
701 if (bufReceive == NULL)
702 {
703 writeError(ERR_DEBUG_MODULE, "[%s] No data received. Possible incorrect community string.", MODULE_NAME);
704 return(FAILURE);
705 }
706
707 *nPassCount = countResponses(nReceiveBufferSize, bufReceive);
708 if (*nPassCount <= 0)
709 {
710 writeError(ERR_ERROR, "[%s] Responses received, however, no community strings were located.", MODULE_NAME);
711 return(FAILURE);
712 }
713 else
714 {
715 writeError(ERR_DEBUG_MODULE, "[%s] Creating password array for %d entries.", MODULE_NAME, *nPassCount);
716 *arrszPassList = malloc(*nPassCount * sizeof(char*));
717 memset(*arrszPassList, 0, *nPassCount * sizeof(char*));
718 }
719
720 bufReceiveTmp = bufReceive;
721 nReceiveBufferSizeTmp = nReceiveBufferSize;
722 for (i = 0; i < *nPassCount; i++)
723 {
724 writeError(ERR_DEBUG_MODULE, "[%s] Retrieving data for response: %d.", MODULE_NAME, i+1);
725 nResponse = processResponse(nReceiveBufferSizeTmp, bufReceiveTmp, &nSNMPLength, &(*arrszPassList)[i], szLocation);
726 if (nResponse == SUCCESS)
727 {
728 writeError(ERR_DEBUG_MODULE, "[%s] Retrieved SNMP data (%d bytes). Community String: %s Location: %s.", MODULE_NAME, nSNMPLength, (*arrszPassList)[i], *szLocation);
729 }
730 else
731 writeError(ERR_ERROR, "[%s] Error processing SNMP response (%d).", MODULE_NAME, i+1);
732
733 bufReceiveTmp += (nSNMPLength + 2);
734 nReceiveBufferSizeTmp -= (nSNMPLength + 2);
735 }
736
737 free(bufReceive);
738
739 return(nResponse);
740 }
741