1 /* This NetX tests an SMTP Server configured for no authentication (the server
2    response to EHLO message contains no AUTH parameters).  The client if configured
3    for LOGIN or PLAIN authentication can still try to authenticate itself but the
4    server may send an error message which will cause the client to abort.
5 
6    In this test case, the Client is configured for AUTH NONE, so the Client should
7    skip the authentication step and go directly to MAIL.  The simulated server response
8    expects to go from EHLO to MAIL, skipping authentication.  */
9 
10 
11 #include   "tx_api.h"
12 #include   "nx_api.h"
13 
14 
15 extern void test_control_return(UINT status);
16 
17 #if !defined(NX_DISABLE_IPV4)
18 
19 #include   "nxd_smtp_client.h"
20 
21 #define     DEMO_STACK_SIZE         2048
22 #define     SERVER_IPADR            IP_ADDRESS(10, 0, 0, 1)
23 #define     CLIENT_IPADR            IP_ADDRESS(10, 0, 0, 10)
24 
25 /* Define the ThreadX and NetX object control blocks...  */
26 
27 static TX_THREAD               thread_client;
28 static TX_THREAD               thread_server;
29 
30 static NX_PACKET_POOL          client_packet_pool;
31 static NX_IP                   client_ip;
32 static NX_IP                   server_ip;
33 
34 
35 static NX_PACKET_POOL          server_packet_pool;
36 static NX_TCP_SOCKET           server_socket;
37 static NX_SMTP_CLIENT          smtp_client;
38 
39 #define SUBJECT_LINE           "NetX Duo SMTP Client Demo"
40 #define MAIL_BODY              ".NetX Duo SMTP client is a simple SMTP client implementation  \r\n" \
41                                ".that allow embedded devices to send email to an SMTP server. \r\n" \
42                                "This feature is intended to allow a device to send simple status\r\n " \
43                                "reports using the most universal Internet application email.\r\n" \
44                                "The rest of this narrative is merely to supply this most interesting quote: \r\n" \
45                                "Perhaps the most vivid recollection of my youth is that of the local wheelmen, \r\n" \
46                                "led by my father, stopping at our home to eat pone, sip mint juleps, and flog \r\n" \
47                                "the field hands. This more than anything cultivated my life-long aversion \r\n"  \
48                                "to bicycles. ~~ Tennessee Williams.\r\n\r\n" \
49                                "Nothing compares to the simple pleasure of a bike ride. --John F. Kennedy, (surely you've heard of him?)\r\n\r\n" \
50                                "Perhaps the most vivid recollection of my youth is that of being flogged \r\n" \
51                                "by the local wheelmen, along with the field hands, the postman, and a \r\n" \
52                                "young Tennessee Williams. This more than anything cultivated my life-long " \
53                                "aversion to his plays. -Truman Capote\r\n" \
54                                "When I see an adult on a bicycle, I do not despair for the future of the human race. H.G. Wells \r\n"  \
55                                "during the Second World War, if the United States had retooled its \r\n" \
56                                "factories for manufacturing bicycles instead of munitions, we'd be one of \r\n" \
57                                "the healthiest, least oil-dependent, and most environmentally-sound \r\n" \
58                                "constituents in the Nazi empire today. -Ralph Nader."
59 
60 
61 #define PASSWORD               "testpwd"
62 #define RECIPIENT_ADDRESS      "recipient@domain.com"
63 #define LOCAL_DOMAIN           "domain.com"
64 #define FROM_ADDRESS           "recipient@domain.com"
65 #define USERNAME               FROM_ADDRESS
66 #define SMTP_SERVER_PORT       25
67 
68 
69 /* Set the authentication type to none. */
70 #define CLIENT_AUTHENTICATION_TYPE NX_SMTP_CLIENT_AUTH_NONE
71 
72 #if defined(__PRODUCT_NETXDUO__)
73 static NXD_ADDRESS server_ip_address;
74 #else
75 static ULONG server_ip_address;
76 #endif
77 
78 
79 static UINT server_complete = NX_FALSE;
80 
81 /* Define the counters used in the demo application...  */
82 
83 static UINT                    status;
84 static ULONG                   error_counter = 0;
85 static ULONG                   notify_calls =  0;
86 
87 /* Define thread prototypes.  */
88 
89 static void    thread_0_entry(ULONG thread_input);
90 static void    thread_1_entry(ULONG thread_input);
91 extern void    _nx_ram_network_driver_1024(struct NX_IP_DRIVER_STRUCT *driver_req);
92 static void    receive_packet_function(NX_TCP_SOCKET *socket_ptr);
93 
94 /* SMTP Tests.  */
95 static void    smtp_test_initialize();
96 
97 /* Send SMTP server response.  */
98 static UINT    nx_smtp_response_packet_send(NX_TCP_SOCKET *server_socket, UINT port, UINT packet_number);
99 
100 extern char response_220_greetings_pkt[185];
101 extern int  response_220_greetings_size;
102 
103 /* This is the one packet 250 EHLO message */
104 extern char response_250_ehlo_noauth_pkt[145];
105 extern int response_250_ehlo_noauth_size;
106 
107 extern char response_250_sender_ok_pkt[40];
108 extern int response_250_sender_ok_size;
109 
110 extern char response_250_recipient_ok_pkt[43];
111 extern int response_250_recipient_ok_size;
112 
113 extern char response_354_enter_mail_pkt[40];
114 extern int response_354_enter_mail_size;
115 
116 extern char response_250_message_saved_pkt[92];
117 extern int response_250_message_saved_size;
118 
119 extern char response_221_bye_pkt[80];
120 extern int response_221_bye_size;
121 
122 
123 typedef struct SMTP_TEST_STRUCT
124 {
125     char          *smtp_test_pkt_data;
126     int           smtp_test_pkt_size;
127 } SMTP_TEST;
128 
129 
130 #define MSG_COUNT      7
131 
132 static SMTP_TEST       smtp_test[MSG_COUNT];
133 
134 
135 /* Define what the initial system looks like.  */
136 
137 #ifdef CTEST
test_application_define(void * first_unused_memory)138 VOID test_application_define(void *first_unused_memory)
139 #else
140 void    netx_smtp_auth_none_test_application_define(void *first_unused_memory)
141 #endif
142 {
143 
144 CHAR    *pointer;
145 
146     /* Setup the working pointer.  */
147     pointer =  (CHAR *) first_unused_memory;
148 
149     /* Create the SMTP client thread.  */
150     tx_thread_create(&thread_client, "thread client", thread_0_entry, 0,
151             pointer, DEMO_STACK_SIZE,
152             4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
153     pointer =  pointer + DEMO_STACK_SIZE;
154 
155     tx_thread_create(&thread_server, "thread server", thread_1_entry, 0,
156             pointer, DEMO_STACK_SIZE,
157             3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
158     pointer =  pointer + DEMO_STACK_SIZE;
159 
160     /* Initialize the NetX system.  */
161     nx_system_initialize();
162 
163     /* Create client packet pool.  */
164     status =  nx_packet_pool_create(&client_packet_pool, "NetX Main Packet Pool", 1536, pointer, 10*1536);
165     pointer = pointer + (10*1536);
166 
167     /* Check for pool creation error.  */
168     if (status)
169         return;
170 
171     /* Create server packet pool.  */
172     status =  nx_packet_pool_create(&server_packet_pool, "NetX Main Packet Pool", 1536, pointer, 10*1536);
173     pointer = pointer + (10*1536);
174 
175     /* Check for pool creation error.  */
176     if (status)
177         return;
178 
179     /* Create an IP instance.  */
180     status = nx_ip_create(&client_ip, "SMTP CLient IP", CLIENT_IPADR, 0xFFFFFF00UL, &client_packet_pool, _nx_ram_network_driver_1024,
181                     pointer, 2048, 1);
182     pointer =  pointer + 2048;
183 
184     /* Create another IP instance.  */
185     status += nx_ip_create(&server_ip, "SMTP Server IP", SERVER_IPADR, 0xFFFFFF00UL, &server_packet_pool, _nx_ram_network_driver_1024,
186                     pointer, 2048, 1);
187     pointer =  pointer + 2048;
188 
189     /* Check for IP create errors.  */
190     if (status)
191         error_counter++;
192 
193     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
194     status =  nx_arp_enable(&client_ip, (void *) pointer, 1024);
195     pointer = pointer + 1024;
196 
197     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
198     status +=  nx_arp_enable(&server_ip, (void *) pointer, 1024);
199     pointer = pointer + 1024;
200 
201     /* Check for ARP enable errors.  */
202     if (status)
203         error_counter++;
204 
205     /* Enable TCP traffic.  */
206     status =  nx_tcp_enable(&client_ip);
207     status += nx_tcp_enable(&server_ip);
208 
209     /* Check for TCP enable errors.  */
210     if (status)
211         error_counter++;
212 
213 
214     /* The demo client username and password is the authentication
215    data used when the server attempts to authentication the client. */
216 
217 #if defined(__PRODUCT_NETXDUO__)
218     server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
219     server_ip_address.nxd_ip_address.v4 = SERVER_IPADR;
220 
221     status =  nxd_smtp_client_create(&smtp_client, &client_ip, &client_packet_pool,
222                                      USERNAME,
223                                      PASSWORD,
224                                      FROM_ADDRESS,
225                                      LOCAL_DOMAIN, CLIENT_AUTHENTICATION_TYPE,
226                                      &server_ip_address, SMTP_SERVER_PORT);
227 #else
228     server_ip_address = SERVER_IPADR;
229 
230     status =  nx_smtp_client_create(&smtp_client, &client_ip, &client_packet_pool,
231                                      USERNAME,
232                                      PASSWORD,
233                                      FROM_ADDRESS,
234                                      LOCAL_DOMAIN, CLIENT_AUTHENTICATION_TYPE,
235                                      server_ip_address, SMTP_SERVER_PORT);
236 #endif
237 
238     if (status != NX_SUCCESS)
239     {
240         error_counter++;
241     }
242 
243     return;
244 }
245 
246 
247 /* Define the test threads.  */
248 
thread_0_entry(ULONG thread_input)249 static void    thread_0_entry(ULONG thread_input)
250 {
251 
252 ULONG       actual_status;
253 
254     printf("NetX Test:   SMTP No Authentication Test...............................");
255 
256     /* Check for earlier errors.  */
257     if(error_counter)
258     {
259         printf("ERROR!\n");
260         test_control_return(1);
261     }
262 
263 #ifdef FEATURE_NX_IPV6
264     /* Sleep 5 seconds to finish DAD.  */
265     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
266 #endif
267 
268     /* Ensure the IP instance has been initialized.  */
269     status = nx_ip_status_check(&client_ip, NX_IP_INITIALIZE_DONE, &actual_status, 100);
270 
271     /* Check status...*/
272     if(status != NX_SUCCESS)
273     {
274         printf("ERROR!\n");
275         test_control_return(1);
276     }
277 
278     /* Let the server get set up first. */
279     tx_thread_sleep(20);
280 
281 
282     /* The SMTP test initialize.  */
283     smtp_test_initialize();
284 
285      /* Create a mail instance with the above text message and recipient info. */
286     status =  nx_smtp_mail_send(&smtp_client, RECIPIENT_ADDRESS, NX_SMTP_MAIL_PRIORITY_NORMAL,
287                                 SUBJECT_LINE, MAIL_BODY, strlen(MAIL_BODY));
288 
289     /* Create a mail instance with the above text message and recipient info. */
290 
291     /* Check for errors. */
292     if (status != NX_SUCCESS)
293     {
294         error_counter++;
295     }
296 
297     /* Give the server time to disconnect. */
298     while(1)
299     {
300 
301         if (server_complete)
302             break;
303 
304         tx_thread_sleep(20);
305     }
306     /* Release threadx resources used by client. */
307     status = nx_smtp_client_delete(&smtp_client);
308 
309     /* Return the test result.  */
310     if (error_counter)
311     {
312         printf("ERROR!\n");
313         test_control_return(1);
314     }
315     else
316     {
317 
318         printf("SUCCESS!\n");
319         test_control_return(0);
320     }
321 }
322 
323 /* This thread task simulates SMTP server response to client requests. */
thread_1_entry(ULONG thread_input)324 static void    thread_1_entry(ULONG thread_input)
325 {
326 
327 NX_PACKET   *my_packet;
328 ULONG       port;
329 ULONG       peer_address;
330 UINT        i;
331 UCHAR      *work_ptr;
332 ULONG      actual_status;
333 
334 
335     /* Check for earlier errors.  */
336     if(error_counter)
337     {
338         printf("ERROR!\n");
339         test_control_return(1);
340     }
341 
342 #ifdef FEATURE_NX_IPV6
343     /* Sleep 5 seconds to finish DAD.  */
344     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
345 #endif /* FEATURE_NX_IPV6 */
346 
347     /* Ensure the IP instance has been initialized.  */
348     status = nx_ip_status_check(&server_ip, NX_IP_INITIALIZE_DONE, &actual_status, 100);
349 
350     /* Check status...*/
351     if(status != NX_SUCCESS)
352     {
353         printf("ERROR!\n");
354         test_control_return(1);
355     }
356 
357     /* Create a TCP socket act as the SMTP server.  */
358     status = nx_tcp_socket_create(&server_ip, &server_socket, "Socket 1",
359                                   NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
360                                   8000, NX_NULL, NX_NULL);
361 
362     /* Check status.  */
363     if (status)
364     {
365         error_counter++;
366     }
367 
368     /* Register the receive notify function.  */
369     status =  nx_tcp_socket_receive_notify(&server_socket, receive_packet_function);
370 
371     /* Check status.  */
372     if (status)
373     {
374         error_counter++;
375     }
376 
377     /* Bind the TCP socket to the SMTP port.  */
378     status =  nx_tcp_server_socket_listen(&server_ip, SMTP_SERVER_PORT, &server_socket, 5, NX_NULL);
379 
380     /* Check status.  */
381     if (status)
382     {
383         error_counter++;
384     }
385 
386     status = nx_tcp_server_socket_accept(&server_socket, NX_WAIT_FOREVER);
387 
388         /* Check status.  */
389     if (status)
390     {
391         error_counter++;
392     }
393 
394     /* Act as the SMTP server to receive the SMTP Client query and send the SMTP response.  */
395     for (i = 0; i < MSG_COUNT; i++ )
396     {
397 
398         if (i == 0)
399         {
400             /* This is the greeting, we don't wait for a client response first...*/
401         }
402         else
403         {
404             /* Receive a TCP packet.  */
405             status =  nx_tcp_socket_receive(&server_socket, &my_packet, 100 * NX_IP_PERIODIC_RATE);
406 
407             /* Check status.  */
408             if (status)
409             {
410                 error_counter++;
411                 continue;            }
412 
413             /* Get the SMTP client TCP port.  */
414             status = nx_tcp_socket_peer_info_get(&server_socket, &peer_address, &port);
415 
416             /* Check status.  */
417             if (status)
418             {
419                error_counter++;
420             }
421 
422             /* This is the message data. We need to parse for the End Of Message marker. */
423             if (i == 5)
424             {
425                 /* Look for 0x0D 0x0A 0x2E 0x0d 0x0A indiating end of mail message. */
426                 work_ptr = my_packet -> nx_packet_prepend_ptr + my_packet -> nx_packet_length - 5;
427 
428                 if ((*work_ptr == 0x0D) &&
429                     (*(work_ptr + 1) == 0x0A) &&
430                     (*(work_ptr + 2) == 0x2E) &&
431                     (*(work_ptr + 3) == 0x0D) &&
432                     (*(work_ptr + 4) == 0x0A))
433 
434                 {
435 
436                     /* Done iwth message, wait for QUIT command from client. */
437                 }
438                 else
439                 {
440 
441                     /* Stay in this state. */
442 
443                     i--;
444                     nx_packet_release(my_packet);
445                     continue;
446                 }
447              }
448             /* Release the packet.  */
449             nx_packet_release(my_packet);
450         }
451         /* Send the SMTP response packet.  */
452         status = nx_smtp_response_packet_send(&server_socket, port, i);
453 
454         /* Check status.  */
455         if (status)
456         {
457             error_counter++;
458         }
459     }
460 
461     /* Wait for Client process last message. */
462     tx_thread_sleep(20);
463 
464     /* Unlisten and Unbind the TCP socket.  */
465 
466     status = nx_tcp_server_socket_unaccept(&server_socket);
467     status += nx_tcp_server_socket_unlisten(&server_ip, SMTP_SERVER_PORT);
468 
469     /* Check status.  */
470     if (status)
471     {
472         error_counter++;
473     }
474 
475     /* Delete the TCP socket.  */
476     status =  nx_tcp_socket_delete(&server_socket);
477 
478     /* Check status.  */
479     if (status)
480     {
481         error_counter++;
482     }
483 
484 
485     server_complete = NX_TRUE;
486 
487 }
488 
receive_packet_function(NX_TCP_SOCKET * socket_ptr)489 static void    receive_packet_function(NX_TCP_SOCKET *socket_ptr)
490 {
491 
492     if (socket_ptr == &server_socket)
493         notify_calls++;
494 }
495 
nx_smtp_response_packet_send(NX_TCP_SOCKET * server_socket,UINT port,UINT packet_number)496 static UINT   nx_smtp_response_packet_send(NX_TCP_SOCKET *server_socket, UINT port, UINT packet_number)
497 {
498 UINT        status;
499 NX_PACKET   *response_packet;
500 
501     /* Allocate a response packet.  */
502     status =  nx_packet_allocate(&server_packet_pool, &response_packet, NX_TCP_PACKET, TX_WAIT_FOREVER);
503 
504     /* Check status.  */
505     if (status)
506     {
507         error_counter++;
508         return status;
509     }
510     memset(response_packet -> nx_packet_prepend_ptr, 0, (response_packet -> nx_packet_data_end - response_packet -> nx_packet_prepend_ptr));
511 
512     /* Write the SMTP response messages into the packet payload!  */
513     memcpy(response_packet -> nx_packet_prepend_ptr,
514            smtp_test[packet_number].smtp_test_pkt_data,
515            smtp_test[packet_number].smtp_test_pkt_size);
516 
517     /* Adjust the write pointer.  */
518     response_packet -> nx_packet_length =  smtp_test[packet_number].smtp_test_pkt_size;
519     response_packet -> nx_packet_append_ptr =  response_packet -> nx_packet_prepend_ptr + response_packet -> nx_packet_length;
520 
521     /* Send the TCP packet with the correct port.  */
522     status =  nx_tcp_socket_send(server_socket, response_packet, 100);
523 
524     /* Check the status.  */
525     if (status)
526     {
527         error_counter++;
528         nx_packet_release(response_packet);
529     }
530 
531     return status;
532 }
533 
smtp_test_initialize()534 static void     smtp_test_initialize()
535 {
536 
537     smtp_test[0].smtp_test_pkt_data = &response_220_greetings_pkt[0];
538     smtp_test[0].smtp_test_pkt_size = response_220_greetings_size;
539     smtp_test[1].smtp_test_pkt_data = &response_250_ehlo_noauth_pkt[0];
540     smtp_test[1].smtp_test_pkt_size = response_250_ehlo_noauth_size;
541 
542     smtp_test[2].smtp_test_pkt_data = &response_250_sender_ok_pkt[0];
543     smtp_test[2].smtp_test_pkt_size = response_250_sender_ok_size;
544     smtp_test[3].smtp_test_pkt_data = &response_250_recipient_ok_pkt[0];
545     smtp_test[3].smtp_test_pkt_size = response_250_recipient_ok_size;
546     smtp_test[4].smtp_test_pkt_data = &response_354_enter_mail_pkt[0];
547     smtp_test[4].smtp_test_pkt_size = response_354_enter_mail_size;
548 
549     smtp_test[5].smtp_test_pkt_data = &response_250_message_saved_pkt[0];
550     smtp_test[5].smtp_test_pkt_size = response_250_message_saved_size;
551 
552     smtp_test[6].smtp_test_pkt_data = &response_221_bye_pkt[0];
553     smtp_test[6].smtp_test_pkt_size = response_221_bye_size;
554 }
555 
556 #else
557 
558 #ifdef CTEST
test_application_define(void * first_unused_memory)559 VOID test_application_define(void *first_unused_memory)
560 #else
561 void    netx_smtp_auth_none_test_application_define(void *first_unused_memory)
562 #endif
563 {
564 
565     /* Print out test information banner.  */
566     printf("NetX Test:   SMTP No Authentication Test...............................N/A\n");
567 
568     test_control_return(3);
569 }
570 #endif
571 
572