1 /* This NetX test concentrates on the SNMPv3 operation with MD5 security. The test uses a different authentiation and
2 encryption password than is received from the SNMP Manager. The test is successful if the SNMP Agent rejects the SNMP
3 manager response, sets an authentication error to notify the calling application authentication failed, and does not send a
4 response back to the SNMP Manager.
5 */
6
7 #include "tx_api.h"
8 #include "nx_api.h"
9 #include "nxd_snmp.h"
10 #include "nx_udp.h"
11 #include "small_mib_helper.h"
12
13 extern void test_control_return(UINT);
14
15 #define DEMO_STACK_SIZE 4096
16
17 #if !defined(NX_DISABLE_IPV4)
18
19 extern MIB_ENTRY mib2_mib[];
20
21 static NX_SNMP_SECURITY_KEY my_authentication_key;
22 static NX_SNMP_SECURITY_KEY my_privacy_key;
23
24 static UINT v3_mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
25 static UINT v3_mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
26 static UINT v3_mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
27 static UINT v3_mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username);
28 static VOID v3_mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr);
29
30
31 static UINT query_response_complete = NX_FALSE; /* to synchronize when the agent sends the SNMP trap */
32 #define QUERY_COUNT 2
33
34 /* To show byte by byte comparison of pre-recorded response with SNMP agent, define this option.
35 #define VERBOSE
36 */
37
38
39 /* Define the ThreadX and NetX object control blocks... */
40
41 static TX_THREAD thread_agent;
42 static TX_THREAD thread_manager;
43 static NX_SNMP_AGENT my_agent;
44 static NX_PACKET_POOL pool_0;
45 static NX_IP agent_ip;
46 static NX_IP manager_ip;
47 static NX_UDP_SOCKET snmp_manager_socket;
48
49 #define SNMP_MANAGER_ADDRESS IP_ADDRESS(10,0,0,1)
50 #define SNMP_AGENT_ADDRESS IP_ADDRESS(10,0,0,10)
51
52
53
54 /* Define the counters used in the demo application... */
55
56 static UINT status;
57 static ULONG error_counter = 0;
58
59
60 /* Define thread prototypes. */
61
62 static void thread_0_entry(ULONG thread_input);
63 static void thread_1_entry(ULONG thread_input);
64 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
65 static void snmp_test_initialize();
66
67 /* Send SNMP manager query. */
68 static UINT nx_snmp_query_packet_send(NX_UDP_SOCKET *snmp_manager_socket, UINT request_id, UINT packet_number);
69
70 extern char get_request_priv_pkt[59];
71 extern int get_request_priv_size;
72 extern char getnext_request_priv_pkt[127];
73 extern int getnext_request_priv_size;
74
75
76
77 typedef struct SNMP_QUERY_STRUCT
78 {
79 char *snmp_query_pkt_data;
80 int snmp_query_pkt_size;
81 } SNMP_QUERY;
82
83
84
85 static SNMP_QUERY snmp_query[QUERY_COUNT];
86
87
88
89 /* Define what the initial system looks like. */
90
91 #ifdef CTEST
test_application_define(void * first_unused_memory)92 VOID test_application_define(void *first_unused_memory)
93 #else
94 void netx_snmp_v3_md5_failed_security_test_application_define(void *first_unused_memory)
95 #endif
96 {
97
98 CHAR *pointer;
99
100 /* Setup the working pointer. */
101 pointer = (CHAR *) first_unused_memory;
102
103 /* Create the SNMP agent thread. */
104 status = tx_thread_create(&thread_agent, "Agent thread", thread_0_entry, 0,
105 pointer, DEMO_STACK_SIZE,
106
107 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
108 pointer = pointer + DEMO_STACK_SIZE;
109
110 /* Create the SNMP Manager thread. */
111 status += tx_thread_create(&thread_manager, "Manager thread", thread_1_entry, 0,
112 pointer, DEMO_STACK_SIZE,
113 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
114 pointer = pointer + DEMO_STACK_SIZE;
115
116 /* Check for IP create errors. */
117 /* Check for IP create errors. */
118 if (status)
119 {
120 error_counter++;
121 test_control_return(1);
122 }
123
124 /* Initialize the NetX system. */
125 nx_system_initialize();
126
127 /* Create a packet pool. */
128 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1000, pointer, 10000);
129 pointer = pointer + 10000;
130
131 /* Check for IP create errors. */
132 if (status)
133 {
134 error_counter++;
135 }
136
137 /* Create an IP instance. */
138 status = nx_ip_create(&agent_ip, "Agent IP", SNMP_AGENT_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500, pointer , 2048, 1);
139
140 pointer += 2048;
141
142 /* Create another IP instance. */
143 status += nx_ip_create(&manager_ip, "Manager IP", SNMP_MANAGER_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500, pointer, 2048, 1);
144
145 pointer += 2048;
146
147 /* Check for IP create errors. */
148 if (status)
149 {
150 error_counter++;
151 }
152
153 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
154 status = nx_arp_enable(&agent_ip, (void *) pointer, 1024);
155 pointer = pointer + 1024;
156
157 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
158 status += nx_arp_enable(&manager_ip, (void *) pointer, 1024);
159 pointer = pointer + 1024;
160
161 /* Check for ARP enable errors. */
162 if (status)
163 {
164 error_counter++;
165 }
166
167 /* Enable UDP traffic. */
168 status = nx_udp_enable(&agent_ip);
169 status += nx_udp_enable(&manager_ip);
170
171 /* Check for UDP enable errors. */
172 if (status)
173 {
174 error_counter++;
175 }
176
177
178 /* Create an SNMP agent instance. */
179 status = nx_snmp_agent_create(&my_agent, "public", &agent_ip, pointer, 4096, &pool_0,
180 v3_mib2_username_processing, v3_mib2_get_processing,
181 v3_mib2_getnext_processing, v3_mib2_set_processing);
182 pointer = pointer + 4096;
183
184
185 if (status)
186 {
187 error_counter++;
188 }
189
190
191 /* Create an authentication key using MD5 and register it with the agent. */
192 status = nx_snmp_agent_md5_key_create(&my_agent, (UCHAR *)("authpassword2"), &my_authentication_key);
193
194 /* Register the authentication key with the agent. */
195 status |= nx_snmp_agent_authenticate_key_use(&my_agent, &my_authentication_key);
196
197 if (status != NX_SUCCESS)
198 {
199 error_counter++;
200 return;
201 }
202
203 /* Create a privacy key and register it with the SNMP agent. */
204 status = nx_snmp_agent_md5_key_create(&my_agent, (UCHAR *)("privpassword2"), &my_privacy_key);
205
206 status |= nx_snmp_agent_privacy_key_use(&my_agent, &my_privacy_key);
207
208 if (status |= NX_SUCCESS)
209 {
210 error_counter++;
211 }
212
213 return;
214
215 }
216
217 /* Define the test threads. */
218
thread_0_entry(ULONG thread_input)219 static void thread_0_entry(ULONG thread_input)
220 {
221
222 UINT status;
223
224
225 printf("NetX Test: SNMP V3 with Failed MD5 Security Test.....................");
226 tx_thread_sleep(20);
227
228 if (error_counter)
229 {
230 printf("ERROR!\n");
231 test_control_return(1);
232 }
233
234 /* Initialize our boot up count to 1. */
235 status = nx_snmp_agent_v3_context_boots_set(&my_agent, 1);
236
237 if (status)
238 {
239 error_counter++;
240 }
241
242 /* Reset the system clock so we can reasonably fit in the 150 second Time Window. */
243 tx_time_set(0);
244
245 /* Start the SNMP instance. */
246 status = nx_snmp_agent_start(&my_agent);
247
248 /* Return the test result. */
249 if (status)
250 {
251 error_counter++;
252 }
253
254 while (!query_response_complete)
255 {
256 tx_thread_sleep(100);
257 }
258
259 tx_thread_sleep(50);
260
261 if (error_counter)
262 {
263 printf("ERROR!\n");
264 test_control_return(1);
265 }
266 else
267 {
268 printf("SUCCESS!\n");
269 test_control_return(0);
270 }
271 }
272
273
thread_1_entry(ULONG thread_input)274 static void thread_1_entry(ULONG thread_input)
275 {
276
277 NX_PACKET *agent_packet;
278 UINT i;
279 USHORT request_id = 1;
280
281
282 /* Let the agent get set up first! */
283 tx_thread_sleep(50);
284
285
286 status = nx_udp_socket_create(&manager_ip, &snmp_manager_socket, "Manager Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
287
288 /* Bind the UDP socket to an IP port. */
289 status |= nx_udp_socket_bind(&snmp_manager_socket, 0, 100);
290
291 /* Check status. */
292 if (status)
293 {
294
295 error_counter++;
296
297 /* Indicate the query response is complete. */
298 query_response_complete = NX_TRUE;
299
300 return;
301 }
302
303 /* Load the test data. */
304 snmp_test_initialize();
305
306 /* Send SNMP queries to the agent.. */
307 for (i = 0; i < QUERY_COUNT; i++ )
308 {
309
310 /* Send the SNMP manager query packet. */
311 status = nx_snmp_query_packet_send(&snmp_manager_socket, request_id, i);
312
313 /* Check status. */
314 if (status)
315 {
316 error_counter++;
317 break;
318 }
319
320 /* Receive the SNMP agent response. */
321 status = nx_udp_socket_receive(&snmp_manager_socket, &agent_packet, 100);
322
323 /* Check status. We should only get one response. */
324 if (status && (i == 0))
325 {
326 error_counter++;
327 break;
328 }
329
330 /* Check for errors on discovery/report exchange. */
331 if (i == 0)
332 {
333 if ((my_agent.nx_snmp_agent_reports_sent != 1) || (my_agent.nx_snmp_agent_unknown_engineid_count != 1))
334 {
335 error_counter++;
336 break;
337 }
338 /* Allow variability in size due to unpredictable variables (timer). */
339 if ((agent_packet -> nx_packet_length <= 105) || (agent_packet -> nx_packet_length >= 109))
340 {
341 error_counter++;
342 break;
343 }
344 }
345
346 /* Check for errors on the completion of V3 handshake. */
347 if (i == 1)
348 {
349 /* When authentication fails, SNMP should set an authentication error and send another report. */
350 if ((my_agent.nx_snmp_agent_authentication_errors == 0) || (my_agent.nx_snmp_agent_reports_sent > 1))
351 {
352 error_counter++;
353 break;
354 }
355
356 }
357
358 if (status == NX_SUCCESS)
359 {
360
361 /* Release the packet. */
362 nx_packet_release(agent_packet);
363 }
364
365 request_id++;
366 }
367
368 /* Check for other general errors. */
369 if (my_agent.nx_snmp_agent_request_errors || my_agent.nx_snmp_agent_internal_errors)
370 {
371
372 error_counter++;
373 }
374
375 /* Indicate the query response is complete. */
376 query_response_complete = NX_TRUE;
377
378 }
379
380
nx_snmp_query_packet_send(NX_UDP_SOCKET * snmp_manager_socket,UINT snmp_request_id,UINT packet_number)381 static UINT nx_snmp_query_packet_send(NX_UDP_SOCKET *snmp_manager_socket, UINT snmp_request_id, UINT packet_number)
382 {
383 UINT status;
384 NX_PACKET *query_packet;
385
386 /* Allocate a response packet. */
387 status = nx_packet_allocate(&pool_0, &query_packet, NX_UDP_PACKET, 100);
388
389 /* Check status. */
390 if (status)
391 {
392 return status;
393 }
394
395
396 memset(query_packet -> nx_packet_prepend_ptr, 0, (query_packet -> nx_packet_data_end - query_packet -> nx_packet_prepend_ptr));
397
398 /* Write the SMTP response messages into the packet payload! */
399 memcpy(query_packet -> nx_packet_prepend_ptr,
400 snmp_query[packet_number].snmp_query_pkt_data,
401 snmp_query[packet_number].snmp_query_pkt_size);
402
403 /* Adjust the write pointer. */
404 query_packet -> nx_packet_length = snmp_query[packet_number].snmp_query_pkt_size;
405 query_packet -> nx_packet_append_ptr = query_packet -> nx_packet_prepend_ptr + query_packet -> nx_packet_length;
406
407 /* Send the UDP packet with the correct port. */
408 status = nx_udp_socket_send(snmp_manager_socket, query_packet, IP_ADDRESS(10, 0, 0, 10), 161);
409
410 /* Check the status. */
411 if (status)
412 nx_packet_release(query_packet);
413
414 return status;
415 }
416
417
snmp_test_initialize()418 static void snmp_test_initialize()
419 {
420
421 /* Contact - no security*/
422 snmp_query[0].snmp_query_pkt_data = &get_request_priv_pkt[0];
423 snmp_query[0].snmp_query_pkt_size = get_request_priv_size;
424 snmp_query[1].snmp_query_pkt_data = &getnext_request_priv_pkt[0];
425 snmp_query[1].snmp_query_pkt_size = getnext_request_priv_size;
426
427
428 }
429
430
431 /* Define the application's GET processing routine. */
432
v3_mib2_get_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)433 UINT v3_mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
434 {
435
436 UINT i;
437 UINT status;
438
439
440
441 /* Loop through the sample MIB to see if we have information for the supplied variable. */
442 i = 0;
443 status = NX_SNMP_ERROR;
444 while (mib2_mib[i].object_name)
445 {
446
447 /* See if we have found the matching entry. */
448 status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
449
450 /* Was it found? */
451 if (status == NX_SUCCESS)
452 {
453
454 /* Yes it was found. */
455 break;
456 }
457
458 /* Move to the next index. */
459 i++;
460 }
461
462 /* Determine if a not found condition is present. */
463 if (status != NX_SUCCESS)
464 {
465
466 /* The object was not found - return an error. */
467 return(NX_SNMP_ERROR_NOSUCHNAME);
468 }
469
470 /* Determine if the entry has a get function. */
471 if (mib2_mib[i].object_get_callback)
472 {
473
474 /* Yes, call the get function. */
475 status = (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
476 }
477 else
478 {
479
480 /* No get function, return no access. */
481 status = NX_SNMP_ERROR_NOACCESS;
482 }
483
484 /* Return the status. */
485 return(status);
486 }
487
488
489 /* Define the application's GETNEXT processing routine. */
490
v3_mib2_getnext_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)491 UINT v3_mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
492 {
493
494 UINT i;
495 UINT status;
496
497
498 /* Loop through the sample MIB to see if we have information for the supplied variable. */
499 i = 0;
500 status = NX_SNMP_ERROR;
501 while (mib2_mib[i].object_name)
502 {
503
504 /* See if we have found the next entry. */
505 status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
506
507 /* Is the next entry the mib greater? */
508 if (status == NX_SNMP_NEXT_ENTRY)
509 {
510
511 /* Yes it was found. */
512 break;
513 }
514
515 /* Move to the next index. */
516 i++;
517 }
518
519 /* Determine if a not found condition is present. */
520 if (status != NX_SNMP_NEXT_ENTRY)
521 {
522
523 /* The object was not found - return an error. */
524 return(NX_SNMP_ERROR_NOSUCHNAME);
525 }
526
527
528 /* Copy the new name into the object. */
529 nx_snmp_object_copy(mib2_mib[i].object_name, object_requested);
530
531 /* Determine if the entry has a get function. */
532 if (mib2_mib[i].object_get_callback)
533 {
534
535 /* Yes, call the get function. */
536 status = (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
537
538 /* Determine if the object data indicates an end-of-mib condition. */
539 if (object_data -> nx_snmp_object_data_type == NX_SNMP_END_OF_MIB_VIEW)
540 {
541
542 /* Copy the name supplied in the mib table. */
543 nx_snmp_object_copy(mib2_mib[i].object_value_ptr, object_requested);
544 }
545 }
546 else
547 {
548
549 /* No get function, return no access. */
550 status = NX_SNMP_ERROR_NOACCESS;
551 }
552
553 /* Return the status. */
554 return(status);
555 }
556
557
558 /* Define the application's SET processing routine. */
559
v3_mib2_set_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)560 UINT v3_mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
561 {
562
563 UINT i;
564 UINT status;
565
566
567 /* Loop through the sample MIB to see if we have information for the supplied variable. */
568 i = 0;
569 status = NX_SNMP_ERROR;
570 while (mib2_mib[i].object_name)
571 {
572
573 /* See if we have found the matching entry. */
574 status = nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
575
576 /* Was it found? */
577 if (status == NX_SUCCESS)
578 {
579
580 /* Yes it was found. */
581 break;
582 }
583
584 /* Move to the next index. */
585 i++;
586 }
587
588 /* Determine if a not found condition is present. */
589 if (status != NX_SUCCESS)
590 {
591
592 /* The object was not found - return an error. */
593 return(NX_SNMP_ERROR_NOSUCHNAME);
594 }
595
596
597 /* Determine if the entry has a set function. */
598 if (mib2_mib[i].object_set_callback)
599 {
600
601 /* Yes, call the set function. */
602 status = (mib2_mib[i].object_set_callback)(mib2_mib[i].object_value_ptr, object_data);
603 }
604 else
605 {
606
607 /* No get function, return no access. */
608 status = NX_SNMP_ERROR_NOACCESS;
609 }
610
611
612 /* Return the status. */
613 return(status);
614 }
615
616 /* Create an error code if matching user not found. */
617 #define USER_NOT_FOUND 1
618
619 /* Define the username callback routine routine. Usernames should be
620 associated with permissions (public or private string) and what version
621 of SNMP the user is configured for. The username callback should verify
622 the incoming username MIB access permissions. */
v3_mib2_username_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * username)623 UINT v3_mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username)
624 {
625
626 v3_mib2_variable_update(&agent_ip, &my_agent);
627
628 return NX_SUCCESS;
629
630 }
631
632 extern ULONG sysUpTime;
633 /* Define the application's update routine. */
634
v3_mib2_variable_update(NX_IP * ip_ptr,NX_SNMP_AGENT * agent_ptr)635 VOID v3_mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr)
636 {
637
638 /* Update the snmp parameters. */
639 sysUpTime = tx_time_get();
640 }
641
642 #else
643
644 #ifdef CTEST
test_application_define(void * first_unused_memory)645 VOID test_application_define(void *first_unused_memory)
646 #else
647 void netx_snmp_v3_md5_failed_security_test_application_define(void *first_unused_memory)
648 #endif
649 {
650
651 /* Print out test information banner. */
652 printf("NetX Test: SNMP V3 with Failed MD5 Security Test.....................N/A\n");
653
654 test_control_return(3);
655 }
656 #endif
657