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