1 /* This NetX test concentrates on the basic SNMPv2 operation.  The 'manager' sends
2    a request for an unknown item ("oid"). The SNMP agent should not responds, but
3    set an internal error and be able to respond to the next request.
4 
5    The MIB database is defined in demo_snmp_helper.h */
6 
7 
8 #include   "tx_api.h"
9 #include   "nx_api.h"
10 #include   "nxd_snmp.h"
11 #include   "nx_udp.h"
12 #include   "small_mib_helper.h"
13 
14 extern void    test_control_return(UINT);
15 
16 #if !defined(NX_DISABLE_IPV4) && !defined(NX_DISABLE_FRAGMENTATION)
17 
18 #define     DEMO_STACK_SIZE         4096
19 
20 extern MIB_ENTRY   mib2_mib[];
21 
22 //NX_SNMP_SECURITY_KEY my_authentication_key;
23 
24 NX_SNMP_SECURITY_KEY my_privacy_key;
25 
26 static UINT    mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
27 static UINT    mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
28 static UINT    mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data);
29 static UINT    mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username);
30 static VOID    mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr);
31 
32 static UCHAR context_engine_id[] = {0x80, 0x00, 0x0d, 0xfe, 0x03, 0x00, 0x11, 0x23, 0x23, 0x44, 0x55};
33 static UINT context_engine_size = 11;
34 static UCHAR context_name[] = {0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c};
35 static UINT context_name_size = 7;
36 
37 
38 /* Define the ThreadX and NetX object control blocks...  */
39 
40 static TX_THREAD               thread_agent;
41 static NX_SNMP_AGENT           my_agent;
42 static NX_PACKET_POOL          pool_0;
43 static NX_IP                   agent_ip;
44 
45 #define SNMP_AGENT_ADDRESS     IP_ADDRESS(10, 128, 16, 17)
46 
47 
48 /* Define the counters used in the demo application...  */
49 
50 static UINT                    status;
51 static ULONG                   error_counter;
52 static ULONG                   snmp_stack[DEMO_STACK_SIZE / sizeof(ULONG)];
53 
54 
55 /* Define thread prototypes.  */
56 
57 static void    thread_0_entry(ULONG thread_input);
58 static void    thread_1_entry(ULONG thread_input);
59 extern void    _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
60 static void    snmp_test_initialize();
61 
62 /* Inject SNMP manager query.  */
63 static VOID packet_inject(UCHAR *data_ptr, UINT data_size);
64 
65 
66 extern unsigned char v3_buffer_overwrite_packet1[1514];
67 extern int           v3_buffer_overwrite_packet1_size;
68 extern unsigned char v3_buffer_overwrite_packet2[54];
69 extern int           v3_buffer_overwrite_packet2_size;
70 
71 #define QUERY_COUNT  2
72 
73 typedef struct SNMP_QUERY_STRUCT
74 {
75     char          *snmp_query_pkt_data;
76     int           snmp_query_pkt_size;
77 } SNMP_QUERY;
78 
79 
80 static SNMP_QUERY   snmp_query[QUERY_COUNT];
81 
82 
83 #ifdef CTEST
test_application_define(void * first_unused_memory)84 VOID test_application_define(void *first_unused_memory)
85 #else
86 void    netx_snmp_v3_buffer_overwrite_test_application_define(void *first_unused_memory)
87 #endif
88 {
89 
90 CHAR    *pointer;
91 
92     /* Setup the working pointer.  */
93     pointer =  (CHAR *) first_unused_memory;
94 
95     /* Create the SNMP agent thread.  */
96     tx_thread_create(&thread_agent, "Agent thread", thread_0_entry, 0,
97                       pointer, DEMO_STACK_SIZE, 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
98 
99     pointer =  pointer + DEMO_STACK_SIZE;
100 
101     /* Initialize the NetX system.  */
102     nx_system_initialize();
103 
104     /* Create a packet pool.  */
105     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, pointer, (sizeof(NX_PACKET) + 1536) * 10);
106     pointer = pointer + (sizeof(NX_PACKET) + 1536) * 10;
107 
108     /* Create an IP instance.  */
109     status += nx_ip_create(&agent_ip, "Agent IP", SNMP_AGENT_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
110                     pointer, 2048, 1);
111     pointer =  pointer + 2048;
112 
113     /* Check for IP create errors.  */
114     if (status)
115     {
116         error_counter++;
117     }
118 
119     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
120     status =  nx_arp_enable(&agent_ip, (void *) pointer, 1024);
121     pointer = pointer + 1024;
122 
123     /* Check for ARP enable errors.  */
124     if (status)
125     {
126         error_counter++;
127     }
128 
129     /* Enable UDP traffic.  */
130     status =  nx_udp_enable(&agent_ip);
131 
132     /* Check for UDP enable errors.  */
133     if (status)
134     {
135         error_counter++;
136     }
137 
138     status =  nx_ip_fragment_enable(&agent_ip);
139     if (status)
140     {
141         error_counter++;
142     }
143 }
144 
145 /* Define the test threads.  */
146 
thread_0_entry(ULONG thread_input)147 static void    thread_0_entry(ULONG thread_input)
148 {
149 
150 UINT status;
151 UINT        i;
152 NX_PACKET  *packet_ptr;
153 
154     printf("NetX Test:   SNMP V3 Buffer Overwrite Test.............................");
155 
156     if (error_counter)
157     {
158         printf("ERROR!\n");
159         test_control_return(1);
160     }
161 
162     /* Create an SNMP agent instance.  */
163     status = nx_snmp_agent_create(&my_agent, "SNMP Agent", &agent_ip, snmp_stack, sizeof(snmp_stack), &pool_0,
164                          mib2_username_processing, mib2_get_processing,
165                          mib2_getnext_processing, mib2_set_processing);
166 
167     if (status)
168     {
169         error_counter++;
170     }
171 
172 #ifdef AUTHENTICATION_REQUIRED
173     /* Create an authentication key. */
174     status = nx_snmp_agent_md5_key_create(&my_agent, (UCHAR *)"authpassword", &my_authentication_key);
175     if (status)
176     {
177         error_counter++;
178     }
179 
180     /* Use the authentication key. */
181     status = nx_snmp_agent_authenticate_key_use(&my_agent, &my_authentication_key);
182     if (status)
183     {
184         error_counter++;
185     }
186 #endif
187 
188     /* Create a privacy key. */
189     status = nx_snmp_agent_md5_key_create(&my_agent, (UCHAR *)"privpassword", &my_privacy_key);
190     if (status)
191     {
192         error_counter++;
193     }
194 
195 #if 0
196     /* Use the privacy key. */
197     status = nx_snmp_agent_privacy_key_use(&my_agent, &my_privacy_key);
198     if (status)
199     {
200         error_counter++;
201     }
202 #endif
203 
204     /* Start the SNMP instance.  */
205     status = nx_snmp_agent_start(&my_agent);
206 
207     /* Return the test result.  */
208     if (status)
209     {
210        error_counter++;
211     }
212 
213     /* Load the test data up. */
214     snmp_test_initialize();
215 
216     /* Send SNMP queries to the agent.  */
217     for (i = 0; i < QUERY_COUNT; i++ )
218     {
219 
220         /* Inject the SNMP manager query packet.  */
221         packet_inject(snmp_query[i].snmp_query_pkt_data, snmp_query[i].snmp_query_pkt_size);
222     }
223 
224     /* Wait for processing snmp packet.  */
225     tx_thread_sleep(NX_IP_PERIODIC_RATE);
226 
227     /* Make sure the packet pool is not corrupted.  */
228     while (pool_0.nx_packet_pool_available)
229     {
230         if (nx_packet_allocate(&pool_0, &packet_ptr, 0, NX_NO_WAIT) ||
231             (packet_ptr -> nx_packet_pool_owner != &pool_0))
232         {
233             error_counter++;
234             break;
235         }
236     }
237 
238     if (error_counter)
239     {
240         printf("ERROR!\n");
241         test_control_return(1);
242     }
243     else
244     {
245         printf("SUCCESS!\n");
246         test_control_return(0);
247     }
248 
249     return;
250 }
251 
packet_inject(UCHAR * data_ptr,UINT data_size)252 static VOID packet_inject(UCHAR *data_ptr, UINT data_size)
253 {
254 UINT        status;
255 NX_PACKET  *my_packet;
256 
257     status = nx_packet_allocate(&pool_0, &my_packet, NX_RECEIVE_PACKET, NX_NO_WAIT);
258 
259     /* Check status */
260     if(status)
261         error_counter ++;
262 
263     /* Make sure IP header is 4-byte aligned. */
264     my_packet -> nx_packet_prepend_ptr += 2;
265     my_packet -> nx_packet_append_ptr += 2;
266 
267     /* Fill in the packet with data. Skip the MAC header.  */
268     status = nx_packet_data_append(my_packet, data_ptr, data_size, &pool_0, NX_NO_WAIT);
269 
270     /* Check status */
271     if(status)
272         error_counter ++;
273 
274     /* Skip the MAC header.  */
275     my_packet -> nx_packet_length -= 14;
276     my_packet -> nx_packet_prepend_ptr += 14;
277 
278     /* Directly receive the TCP packet.  */
279     _nx_ip_packet_deferred_receive(&agent_ip, my_packet);
280 }
281 
snmp_test_initialize()282 static void  snmp_test_initialize()
283 {
284     snmp_query[0].snmp_query_pkt_data = &v3_buffer_overwrite_packet1[0];
285     snmp_query[0].snmp_query_pkt_size = v3_buffer_overwrite_packet1_size;
286 
287     snmp_query[1].snmp_query_pkt_data = &v3_buffer_overwrite_packet2[0];
288     snmp_query[1].snmp_query_pkt_size = v3_buffer_overwrite_packet2_size;
289 }
290 
291 
292 /* Define the application's GET processing routine.  */
293 
mib2_get_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)294 UINT    mib2_get_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
295 {
296 
297 UINT    i;
298 UINT    status;
299 
300 
301 
302     /* Loop through the sample MIB to see if we have information for the supplied variable.  */
303     i =  0;
304     status =  NX_SNMP_ERROR;
305     while (mib2_mib[i].object_name)
306     {
307 
308         /* See if we have found the matching entry.  */
309         status =  nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
310 
311         /* Was it found?  */
312         if (status == NX_SUCCESS)
313         {
314 
315             /* Yes it was found.  */
316             break;
317         }
318 
319         /* Move to the next index.  */
320         i++;
321     }
322 
323     /* Determine if a not found condition is present.  */
324     if (status != NX_SUCCESS)
325     {
326 
327         /* The object was not found - return an error.  */
328         return(NX_SNMP_ERROR_NOSUCHNAME);
329     }
330 
331     /* Determine if the entry has a get function.  */
332     if (mib2_mib[i].object_get_callback)
333     {
334 
335         /* Yes, call the get function.  */
336         status =  (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
337     }
338     else
339     {
340 
341         /* No get function, return no access.  */
342         status =  NX_SNMP_ERROR_NOACCESS;
343     }
344 
345     /* Return the status.  */
346     return(status);
347 }
348 
349 
350 /* Define the application's GETNEXT processing routine.  */
351 
mib2_getnext_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)352 UINT    mib2_getnext_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
353 {
354 
355 UINT    i;
356 UINT    status;
357 
358 
359     /* Loop through the sample MIB to see if we have information for the supplied variable.  */
360     i =  0;
361     status =  NX_SNMP_ERROR;
362     while (mib2_mib[i].object_name)
363     {
364 
365         /* See if we have found the next entry.  */
366         status =  nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
367 
368         /* Is the next entry the mib greater?  */
369         if (status == NX_SNMP_NEXT_ENTRY)
370         {
371 
372             /* Yes it was found.  */
373             break;
374         }
375 
376         /* Move to the next index.  */
377         i++;
378     }
379 
380     /* Determine if a not found condition is present.  */
381     if (status != NX_SNMP_NEXT_ENTRY)
382     {
383 
384         /* The object was not found - return an error.  */
385         return(NX_SNMP_ERROR_NOSUCHNAME);
386     }
387 
388 
389     /* Copy the new name into the object.  */
390     nx_snmp_object_copy(mib2_mib[i].object_name, object_requested);
391 
392     /* Determine if the entry has a get function.  */
393     if (mib2_mib[i].object_get_callback)
394     {
395 
396         /* Yes, call the get function.  */
397         status =  (mib2_mib[i].object_get_callback)(mib2_mib[i].object_value_ptr, object_data);
398 
399         /* Determine if the object data indicates an end-of-mib condition.  */
400         if (object_data -> nx_snmp_object_data_type == NX_SNMP_END_OF_MIB_VIEW)
401         {
402 
403             /* Copy the name supplied in the mib table.  */
404             nx_snmp_object_copy(mib2_mib[i].object_value_ptr, object_requested);
405         }
406     }
407     else
408     {
409 
410         /* No get function, return no access.  */
411         status =  NX_SNMP_ERROR_NOACCESS;
412     }
413 
414     /* Return the status.  */
415     return(status);
416 }
417 
418 
419 /* Define the application's SET processing routine.  */
420 
mib2_set_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * object_requested,NX_SNMP_OBJECT_DATA * object_data)421 UINT    mib2_set_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *object_requested, NX_SNMP_OBJECT_DATA *object_data)
422 {
423 
424 UINT    i;
425 UINT    status;
426 
427 
428     /* Loop through the sample MIB to see if we have information for the supplied variable.  */
429     i =  0;
430     status =  NX_SNMP_ERROR;
431     while (mib2_mib[i].object_name)
432     {
433 
434         /* See if we have found the matching entry.  */
435         status =  nx_snmp_object_compare(object_requested, mib2_mib[i].object_name);
436 
437         /* Was it found?  */
438         if (status == NX_SUCCESS)
439         {
440 
441             /* Yes it was found.  */
442             break;
443         }
444 
445         /* Move to the next index.  */
446         i++;
447     }
448 
449     /* Determine if a not found condition is present.  */
450     if (status != NX_SUCCESS)
451     {
452 
453         /* The object was not found - return an error.  */
454         return(NX_SNMP_ERROR_NOSUCHNAME);
455     }
456 
457 
458     /* Determine if the entry has a set function.  */
459     if (mib2_mib[i].object_set_callback)
460     {
461 
462         /* Yes, call the set function.  */
463         status =  (mib2_mib[i].object_set_callback)(mib2_mib[i].object_value_ptr, object_data);
464     }
465     else
466     {
467 
468         /* No get function, return no access.  */
469         status =  NX_SNMP_ERROR_NOACCESS;
470     }
471 
472 
473     /* Return the status.  */
474     return(status);
475 }
476 
477 /* Create an error code if matching user not found. */
478 #define USER_NOT_FOUND 1
479 
480 /* Define the username callback routine routine. Usernames should be
481    associated with permissions (public or private string) and what version
482    of SNMP the user is configured for. The username callback should verify
483    the incoming username MIB access permissions.  */
mib2_username_processing(NX_SNMP_AGENT * agent_ptr,UCHAR * username)484 UINT  mib2_username_processing(NX_SNMP_AGENT *agent_ptr, UCHAR *username)
485 {
486 
487     mib2_variable_update(&agent_ip, &my_agent);
488 
489     return NX_SUCCESS;
490 
491 }
492 
493 /* Define the application's update routine.  */
494 
mib2_variable_update(NX_IP * ip_ptr,NX_SNMP_AGENT * agent_ptr)495 VOID  mib2_variable_update(NX_IP *ip_ptr, NX_SNMP_AGENT *agent_ptr)
496 {
497 
498     /* Update the snmp parameters.  */
499     return;
500 }
501 #else
502 
503 #ifdef CTEST
test_application_define(void * first_unused_memory)504 VOID test_application_define(void *first_unused_memory)
505 #else
506 void    netx_snmp_v3_buffer_overwrite_test_application_define(void *first_unused_memory)
507 #endif
508 {
509 
510     /* Print out test information banner.  */
511     printf("NetX Test:   SNMP V3 Buffer Overwrite Test.............................N/A\n");
512 
513     test_control_return(3);
514 }
515 #endif
516 
517