1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /**                                                                       */
16 /** NetX SMTP Client Component                                            */
17 /**                                                                       */
18 /**   Simple Mail Transfer Protocol (SMTP)                                */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 #define NX_SMTP_SOURCE_CODE
25 
26 
27 /* Force error checking to be disabled in this module.  */
28 
29 #ifndef NX_DISABLE_ERROR_CHECKING
30 #define NX_DISABLE_ERROR_CHECKING
31 #endif
32 
33 
34 
35 #include "ctype.h"
36 #include "nx_api.h"
37 #include "nx_ip.h"
38 #include "nx_ipv4.h"
39 #include "nxd_smtp_client.h"
40 #ifdef FEATURE_NX_IPV6
41 #include "nx_ipv6.h"
42 #endif
43 #include "nx_tcp.h"
44 
45 /* Necessary for threadx thread state macros. */
46 extern  TX_THREAD   *_tx_thread_current_ptr;
47 extern  TX_THREAD    _tx_timer_thread;
48 extern  volatile ULONG _tx_thread_system_state;
49 
50 #define         NX_SMTP_BUFFER_SIZE           512
51 static CHAR     _nx_smtp_buffer[NX_SMTP_BUFFER_SIZE];
52 
53 
54 /* Define internal SMTP Client functions.  */
55 
56 static VOID _nx_smtp_find_crlf(UCHAR *buffer, UINT length, UCHAR **CRLF, UINT reverse);
57 static UINT _nx_smtp_cmd_idle(NX_SMTP_CLIENT *client_ptr);
58 static UINT _nx_smtp_rsp_idle(NX_SMTP_CLIENT *client_ptr);
59 static UINT _nx_smtp_cmd_greeting(NX_SMTP_CLIENT *client_ptr);
60 static UINT _nx_smtp_rsp_greeting(NX_SMTP_CLIENT *client_ptr);
61 static UINT _nx_smtp_cmd_ehlo(NX_SMTP_CLIENT *client_ptr);
62 static UINT _nx_smtp_rsp_ehlo(NX_SMTP_CLIENT *client_ptr);
63 static UINT _nx_smtp_cmd_helo(NX_SMTP_CLIENT *client_ptr);
64 static UINT _nx_smtp_rsp_helo(NX_SMTP_CLIENT *client_ptr);
65 static UINT _nx_smtp_cmd_mail(NX_SMTP_CLIENT *client_ptr);
66 static UINT _nx_smtp_rsp_mail(NX_SMTP_CLIENT *client_ptr);
67 static UINT _nx_smtp_cmd_rcpt(NX_SMTP_CLIENT *client_ptr);
68 static UINT _nx_smtp_rsp_rcpt(NX_SMTP_CLIENT *client_ptr);
69 static UINT _nx_smtp_cmd_data(NX_SMTP_CLIENT *client_ptr);
70 static UINT _nx_smtp_rsp_data(NX_SMTP_CLIENT *client_ptr);
71 static UINT _nx_smtp_cmd_message(NX_SMTP_CLIENT *client_ptr);
72 static UINT _nx_smtp_rsp_message(NX_SMTP_CLIENT *client_ptr);
73 static UINT _nx_smtp_cmd_rset(NX_SMTP_CLIENT *client_ptr);
74 static UINT _nx_smtp_rsp_rset(NX_SMTP_CLIENT *client_ptr);
75 static UINT _nx_smtp_cmd_quit(NX_SMTP_CLIENT *client_ptr);
76 static UINT _nx_smtp_rsp_quit(NX_SMTP_CLIENT *client_ptr);
77 static UINT _nx_smtp_cmd_noop(NX_SMTP_CLIENT *client_ptr);
78 static UINT _nx_smtp_rsp_noop(NX_SMTP_CLIENT *client_ptr);
79 static UINT _nx_smtp_cmd_auth(NX_SMTP_CLIENT *client_ptr);
80 static UINT _nx_smtp_rsp_auth(NX_SMTP_CLIENT *client_ptr);
81 static UINT _nx_smtp_cmd_auth_challenge(NX_SMTP_CLIENT *client_ptr);
82 static UINT _nx_smtp_rsp_auth_challenge(NX_SMTP_CLIENT *client_ptr);
83 static UINT _nx_smtp_rsp_hello_command(NX_SMTP_CLIENT* client_ptr);
84 static UINT _nx_smtp_utility_read_server_code(NX_SMTP_CLIENT *client_ptr, ULONG timeout, UINT  receive_all_lines);
85 static UINT _nx_smtp_utility_send_to_server(NX_SMTP_CLIENT *client_ptr, CHAR *buffer_ptr, UINT buffer_length, ULONG timeout);
86 static UINT _nx_smtp_utility_authentication_challenge(NX_SMTP_CLIENT *client_ptr, UCHAR *buffer_ptr, UINT length);
87 static UINT _nx_smtp_client_process(NX_SMTP_CLIENT *client_ptr);
88 static UINT _nx_smtp_utility_send_header_to_server(NX_SMTP_CLIENT *client_ptr, ULONG timeout) ;
89 static VOID _nx_smtp_utility_parse_server_services(NX_SMTP_CLIENT *client_ptr);
90 static UINT _nx_smtp_parse_250_response(UCHAR *buffer_ptr, UINT buffer_length, UINT *is_last_code);
91 static UINT _nx_smtp_parse_response(NX_SMTP_CLIENT *client_ptr, UCHAR *buffer, UINT arguement_index,
92                                     UINT buffer_length, UCHAR *arguement, UINT arguement_length,
93                                     UINT include_crlf);
94 
95 static NX_SMTP_CLIENT_STATES protocol_states[] =
96 {
97     {_nx_smtp_cmd_idle               , _nx_smtp_rsp_idle},
98     {_nx_smtp_cmd_greeting           , _nx_smtp_rsp_greeting},
99     {_nx_smtp_cmd_ehlo               , _nx_smtp_rsp_ehlo},
100     {_nx_smtp_cmd_helo               , _nx_smtp_rsp_helo},
101     {_nx_smtp_cmd_mail               , _nx_smtp_rsp_mail},
102     {_nx_smtp_cmd_rcpt               , _nx_smtp_rsp_rcpt},
103     {_nx_smtp_cmd_data               , _nx_smtp_rsp_data},
104     {_nx_smtp_cmd_message            , _nx_smtp_rsp_message},
105     {_nx_smtp_cmd_rset               , _nx_smtp_rsp_rset},
106     {_nx_smtp_cmd_quit               , _nx_smtp_rsp_quit},
107     {_nx_smtp_cmd_noop               , _nx_smtp_rsp_noop},
108     {_nx_smtp_cmd_auth               , _nx_smtp_rsp_auth},
109     {_nx_smtp_cmd_auth_challenge     , _nx_smtp_rsp_auth_challenge},
110 };
111 
112 
113 
114 
115 /**************************************************************************/
116 /*                                                                        */
117 /*  FUNCTION                                               RELEASE        */
118 /*                                                                        */
119 /*    _nxde_smtp_client_create                            PORTABLE C      */
120 /*                                                           6.1          */
121 /*  AUTHOR                                                                */
122 /*                                                                        */
123 /*    Yuxin Zhou, Microsoft Corporation                                   */
124 /*                                                                        */
125 /*  DESCRIPTION                                                           */
126 /*                                                                        */
127 /*    This function performs error checking on the client create service. */
128 /*                                                                        */
129 /*    Note: The string lengths of username,password,from_address and      */
130 /*    client_domain are limited by internal buffer size.                  */
131 /*                                                                        */
132 /*  INPUT                                                                 */
133 /*                                                                        */
134 /*                                                                        */
135 /*    client_ptr                        Pointer to SMTP Client instance   */
136 /*    ip_ptr                            Pointer to IP instance            */
137 /*    packet_pool_ptr                   Pointer to client packet pool     */
138 /*    username                          Pointer to username               */
139 /*    password                          Pointer to password               */
140 /*    from_address                      Pointer to Client email address   */
141 /*    client_domain                     Pointer to client domain          */
142 /*    authentication_type               SMTP authentication type          */
143 /*    server_address                    Pointer to server address         */
144 /*    server_port                       SMTP server TCP port              */
145 /*                                                                        */
146 /*  OUTPUT                                                                */
147 /*                                                                        */
148 /*    NX_PTR_ERROR                       Invalid pointer parameter        */
149 /*    NX_SMTP_INVALID_PARAM              Invalid non pointer input        */
150 /*    status                             Actual completion status         */
151 /*                                                                        */
152 /*  CALLS                                                                 */
153 /*                                                                        */
154 /*    _nxd_smtp_client_create           Actual SMTP client create service */
155 /*                                                                        */
156 /*  CALLED BY                                                             */
157 /*                                                                        */
158 /*    Application Code                                                    */
159 /*                                                                        */
160 /*  RELEASE HISTORY                                                       */
161 /*                                                                        */
162 /*    DATE              NAME                      DESCRIPTION             */
163 /*                                                                        */
164 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
165 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
166 /*                                            resulting in version 6.1    */
167 /*                                                                        */
168 /**************************************************************************/
_nxde_smtp_client_create(NX_SMTP_CLIENT * client_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * client_packet_pool_ptr,CHAR * username,CHAR * password,CHAR * from_address,CHAR * client_domain,UINT authentication_type,NXD_ADDRESS * server_address,UINT port)169 UINT  _nxde_smtp_client_create(NX_SMTP_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *client_packet_pool_ptr,
170                                CHAR *username, CHAR *password, CHAR *from_address,
171                                CHAR *client_domain, UINT authentication_type,
172                                NXD_ADDRESS *server_address, UINT port)
173 {
174 
175 UINT status;
176 
177 
178     if ((ip_ptr == NX_NULL) || (client_ptr == NX_NULL) || (client_packet_pool_ptr == NX_NULL) ||
179         (from_address == NX_NULL) || (username == NX_NULL) || (password == NX_NULL) ||
180         (client_domain == NX_NULL) || (server_address == NX_NULL))
181     {
182 
183         /* Return error status.  */
184        return(NX_PTR_ERROR);
185     }
186 
187         /* Check for invalid non pointer input. */
188     if (ip_ptr -> nx_ip_id != NX_IP_ID)
189     {
190 
191         return NX_SMTP_INVALID_PARAM;
192     }
193 
194 
195     /* Make sure the IP version is set correctly. */
196     if((server_address -> nxd_ip_version != NX_IP_VERSION_V4) &&
197        (server_address -> nxd_ip_version != NX_IP_VERSION_V6))
198     {
199         return(NX_IP_ADDRESS_ERROR);
200     }
201 
202     /* Call the actual client create service.  */
203     status =  _nxd_smtp_client_create(client_ptr, ip_ptr, client_packet_pool_ptr, username, password,
204                                       from_address, client_domain, authentication_type,
205                                       server_address, port);
206 
207     /* Return completion status.  */
208     return(status);
209 }
210 
211 
212 /**************************************************************************/
213 /*                                                                        */
214 /*  FUNCTION                                               RELEASE        */
215 /*                                                                        */
216 /*    _nxd_smtp_client_create                             PORTABLE C      */
217 /*                                                           6.1          */
218 /*  AUTHOR                                                                */
219 /*                                                                        */
220 /*    Yuxin Zhou, Microsoft Corporation                                   */
221 /*                                                                        */
222 /*  DESCRIPTION                                                           */
223 /*                                                                        */
224 /*    This function creates a SMTP client instance for sending mail to an */
225 /*    SMTP Server over IPv4 or IPv6 networks. It also creates the TCP     */
226 /*    socket for making connections with the SMTP server, sets the        */
227 /*    server IP address and port, and sets the Client username and SMTP   */
228 /*    address (from address) used in all SMTP mail transmissions.         */
229 /*                                                                        */
230 /*    Note: The string lengths of username,password,from_address and      */
231 /*    client_domain are limited by internal buffer size.                  */
232 /*                                                                        */
233 /*   INPUT                                                                */
234 /*                                                                        */
235 /*    client_ptr                        Pointer to SMTP Client instance   */
236 /*    ip_ptr                            Pointer to IP instance            */
237 /*    packet_pool_ptr                   Pointer to client packet pool     */
238 /*    username                          Pointer to username               */
239 /*    password                          Pointer to password               */
240 /*    from_address                      Pointer to Client email address   */
241 /*    client_domain                     Pointer to client domain          */
242 /*    authentication_type               SMTP authentication type          */
243 /*    server_address                    Pointer to server address         */
244 /*    server_port                       SMTP server TCP port              */
245 /*                                                                        */
246 /*  OUTPUT                                                                */
247 /*                                                                        */
248 /*    NX_SUCCESS                        Successful completion status      */
249 /*    status                            Actual completion status          */
250 /*                                                                        */
251 /*  CALLED BY                                                             */
252 /*                                                                        */
253 /*    Application Code                                                    */
254 /*                                                                        */
255 /*  CALLS                                                                 */
256 /*                                                                        */
257 /*    memset                            Clear area of memory              */
258 /*    memcpy                            Copy data to area of memory       */
259 /*    nx_tcp_socket_create              Create a NetX TCP socket          */
260 /*                                                                        */
261 /*  RELEASE HISTORY                                                       */
262 /*                                                                        */
263 /*    DATE              NAME                      DESCRIPTION             */
264 /*                                                                        */
265 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
266 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
267 /*                                            verified memcpy use cases,  */
268 /*                                            resulting in version 6.1    */
269 /*                                                                        */
270 /**************************************************************************/
_nxd_smtp_client_create(NX_SMTP_CLIENT * client_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * client_packet_pool_ptr,CHAR * username,CHAR * password,CHAR * from_address,CHAR * client_domain,UINT authentication_type,NXD_ADDRESS * server_address,UINT port)271 UINT  _nxd_smtp_client_create(NX_SMTP_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *client_packet_pool_ptr,
272                               CHAR *username, CHAR *password, CHAR *from_address,
273                               CHAR *client_domain, UINT authentication_type,
274                               NXD_ADDRESS *server_address, UINT port)
275 {
276 
277 UINT status = NX_SUCCESS;
278 UINT str_length;
279 NX_SMTP_CLIENT_MAIL    *mail_ptr;
280 
281 
282     /* Initialize client as not ready for SMTP yet. */
283     client_ptr -> nx_smtp_client_init_status = NX_FALSE;
284 
285     mail_ptr = &client_ptr -> nx_smtp_client_mail;
286 
287     /* Clear the Client and session memory.  */
288     memset(client_ptr, 0, sizeof(NX_SMTP_CLIENT));
289 
290     /* Configure client with input parameters.  */
291     status = _nx_utility_string_length_check(username, &str_length, NX_SMTP_CLIENT_MAX_USERNAME);
292     if (status)
293     {
294         return(status);
295     }
296 
297     memcpy(client_ptr -> nx_smtp_username, username, str_length); /* Use case of memcpy is verified. */
298 
299     status = _nx_utility_string_length_check(password, &str_length, NX_SMTP_CLIENT_MAX_PASSWORD);
300     if (status)
301     {
302         return(status);
303     }
304 
305     memcpy(client_ptr -> nx_smtp_password, password, str_length); /* Use case of memcpy is verified. */
306 
307     status = _nx_utility_string_length_check(client_domain, &str_length, NX_SMTP_CLIENT_MAX_USERNAME);
308     if (status)
309     {
310         return(status);
311     }
312 
313     memcpy(client_ptr -> nx_smtp_client_domain, client_domain, str_length); /* Use case of memcpy is verified. */
314 
315     /* Set the mail server IP address and port number.  */
316 
317 #ifdef FEATURE_NX_IPV6
318     client_ptr -> nx_smtp_server_address.nxd_ip_version = server_address -> nxd_ip_version;
319     client_ptr -> nx_smtp_server_address.nxd_ip_address.v6[0] = server_address -> nxd_ip_address.v6[0] ;
320     client_ptr -> nx_smtp_server_address.nxd_ip_address.v6[1] = server_address -> nxd_ip_address.v6[1] ;
321     client_ptr -> nx_smtp_server_address.nxd_ip_address.v6[2] = server_address -> nxd_ip_address.v6[2] ;
322     client_ptr -> nx_smtp_server_address.nxd_ip_address.v6[3] = server_address -> nxd_ip_address.v6[3] ;
323 #else
324 
325     client_ptr -> nx_smtp_server_address.nxd_ip_version = server_address -> nxd_ip_version;
326     client_ptr -> nx_smtp_server_address.nxd_ip_address.v4 = server_address -> nxd_ip_address.v4;
327 #endif
328     client_ptr -> nx_smtp_server_port = (port & 0xFFFF);
329 
330     /* Set up the "from" address. */
331     mail_ptr -> nx_smtp_client_mail_from_address = from_address;
332 
333     /* Check if authentication type is specified. */
334     if ((authentication_type != NX_SMTP_CLIENT_AUTH_PLAIN) &&
335         (authentication_type != NX_SMTP_CLIENT_AUTH_LOGIN) &&
336         (authentication_type != NX_SMTP_CLIENT_AUTH_NONE))
337     {
338 
339         /* No. Set the default authentication type. */
340         authentication_type = NX_SMTP_CLIENT_AUTH_PLAIN;
341     }
342 
343     client_ptr -> nx_smtp_client_authentication_type = authentication_type;
344 
345     /* Configure client IP options.  */
346     client_ptr -> nx_smtp_client_ip_ptr   =  ip_ptr;
347     client_ptr -> nx_smtp_client_packet_pool_ptr =  client_packet_pool_ptr;
348 
349     /* Set the Client ID to indicate the SMTP client thread is ready.  */
350     client_ptr -> nx_smtp_client_id = NX_SMTP_CLIENT_ID;
351 
352     /* Create a tcp socket to send/receive SMTP data.  */
353     status =  nx_tcp_socket_create(client_ptr -> nx_smtp_client_ip_ptr,
354                                    &client_ptr -> nx_smtp_client_socket, "SMTP Client socket",
355                                    NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
356                                    NX_SMTP_CLIENT_TCP_WINDOW_SIZE,
357                                    NX_NULL, NX_NULL);
358 
359     /* Check for error.  */
360     if (status != NX_SUCCESS)
361     {
362 
363         /* Return error status.  */
364         return(status);
365     }
366 
367     /* Initialize client as ready for conducting an SMTP session. */
368     client_ptr -> nx_smtp_client_init_status = NX_TRUE;
369 
370     return(status);
371 }
372 
373 
374 /**************************************************************************/
375 /*                                                                        */
376 /*  FUNCTION                                               RELEASE        */
377 /*                                                                        */
378 /*    _nxe_smtp_client_delete                             PORTABLE C      */
379 /*                                                           6.1          */
380 /*  AUTHOR                                                                */
381 /*                                                                        */
382 /*    Yuxin Zhou, Microsoft Corporation                                   */
383 /*                                                                        */
384 /*  DESCRIPTION                                                           */
385 /*                                                                        */
386 /*    This function checks for errors on the client delete service.       */
387 /*                                                                        */
388 /*   INPUT                                                                */
389 /*                                                                        */
390 /*    client_ptr                         Pointer to client struct         */
391 /*                                                                        */
392 /*  OUTPUT                                                                */
393 /*                                                                        */
394 /*    NX_PTR_ERROR                       Invalid pointer parameter        */
395 /*    status                             Actual completion status         */
396 /*                                                                        */
397 /*  CALLS                                                                 */
398 /*                                                                        */
399 /*    _nx_smtp_client_delete            Actual SMTP client delete service */
400 /*                                                                        */
401 /*  CALLED BY                                                             */
402 /*                                                                        */
403 /*    Application Code                                                    */
404 /*                                                                        */
405 /*  RELEASE HISTORY                                                       */
406 /*                                                                        */
407 /*    DATE              NAME                      DESCRIPTION             */
408 /*                                                                        */
409 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
410 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
411 /*                                            resulting in version 6.1    */
412 /*                                                                        */
413 /**************************************************************************/
_nxe_smtp_client_delete(NX_SMTP_CLIENT * client_ptr)414 UINT  _nxe_smtp_client_delete(NX_SMTP_CLIENT *client_ptr)
415 {
416 
417 UINT status;
418 
419 
420     /* Check for the validity of input parameter.  */
421     if ((client_ptr == NX_NULL) || (client_ptr -> nx_smtp_client_id != NX_SMTP_CLIENT_ID))
422     {
423 
424         /* Return error status.  */
425         return(NX_PTR_ERROR);
426     }
427 
428     /* Call the actual client create service.  */
429     status =  _nx_smtp_client_delete(client_ptr);
430 
431     /* Return completion status.  */
432     return(status);
433 }
434 
435 
436 /**************************************************************************/
437 /*                                                                        */
438 /*  FUNCTION                                               RELEASE        */
439 /*                                                                        */
440 /*    _nx_smtp_client_delete                              PORTABLE C      */
441 /*                                                           6.1          */
442 /*  AUTHOR                                                                */
443 /*                                                                        */
444 /*    Yuxin Zhou, Microsoft Corporation                                   */
445 /*                                                                        */
446 /*  DESCRIPTION                                                           */
447 /*                                                                        */
448 /*    This function deletes a previously created SMTP client and releases */
449 /*    all client resources (sockets, packet pools).                       */
450 /*                                                                        */
451 /*   INPUT                                                                */
452 /*                                                                        */
453 /*    client_ptr                        Pointer to SMTP Client instance   */
454 /*                                                                        */
455 /*  OUTPUT                                                                */
456 /*                                                                        */
457 /*    NX_SUCCESS                        Successful completion status      */
458 /*    status                            Actual completion status          */
459 /*                                                                        */
460 /*  CALLS                                                                 */
461 /*                                                                        */
462 /*    _nx_smtp_session_delete           Delete the SMTP Client session    */
463 /*                                                                        */
464 /*  CALLED BY                                                             */
465 /*                                                                        */
466 /*    Application Code                                                    */
467 /*                                                                        */
468 /*  RELEASE HISTORY                                                       */
469 /*                                                                        */
470 /*    DATE              NAME                      DESCRIPTION             */
471 /*                                                                        */
472 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
473 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
474 /*                                            resulting in version 6.1    */
475 /*                                                                        */
476 /**************************************************************************/
_nx_smtp_client_delete(NX_SMTP_CLIENT * client_ptr)477 UINT  _nx_smtp_client_delete(NX_SMTP_CLIENT *client_ptr)
478 {
479 
480 UINT status;
481 
482 
483     if ((client_ptr  -> nx_smtp_client_socket).nx_tcp_socket_state == NX_TCP_ESTABLISHED)
484     {
485 
486         nx_tcp_socket_disconnect(&client_ptr -> nx_smtp_client_socket, NX_SMTP_CLIENT_DISCONNECT_TIMEOUT);
487 
488         nx_tcp_client_socket_unbind(&client_ptr -> nx_smtp_client_socket);
489     }
490 
491     status =  nx_tcp_socket_delete(&(client_ptr -> nx_smtp_client_socket));
492 
493     /* Check status.  */
494     if (status)
495     {
496         return status;
497     }
498 
499     /* Clear client memory. */
500     memset(client_ptr, 0, sizeof(NX_SMTP_CLIENT));
501 
502     /* Return success status.  */
503     return(NX_SUCCESS);
504 }
505 
506 
507 
508 /**************************************************************************/
509 /*                                                                        */
510 /*  FUNCTION                                               RELEASE        */
511 /*                                                                        */
512 /*    _nxe_smtp_mail_send                                 PORTABLE C      */
513 /*                                                           6.1          */
514 /*  AUTHOR                                                                */
515 /*                                                                        */
516 /*    Yuxin Zhou, Microsoft Corporation                                   */
517 /*                                                                        */
518 /*  DESCRIPTION                                                           */
519 /*                                                                        */
520 /*    This function checks for errors on the mail send service.           */
521 /*                                                                        */
522 /*    Note: The string lengths of recipient_address and subject are       */
523 /*    limited by internal buffer size.                                    */
524 /*                                                                        */
525 /*   INPUT                                                                */
526 /*                                                                        */
527 /*    client_ptr                      Pointer to Client instance          */
528 /*    recipient_address               Pointer to recipient (To) address   */
529 /*    priority                        Mail send priority level            */
530 /*    subject                         Pointer to mail subject text        */
531 /*    mail_body                       Pointer to mail message text        */
532 /*    mail_body_length                Size of mail message text           */
533 /*                                                                        */
534 /*  OUTPUT                                                                */
535 /*                                                                        */
536 /*    NX_PTR_ERROR                    Invalid pointer parameter           */
537 /*    status                          Actual completion status            */
538 /*                                                                        */
539 /*  CALLS                                                                 */
540 /*                                                                        */
541 /*    _nx_smtp_mail_send              Actual SMTP mail send service       */
542 /*                                                                        */
543 /*  CALLED BY                                                             */
544 /*                                                                        */
545 /*    Application Code                                                    */
546 /*                                                                        */
547 /*  RELEASE HISTORY                                                       */
548 /*                                                                        */
549 /*    DATE              NAME                      DESCRIPTION             */
550 /*                                                                        */
551 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
552 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
553 /*                                            resulting in version 6.1    */
554 /*                                                                        */
555 /**************************************************************************/
_nxe_smtp_mail_send(NX_SMTP_CLIENT * client_ptr,CHAR * recipient_address,UINT priority,CHAR * subject,CHAR * mail_body,UINT mail_body_length)556 UINT  _nxe_smtp_mail_send(NX_SMTP_CLIENT *client_ptr, CHAR *recipient_address, UINT priority,
557                           CHAR *subject, CHAR *mail_body, UINT mail_body_length)
558 {
559 
560 UINT  status;
561 
562 
563     /* Check for invalid pointer input. */
564     if((client_ptr == NX_NULL) || (recipient_address == NX_NULL) ||
565        (mail_body == NX_NULL) || (subject == NX_NULL))
566 
567     {
568         return NX_PTR_ERROR;
569     }
570 
571     if (mail_body_length == 0)
572     {
573         return NX_SMTP_INVALID_PARAM;
574     }
575 
576     /* Check if this function is called from the appropriate thread.  */
577     NX_THREADS_ONLY_CALLER_CHECKING
578 
579     status = _nx_smtp_mail_send(client_ptr, recipient_address,  priority,
580                                 subject, mail_body, mail_body_length);
581 
582     return status;
583 }
584 
585 /**************************************************************************/
586 /*                                                                        */
587 /*  FUNCTION                                               RELEASE        */
588 /*                                                                        */
589 /*    _nx_smtp_mail_send                                  PORTABLE C      */
590 /*                                                           6.1          */
591 /*  AUTHOR                                                                */
592 /*                                                                        */
593 /*    Yuxin Zhou, Microsoft Corporation                                   */
594 /*                                                                        */
595 /*  DESCRIPTION                                                           */
596 /*                                                                        */
597 /*    This function creates and sends an SMTP mail item with the input    */
598 /*    parameters for a previously created SMTP Client. It supports IPv4   */
599 /*    and IPv6 connections.                                               */
600 /*                                                                        */
601 /*    Before calling this service, the SMTP application must initialize   */
602 /*    the SMTP Client (nx_smtp_client_init). Thereafter it need not       */
603 /*    reinitialize the SMTP Client to send subsequent mail items.         */
604 /*                                                                        */
605 /*    This service assumes the syntax of the from_address is correct.     */
606 /*                                                                        */
607 /*    Note: The string lengths of recipient_address and subject are       */
608 /*    limited by internal buffer size.                                    */
609 /*                                                                        */
610 /*   INPUT                                                                */
611 /*                                                                        */
612 /*    client_ptr                      Pointer to Client instance          */
613 /*    recipient_address               Pointer to recipient (To) address   */
614 /*    priority                        Mail send priority level            */
615 /*    subject                         Pointer to mail subject text        */
616 /*    mail_body                       Pointer to mail message text        */
617 /*    mail_body_length                Size of mail message text           */
618 /*                                                                        */
619 /*  OUTPUT                                                                */
620 /*                                                                        */
621 /*    NX_SUCCESS                      Success completion status           */
622 /*    status                          Actual completion status            */
623 /*                                                                        */
624 /*  CALLS                                                                 */
625 /*                                                                        */
626 /*    memset                          Clear data in memory                */
627 /*    _nx_smtp_client_process         Conducts SMTP session for           */
628 /*                                      transmitting mail message         */
629 /*                                                                        */
630 /*  CALLED BY                                                             */
631 /*                                                                        */
632 /*    Application Code                                                    */
633 /*                                                                        */
634 /*  RELEASE HISTORY                                                       */
635 /*                                                                        */
636 /*    DATE              NAME                      DESCRIPTION             */
637 /*                                                                        */
638 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
639 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
640 /*                                            resulting in version 6.1    */
641 /*                                                                        */
642 /**************************************************************************/
_nx_smtp_mail_send(NX_SMTP_CLIENT * client_ptr,CHAR * recipient_address,UINT priority,CHAR * subject,CHAR * mail_body,UINT mail_body_length)643 UINT  _nx_smtp_mail_send(NX_SMTP_CLIENT *client_ptr,
644                          CHAR *recipient_address,
645                          UINT priority, CHAR *subject,
646                          CHAR *mail_body, UINT mail_body_length)
647 {
648 
649 UINT                        status;
650 NX_SMTP_CLIENT_MAIL         *mail_ptr;
651 
652 
653     client_ptr -> nx_smtp_client_mute = NX_FALSE;
654 
655     /* Verify Client is properly set up and ready to conduct an SMTP session. */
656     if (client_ptr -> nx_smtp_client_init_status != NX_TRUE)
657     {
658         return NX_SMTP_CLIENT_NOT_INTIALIZED;
659     }
660 
661     /* Initialize the Client to idle. */
662     client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_IDLE;
663     client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_IDLE;
664 
665 
666     /* Set local variables for convenience. */
667     mail_ptr = &client_ptr -> nx_smtp_client_mail;
668 
669     /* Did we get a valid priority type?  */
670     if ((priority != NX_SMTP_MAIL_PRIORITY_LOW)    &&
671         (priority != NX_SMTP_MAIL_PRIORITY_NORMAL) &&
672         (priority != NX_SMTP_MAIL_PRIORITY_HIGH))
673     {
674 
675         /* No, default priority to normal.  */
676         mail_ptr -> nx_smtp_client_mail_priority =  NX_SMTP_MAIL_PRIORITY_NORMAL;
677     }
678     else
679     {
680 
681         /* Yes, apply it to the session priority.  */
682         mail_ptr -> nx_smtp_client_mail_priority = priority;
683     }
684     mail_ptr -> nx_smtp_client_mail_subject = subject;
685     mail_ptr -> nx_smtp_client_mail_body = mail_body;
686     mail_ptr -> nx_smtp_client_mail_body_length = mail_body_length;
687     mail_ptr -> nx_smtp_client_mail_recipient_address = recipient_address;
688 
689     /* Mark mail item as unsent */
690     client_ptr -> nx_smtp_client_mail_status = NX_SUCCESS;
691 
692     /* Set up the recipient. */
693 
694     /* Set up a local pointer to the session for convenience. */
695 
696     /* Set session members to initial values.  */
697     client_ptr -> nx_smtp_client_authentication_state = NX_SMTP_NOT_AUTHENTICATED;
698     client_ptr -> nx_smtp_client_reply_code_status = 0;
699 
700     /* Start this session by setting the state  to the first step in SMTP Protocol, greeting.  */
701     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_GREETING;
702     client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_GREETING;
703 
704     status = _nx_smtp_client_process(client_ptr);
705 
706     /* Return success status.  */
707     return(status);
708 
709 }
710 
711 /**************************************************************************/
712 /*                                                                        */
713 /*  FUNCTION                                               RELEASE        */
714 /*                                                                        */
715 /*    _nx_smtp_client_process                             PORTABLE C      */
716 /*                                                           6.1          */
717 /*  AUTHOR                                                                */
718 /*                                                                        */
719 /*    Yuxin Zhou, Microsoft Corporation                                   */
720 /*                                                                        */
721 /*  DESCRIPTION                                                           */
722 /*                                                                        */
723 /*    This function executes the SMTP client state machine to transmit a  */
724 /*    previously created mail item to an SMTP server. For more details,   */
725 /*    See nx_smtp_mail_send.                                              */
726 /*                                                                        */
727 /*   INPUT                                                                */
728 /*                                                                        */
729 /*    client_ptr                      Pointer to SMTP Client instance     */
730 /*                                                                        */
731 /*  OUTPUT                                                                */
732 /*                                                                        */
733 /*    NX_SUCCESS                      Success completion status           */
734 /*    status                          Actual completion status            */
735 /*                                                                        */
736 /*  CALLS                                                                 */
737 /*    nx_tcp_client_socket_bind       Bind NetX TCP socket to local port  */
738 /*    nx_tcp_client_socket_unbind     Release port from NetX TCP socket   */
739 /*    nx_tcp_client_socket_connect    Connect to a TCP server socket      */
740 /*    nx_tcp_client_socket_disconnect Disconnect from TCP server socket   */
741 /*                                                                        */
742 /*  CALLED BY                                                             */
743 /*                                                                        */
744 /*    Application Code                                                    */
745 /*                                                                        */
746 /*  RELEASE HISTORY                                                       */
747 /*                                                                        */
748 /*    DATE              NAME                      DESCRIPTION             */
749 /*                                                                        */
750 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
751 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
752 /*                                            resulting in version 6.1    */
753 /*                                                                        */
754 /**************************************************************************/
_nx_smtp_client_process(NX_SMTP_CLIENT * client_ptr)755 static UINT _nx_smtp_client_process(NX_SMTP_CLIENT *client_ptr)
756 {
757 
758 UINT                    status;
759 UINT                    close_connection = NX_FALSE;
760 
761 
762     /* Initialize completion status to successful outcome. */
763     status = NX_SUCCESS;
764 
765     /* Run the SMTP protocol state machine till session terminates.  */
766     while (status == NX_SUCCESS)
767     {
768 
769         /* Check if we are starting a mail transaction. */
770         if (client_ptr -> nx_smtp_client_cmd_state == NX_SMTP_CLIENT_STATE_GREETING)
771         {
772 
773             /* We are so we need to set up a connection. Bind the socket to client port.  */
774             status =  nx_tcp_client_socket_bind(&client_ptr -> nx_smtp_client_socket, NX_ANY_PORT, 100);
775 
776             /* Check for error.  */
777             if (status != NX_SUCCESS)
778             {
779 
780                 /* Reset the Client to idle. The caller must resend the email. */
781                 client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_IDLE;
782                 client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_IDLE;
783 
784                 return status;
785             }
786 
787             /* Connect to the SMTP server using our tcp socket.  */
788             status =  nxd_tcp_client_socket_connect(&client_ptr -> nx_smtp_client_socket,
789                                                     &client_ptr -> nx_smtp_server_address,
790                                                     client_ptr -> nx_smtp_server_port,
791                                                     NX_SMTP_CLIENT_CONNECTION_TIMEOUT);
792 
793             /* Check for error.  */
794             if (status != NX_SUCCESS)
795             {
796 
797                 nx_tcp_client_socket_unbind(&client_ptr -> nx_smtp_client_socket);
798 
799                 /* Reset the Client to idle. The caller must resend the email.*/
800                 client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_IDLE;
801                 client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_IDLE;
802                 return status;
803             }
804 
805             /* Successful connection set up. Now let the Client task process the GREETING command. */
806         }
807 
808         /* Is the next command waiting the outcome of the previous reply handler?  */
809         if ((client_ptr -> nx_smtp_client_cmd_state == NX_SMTP_CLIENT_STATE_AWAITING_REPLY) &&
810             /* Do not advance the state if the client is in mute. */
811             (!client_ptr -> nx_smtp_client_mute))
812         {
813 
814             /* Yes, update the session state to the next command to send.  */
815             client_ptr -> nx_smtp_client_cmd_state =  client_ptr -> nx_smtp_client_rsp_state;
816         }
817 
818         if (!client_ptr -> nx_smtp_client_mute)
819         {
820 
821             /* Execute the next command in the SMTP state machine.  */
822             status =  (*protocol_states[client_ptr -> nx_smtp_client_cmd_state].cmd)(client_ptr);
823 
824             /* Check for internal error state in the SMTP state machine.  */
825             if (status != NX_SUCCESS)
826             {
827 
828                 /* This is likely an internal error and we need to break off the connection, reset the Client state
829                    to an idle state.  */
830 
831                 /* Set the status to close the connection down. */
832                 close_connection = NX_TRUE;
833             }
834         }
835 
836         /* Reset server reply to null. */
837         client_ptr -> nx_smtp_client_reply_code_status = 0;
838 
839         /* Wait for a response unless we are closing the connection, or have
840            encountered an internal error (packet allocation error for example). */
841         if (close_connection == NX_FALSE)
842         {
843 
844             /* Awaiting the server reply to the command just sent.  */
845             status = (*protocol_states[client_ptr -> nx_smtp_client_rsp_state].rsp)(client_ptr);
846 
847             /* Check for internal error state in the SMTP state machine.  */
848             if (status != NX_SUCCESS)
849             {
850 
851                 /* This is an internal error or invalid server reply of some kind. Just shut down the
852                    connection, notify the host application and set the Client to idle. */
853 
854                 /* Set the status to close the connection down. */
855                 close_connection = NX_TRUE;
856             }
857 
858             /* Are we at the end of the Client state (received a reply to our QUIT message to the server)? */
859             else if (client_ptr -> nx_smtp_client_rsp_state == NX_SMTP_CLIENT_STATE_COMPLETED_NORMALLY)
860             {
861 
862                 /* Yes, time to close it down and return to an idle state. */
863                 close_connection = NX_TRUE;
864             }
865             /* else keep the connection open... */
866         }
867 
868         /* Check again if we need to break down the connection. */
869         if (close_connection == NX_TRUE)
870         {
871 
872             UINT timeout = 0;
873 
874             /* We do. Depending on the reason for closing the connection, set the timeout. If we experienced
875                an internal error, e.g. packet allocation error, we probably won't be able to send
876                a fin or rst packet anyway, so set the timeout to zero and close down the connection.
877 
878                RFC 2821 Section 3.9: if client must abort processing due to internal conditions or socket reset,
879                it should handle as error code 451 from the server which is to abort processing immediately.
880              */
881             if (status != NX_SUCCESS)
882             {
883                 timeout = NX_NO_WAIT;
884             }
885             else
886             {
887                 timeout =  NX_SMTP_CLIENT_DISCONNECT_TIMEOUT;
888             }
889 
890             /* Disconnect client socket from server.  */
891             nx_tcp_socket_disconnect(&client_ptr -> nx_smtp_client_socket, timeout);
892 
893             /* Unbind the port from client socket.  */
894             nx_tcp_client_socket_unbind(&client_ptr -> nx_smtp_client_socket);
895 
896             /* Indicate the Client is idle. */
897             client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_IDLE;
898             client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_IDLE;
899 
900             /* Did the session terminate normally (e.g. no internal errors)? */
901             if (status == NX_SUCCESS)
902             {
903 
904                 /* Yes, so set the mail transmit status as the completion status. */
905                 status = client_ptr -> nx_smtp_client_mail_status;
906             }
907 
908             return status;
909         }
910 
911         /* Clear the abort status. */
912         close_connection = NX_FALSE;
913     }
914 
915     return status;
916 }
917 
918 
919 /**************************************************************************/
920 /*                                                                        */
921 /*  FUNCTION                                               RELEASE        */
922 /*                                                                        */
923 /*    _nx_smtp_cmd_greeting                               PORTABLE C      */
924 /*                                                           6.1          */
925 /*  AUTHOR                                                                */
926 /*                                                                        */
927 /*    Yuxin Zhou, Microsoft Corporation                                   */
928 /*                                                                        */
929 /*  DESCRIPTION                                                           */
930 /*                                                                        */
931 /*    This is the start of the SMTP Client process for sending an mail    */
932 /*    item. It sets the client state to send a greeting command to the    */
933 /*    server.                                                             */
934 /*                                                                        */
935 /*  INPUT                                                                 */
936 /*                                                                        */
937 /*    session_ptr                           SMTP Session for sending mail */
938 /*                                                                        */
939 /*  OUTPUT                                                                */
940 /*                                                                        */
941 /*    NX_SUCCESS                            Successful completion status  */
942 /*                                                                        */
943 /*  CALLS                                                                 */
944 /*                                                                        */
945 /*    None                                                                */
946 /*                                                                        */
947 /*  CALLED BY                                                             */
948 /*                                                                        */
949 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
950 /*                                                                        */
951 /*  RELEASE HISTORY                                                       */
952 /*                                                                        */
953 /*    DATE              NAME                      DESCRIPTION             */
954 /*                                                                        */
955 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
956 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
957 /*                                            resulting in version 6.1    */
958 /*                                                                        */
959 /**************************************************************************/
_nx_smtp_cmd_greeting(NX_SMTP_CLIENT * client_ptr)960 UINT  _nx_smtp_cmd_greeting(NX_SMTP_CLIENT *client_ptr)
961 {
962 
963 
964     /* Set session state to wait on the outcome of the greeting response handler.  */
965     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
966 
967     /* Return successful session status.  */
968     return(NX_SUCCESS);
969 }
970 
971 /**************************************************************************/
972 /*                                                                        */
973 /*  FUNCTION                                               RELEASE        */
974 /*                                                                        */
975 /*    _nx_smtp_cmd_idle                                   PORTABLE C      */
976 /*                                                           6.1          */
977 /*  AUTHOR                                                                */
978 /*                                                                        */
979 /*    Yuxin Zhou, Microsoft Corporation                                   */
980 /*                                                                        */
981 /*  DESCRIPTION                                                           */
982 /*                                                                        */
983 /*    Execute the idle state of the SMTP Client (do nothing while waiting */
984 /*    for the next send mail request.                                     */
985 /*                                                                        */
986 /*  INPUT                                                                 */
987 /*                                                                        */
988 /*    session_ptr                           SMTP Session for sending mail */
989 /*                                                                        */
990 /*  OUTPUT                                                                */
991 /*                                                                        */
992 /*    NX_SUCCESS                            Successful completion status  */
993 /*                                                                        */
994 /*  CALLS                                                                 */
995 /*                                                                        */
996 /*    None                                                                */
997 /*                                                                        */
998 /*  CALLED BY                                                             */
999 /*                                                                        */
1000 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
1001 /*                                                                        */
1002 /*  RELEASE HISTORY                                                       */
1003 /*                                                                        */
1004 /*    DATE              NAME                      DESCRIPTION             */
1005 /*                                                                        */
1006 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1007 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1008 /*                                            resulting in version 6.1    */
1009 /*                                                                        */
1010 /**************************************************************************/
_nx_smtp_cmd_idle(NX_SMTP_CLIENT * client_ptr)1011 UINT  _nx_smtp_cmd_idle(NX_SMTP_CLIENT *client_ptr)
1012 {
1013 
1014     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_IDLE;
1015 
1016     /* Return successful session status.  */
1017     return(NX_SUCCESS);
1018 }
1019 
1020 /**************************************************************************/
1021 /*                                                                        */
1022 /*  FUNCTION                                               RELEASE        */
1023 /*                                                                        */
1024 /*    _nx_smtp_rsp_idle                                   PORTABLE C      */
1025 /*                                                           6.1          */
1026 /*  AUTHOR                                                                */
1027 /*                                                                        */
1028 /*    Yuxin Zhou, Microsoft Corporation                                   */
1029 /*                                                                        */
1030 /*  DESCRIPTION                                                           */
1031 /*                                                                        */
1032 /*    Execute the idle state of the SMTP Client (waiting for the next     */
1033 /*    send mail request).  The state machine has a 'response' state for   */
1034 /*    every command state, so this is the response handler for the idle   */
1035 /*    state.                                                              */
1036 /*                                                                        */
1037 /*  INPUT                                                                 */
1038 /*                                                                        */
1039 /*    session_ptr                           SMTP Session for sending mail */
1040 /*                                                                        */
1041 /*  OUTPUT                                                                */
1042 /*                                                                        */
1043 /*    NX_SUCCESS                            Successful completion status  */
1044 /*                                                                        */
1045 /*  CALLS                                                                 */
1046 /*                                                                        */
1047 /*    None                                                                */
1048 /*                                                                        */
1049 /*  CALLED BY                                                             */
1050 /*                                                                        */
1051 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
1052 /*                                                                        */
1053 /*  RELEASE HISTORY                                                       */
1054 /*                                                                        */
1055 /*    DATE              NAME                      DESCRIPTION             */
1056 /*                                                                        */
1057 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1058 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1059 /*                                            resulting in version 6.1    */
1060 /*                                                                        */
1061 /**************************************************************************/
_nx_smtp_rsp_idle(NX_SMTP_CLIENT * client_ptr)1062 UINT  _nx_smtp_rsp_idle(NX_SMTP_CLIENT *client_ptr)
1063 {
1064 
1065     client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_IDLE;
1066 
1067     /* Return successful session status.  */
1068     return(NX_SUCCESS);
1069 }
1070 
1071 /**************************************************************************/
1072 /*                                                                        */
1073 /*  FUNCTION                                               RELEASE        */
1074 /*                                                                        */
1075 /*    _nx_smtp_rsp_greeting                               PORTABLE C      */
1076 /*                                                           6.1          */
1077 /*  AUTHOR                                                                */
1078 /*                                                                        */
1079 /*    Yuxin Zhou, Microsoft Corporation                                   */
1080 /*                                                                        */
1081 /*  DESCRIPTION                                                           */
1082 /*                                                                        */
1083 /*    This handles the server's response to the client greeting and set   */
1084 /*    the next session state and next command to send to the server.      */
1085 /*                                                                        */
1086 /*  INPUT                                                                 */
1087 /*                                                                        */
1088 /*    session_ptr                   Session to send mail to SMTP Server   */
1089 /*                                                                        */
1090 /*  OUTPUT                                                                */
1091 /*                                                                        */
1092 /*    NX_SUCCESS                    Successful completion status          */
1093 /*    status                        Actual completion status              */
1094 /*                                                                        */
1095 /*  CALLS                                                                 */
1096 /*                                                                        */
1097 /*    _nx_smtp_utility_read_server_code                                   */
1098 /*                                  Extracts the server reply code and    */
1099 /*                                  stores reply text to session buffer   */
1100 /*                                                                        */
1101 /*  CALLED BY                                                             */
1102 /*                                                                        */
1103 /*    _nx_smtp_client_process        Runs the SMTP state machine          */
1104 /*                                                                        */
1105 /*  RELEASE HISTORY                                                       */
1106 /*                                                                        */
1107 /*    DATE              NAME                      DESCRIPTION             */
1108 /*                                                                        */
1109 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1110 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1111 /*                                            resulting in version 6.1    */
1112 /*                                                                        */
1113 /**************************************************************************/
_nx_smtp_rsp_greeting(NX_SMTP_CLIENT * client_ptr)1114 UINT  _nx_smtp_rsp_greeting(NX_SMTP_CLIENT *client_ptr)
1115 {
1116 
1117 UINT     status;
1118 
1119 
1120     /* Get the server greeting message.  */
1121     status = _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_GREETING_TIMEOUT, NX_TRUE);
1122 
1123     /* Check for error.  */
1124     if (status != NX_SUCCESS)
1125     {
1126 
1127         /* Return error status.  */
1128         return (status);
1129     }
1130 
1131     /* Process based on the reply protocol code from server.  */
1132     if (client_ptr -> nx_smtp_client_reply_code_status == NX_SMTP_CODE_GREETING_OK)
1133     {
1134 
1135         /* Yes, set session state to next state, EHLO.  */
1136         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_EHLO;
1137     }
1138     else
1139     {
1140 
1141         /* All other codes.  */
1142 
1143         /* Server did not accept the greeting, exit session gracefully.  */
1144         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_QUIT;
1145 
1146         /* Indicate mail cannot be sent. */
1147         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_GREET_REPLY_ERROR;
1148 
1149 
1150     }
1151 
1152     if (client_ptr -> nx_smtp_server_packet)
1153     {
1154         nx_packet_release(client_ptr -> nx_smtp_server_packet);
1155     }
1156     /* Return successful session state.  */
1157     return(NX_SUCCESS);
1158 }
1159 
1160 
1161 /**************************************************************************/
1162 /*                                                                        */
1163 /*  FUNCTION                                               RELEASE        */
1164 /*                                                                        */
1165 /*    _nx_smtp_cmd_helo                                   PORTABLE C      */
1166 /*                                                           6.1          */
1167 /*  AUTHOR                                                                */
1168 /*                                                                        */
1169 /*    Yuxin Zhou, Microsoft Corporation                                   */
1170 /*                                                                        */
1171 /*  DESCRIPTION                                                           */
1172 /*                                                                        */
1173 /*    Create the HELO command text and send to the SMTP server.           */
1174 /*                                                                        */
1175 /*  INPUT                                                                 */
1176 /*                                                                        */
1177 /*    session_ptr                           SMTP Session for sending mail */
1178 /*                                                                        */
1179 /*  OUTPUT                                                                */
1180 /*                                                                        */
1181 /*    NX_SUCCESS                            Successful completion status  */
1182 /*    status                                Actual completion status.     */
1183 /*                                                                        */
1184 /*  CALLS                                                                 */
1185 /*                                                                        */
1186 /*    _nx_smtp_utility_send_to_server       Sends data to server          */
1187 /*    memcpy                                Copy data to area of memory   */
1188 /*                                                                        */
1189 /*  CALLED BY                                                             */
1190 /*                                                                        */
1191 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
1192 /*                                                                        */
1193 /*  RELEASE HISTORY                                                       */
1194 /*                                                                        */
1195 /*    DATE              NAME                      DESCRIPTION             */
1196 /*                                                                        */
1197 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1198 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
1199 /*                                            verified memcpy use cases,  */
1200 /*                                            resulting in version 6.1    */
1201 /*                                                                        */
1202 /**************************************************************************/
_nx_smtp_cmd_helo(NX_SMTP_CLIENT * client_ptr)1203 UINT  _nx_smtp_cmd_helo(NX_SMTP_CLIENT *client_ptr)
1204 {
1205 
1206 UINT     status;
1207 UINT     index;
1208 UINT     domain_length;
1209 
1210 
1211     memset(&_nx_smtp_buffer[0], 0, NX_SMTP_BUFFER_SIZE);
1212 
1213     if (_nx_utility_string_length_check(client_ptr -> nx_smtp_client_domain, &domain_length, NX_SMTP_CLIENT_MAX_USERNAME))
1214     {
1215         return(NX_SIZE_ERROR);
1216     }
1217 
1218     if (NX_SMTP_BUFFER_SIZE < (sizeof(NX_SMTP_COMMAND_HELO) + domain_length + sizeof(NX_SMTP_LINE_TERMINATOR) - 1))
1219     {
1220 
1221         /* Buffer size too small. */
1222         return(NX_SMTP_INTERNAL_ERROR);
1223     }
1224 
1225     /* Format the HELO command.  */
1226     memcpy(&_nx_smtp_buffer[0], NX_SMTP_COMMAND_HELO, sizeof(NX_SMTP_COMMAND_HELO) - 1); /* Use case of memcpy is verified. */
1227     index = sizeof(NX_SMTP_COMMAND_HELO) - 1;
1228 
1229     _nx_smtp_buffer[index++] = ' ';
1230 
1231     memcpy(&_nx_smtp_buffer[index],  client_ptr -> nx_smtp_client_domain, domain_length); /* Use case of memcpy is verified. */
1232     index += domain_length;
1233     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
1234     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
1235 
1236     /* Send the HELO command.  */
1237     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
1238 
1239     /* Check for error.  */
1240     if (status != NX_SUCCESS)
1241     {
1242 
1243         return status;
1244     }
1245 
1246     /* Set session state to wait next response from server.  */
1247     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
1248 
1249     /* Return normal session status.  */
1250     return NX_SUCCESS;
1251 }
1252 
1253 
1254 /**************************************************************************/
1255 /*                                                                        */
1256 /*  FUNCTION                                               RELEASE        */
1257 /*                                                                        */
1258 /*    _nx_smtp_rsp_helo                                   PORTABLE C      */
1259 /*                                                           6.1          */
1260 /*  AUTHOR                                                                */
1261 /*                                                                        */
1262 /*    Yuxin Zhou, Microsoft Corporation                                   */
1263 /*                                                                        */
1264 /*  DESCRIPTION                                                           */
1265 /*                                                                        */
1266 /*    This function handles the server reply to the HELO command and set  */
1267 /*    the next session state and next command to send to the server.  This*/
1268 /*    is the GREETING state where we do not initiate the greeting.        */
1269 /*    Instead we wait for the server's 'greeting' message.                */
1270 /*                                                                        */
1271 /*  INPUT                                                                 */
1272 /*                                                                        */
1273 /*    session_ptr                   Session to send mail to SMTP Server   */
1274 /*                                                                        */
1275 /*  OUTPUT                                                                */
1276 /*                                                                        */
1277 /*    NX_SUCCESS                    Successful completion status          */
1278 /*    status                        Actual completion status              */
1279 /*                                                                        */
1280 /*  CALLS                                                                 */
1281 /*    _nx_smtp_parse_response       Parse specified argument from buffer  */
1282 /*    _nx_smtp_rsp_hello_command    Handle HELO/EHLO reply from Server    */
1283 /*    nx_packet_release             Release NetX receive packet           */
1284 /*    memset                        Clear specified area of memory        */
1285 /*                                                                        */
1286 /*  CALLED BY                                                             */
1287 /*                                                                        */
1288 /*    _nx_smtp_client_process       Runs the SMTP state machine           */
1289 /*                                                                        */
1290 /*  RELEASE HISTORY                                                       */
1291 /*                                                                        */
1292 /*    DATE              NAME                      DESCRIPTION             */
1293 /*                                                                        */
1294 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1295 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1296 /*                                            resulting in version 6.1    */
1297 /*                                                                        */
1298 /**************************************************************************/
_nx_smtp_rsp_helo(NX_SMTP_CLIENT * client_ptr)1299 UINT  _nx_smtp_rsp_helo(NX_SMTP_CLIENT *client_ptr)
1300 {
1301 
1302 UINT        status;
1303 
1304     /* Get the server response to the EHLO command.  */
1305     status = _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
1306 
1307     /* Check for error.  */
1308     if (status != NX_SUCCESS)
1309     {
1310 
1311         /* This is either no packet received or an invalid server response.  */
1312 
1313         /* Return error status.  */
1314         return status;
1315     }
1316 
1317     /* Update session with specific services offered, if any, by server.  */
1318     _nx_smtp_utility_parse_server_services(client_ptr);
1319 
1320     /* We are done with the packet now. */
1321     nx_packet_release(client_ptr -> nx_smtp_server_packet);
1322 
1323         /* if server rejected hello, set the session state to terminate */
1324     if (client_ptr -> nx_smtp_client_rsp_state == NX_SMTP_CLIENT_STATE_QUIT)
1325     {
1326 
1327         /* Return successful session status to execute QUIT command.  */
1328         return NX_SUCCESS;
1329     }
1330 
1331     /* Handle the server reply code first.  */
1332     _nx_smtp_rsp_hello_command(client_ptr);
1333 
1334     /* if server rejected hello, set the session state to terminate */
1335     if (client_ptr -> nx_smtp_client_rsp_state == NX_SMTP_CLIENT_STATE_QUIT)
1336     {
1337 
1338         /* Return successful session status to execute QUIT command.  */
1339         return NX_SUCCESS;
1340     }
1341 
1342     /* Server accepted the HELO command. Continue the SMTP session.  */
1343 
1344     /* Return successful completion status.  */
1345     return NX_SUCCESS;
1346 }
1347 
1348 
1349 /**************************************************************************/
1350 /*                                                                        */
1351 /*  FUNCTION                                               RELEASE        */
1352 /*                                                                        */
1353 /*    _nx_smtp_cmd_ehlo                                   PORTABLE C      */
1354 /*                                                           6.1          */
1355 /*  AUTHOR                                                                */
1356 /*                                                                        */
1357 /*    Yuxin Zhou, Microsoft Corporation                                   */
1358 /*                                                                        */
1359 /*  DESCRIPTION                                                           */
1360 /*                                                                        */
1361 /*    This function creates the EHLO command and sends it to the server.  */
1362 /*                                                                        */
1363 /*  INPUT                                                                 */
1364 /*                                                                        */
1365 /*    session_ptr                           SMTP Session for sending mail */
1366 /*                                                                        */
1367 /*  OUTPUT                                                                */
1368 /*                                                                        */
1369 /*    NX_SUCCESS                            Successful completion status  */
1370 /*    status                                Actual completion status      */
1371 /*                                                                        */
1372 /*  CALLS                                                                 */
1373 /*                                                                        */
1374 /*    _nx_smtp_utility_send_to_server       Send data to server           */
1375 /*    memcpy                                Copy data to area of memory   */
1376 /*                                                                        */
1377 /*  CALLED BY                                                             */
1378 /*                                                                        */
1379 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
1380 /*                                                                        */
1381 /*  RELEASE HISTORY                                                       */
1382 /*                                                                        */
1383 /*    DATE              NAME                      DESCRIPTION             */
1384 /*                                                                        */
1385 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1386 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
1387 /*                                            verified memcpy use cases,  */
1388 /*                                            resulting in version 6.1    */
1389 /*                                                                        */
1390 /**************************************************************************/
_nx_smtp_cmd_ehlo(NX_SMTP_CLIENT * client_ptr)1391 UINT  _nx_smtp_cmd_ehlo(NX_SMTP_CLIENT *client_ptr)
1392 {
1393 
1394 UINT     status;
1395 UINT     index;
1396 UINT     domain_length;
1397 
1398 
1399     memset(&_nx_smtp_buffer[0], 0, NX_SMTP_BUFFER_SIZE);
1400 
1401     if (_nx_utility_string_length_check(client_ptr -> nx_smtp_client_domain, &domain_length, NX_SMTP_CLIENT_MAX_USERNAME))
1402     {
1403         return(NX_SIZE_ERROR);
1404     }
1405 
1406     if (NX_SMTP_BUFFER_SIZE < (sizeof(NX_SMTP_COMMAND_EHLO) + domain_length + sizeof(NX_SMTP_LINE_TERMINATOR) - 1))
1407     {
1408 
1409         /* Buffer size too small. */
1410         return(NX_SMTP_INTERNAL_ERROR);
1411     }
1412 
1413     /* Format the EHLO command.  */
1414     memcpy(&_nx_smtp_buffer[0],  NX_SMTP_COMMAND_EHLO, sizeof(NX_SMTP_COMMAND_EHLO) - 1); /* Use case of memcpy is verified. */
1415     index = sizeof(NX_SMTP_COMMAND_EHLO) - 1;
1416 
1417     _nx_smtp_buffer[index++] = ' ';
1418     memcpy(&_nx_smtp_buffer[index],  client_ptr -> nx_smtp_client_domain, domain_length); /* Use case of memcpy is verified. */
1419     index += domain_length;
1420     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
1421     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
1422 
1423     /* Send the EHLO command.  */
1424     status = _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
1425 
1426     /* Check for error.  */
1427     if (status != NX_SUCCESS)
1428     {
1429 
1430         return status;
1431     }
1432 
1433     /* Set session state to wait on the outcome of the EHLO response handler.  */
1434     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
1435 
1436     /* Return normal session status.  */
1437     return NX_SUCCESS;
1438 }
1439 
1440 
1441 
1442 /**************************************************************************/
1443 /*                                                                        */
1444 /*  FUNCTION                                               RELEASE        */
1445 /*                                                                        */
1446 /*    _nx_smtp_rsp_ehlo                                   PORTABLE C      */
1447 /*                                                           6.1          */
1448 /*  AUTHOR                                                                */
1449 /*                                                                        */
1450 /*    Yuxin Zhou, Microsoft Corporation                                   */
1451 /*                                                                        */
1452 /*  DESCRIPTION                                                           */
1453 /*                                                                        */
1454 /*    This handles the server reply to the EHLO command and determines the*/
1455 /*    next session state and next command to send to the server.          */
1456 /*                                                                        */
1457 /*  INPUT                                                                 */
1458 /*                                                                        */
1459 /*    session_ptr                           SMTP Session for sending mail */
1460 /*                                                                        */
1461 /*  OUTPUT                                                                */
1462 /*                                                                        */
1463 /*    NX_SUCCESS                            Successful completion status  */
1464 /*    status                                Actual completion status      */
1465 /*                                                                        */
1466 /*  CALLS                                                                 */
1467 /*                                                                        */
1468 /*   _nx_smtp_utility_parse_server_services  Parser for extracting server */
1469 /*                                                services and reply code */
1470 /*   _nx_smtp_utility_read_server_code       Parse the server replies     */
1471 /*                                                code and text           */
1472 /*   _nx_smtp_rsp_hello_command              Server HELO/EHLO reply       */
1473 /*                                                handler                 */
1474 /*                                                                        */
1475 /*  CALLED BY                                                             */
1476 /*                                                                        */
1477 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
1478 /*                                                                        */
1479 /*  RELEASE HISTORY                                                       */
1480 /*                                                                        */
1481 /*    DATE              NAME                      DESCRIPTION             */
1482 /*                                                                        */
1483 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1484 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1485 /*                                            resulting in version 6.1    */
1486 /*                                                                        */
1487 /**************************************************************************/
_nx_smtp_rsp_ehlo(NX_SMTP_CLIENT * client_ptr)1488 UINT  _nx_smtp_rsp_ehlo(NX_SMTP_CLIENT *client_ptr)
1489 {
1490 
1491 UINT            status;
1492 
1493 
1494     /* Get the server response to the EHLO command.  */
1495     status = _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
1496 
1497     /* Check for error.  */
1498     if (status != NX_SUCCESS)
1499     {
1500 
1501         /* This is either no packet received or an invalid server response.  */
1502 
1503         /* Return error status.  */
1504         return status;
1505     }
1506 
1507     /* Update session with specific services offered, if any, by server.  */
1508     _nx_smtp_utility_parse_server_services(client_ptr);
1509 
1510     /* We are done with the packet now. */
1511     nx_packet_release(client_ptr -> nx_smtp_server_packet);
1512 
1513     if (client_ptr -> nx_smtp_client_mute)
1514     {
1515         /* We expect another response packet from the server...
1516            keep the same state, don't send anything. */
1517         return NX_SUCCESS;
1518     }
1519 
1520     /* Handle the server reply code first.  */
1521     _nx_smtp_rsp_hello_command(client_ptr);
1522 
1523     /* if server rejected hello, set the session state to terminate */
1524     if (client_ptr -> nx_smtp_client_rsp_state == NX_SMTP_CLIENT_STATE_QUIT)
1525     {
1526 
1527         /* Return successful session status to execute QUIT command.  */
1528         return NX_SUCCESS;
1529     }
1530 
1531     /* Determine if we go to authenticatio next (otherwise we go to the MAIL state).   */
1532     if (client_ptr -> nx_smtp_client_authentication_type != NX_SMTP_CLIENT_AUTH_NONE)
1533     {
1534 
1535         /* Yes, set session to the AUTH state before going on to MAIL.  */
1536         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_AUTH;
1537     }
1538 
1539     /* Return successful completion status.  */
1540     return NX_SUCCESS;
1541 }
1542 
1543 
1544 /**************************************************************************/
1545 /*                                                                        */
1546 /*  FUNCTION                                               RELEASE        */
1547 /*                                                                        */
1548 /*    _nx_smtp_rsp_hello_command                          PORTABLE C      */
1549 /*                                                           6.1          */
1550 /*  AUTHOR                                                                */
1551 /*                                                                        */
1552 /*    Yuxin Zhou, Microsoft Corporation                                   */
1553 /*                                                                        */
1554 /*  DESCRIPTION                                                           */
1555 /*                                                                        */
1556 /*    This function handles the server response to HELO and EHLO commands */
1557 /*    common to both command states.  If server accepts the EHLO/HELO     */
1558 /*    command, proceed with the session                                   */
1559 /*                                                                        */
1560 /*   INPUT                                                                */
1561 /*                                                                        */
1562 /*    session_ptr                   Session to send mail to SMTP Server   */
1563 /*                                                                        */
1564 /*  OUTPUT                                                                */
1565 /*                                                                        */
1566 /*    NX_SUCCESS                    Successful completion status          */
1567 /*                                                                        */
1568 /*  CALLS                                                                 */
1569 /*                                                                        */
1570 /*    None                                                                */
1571 /*                                                                        */
1572 /*  CALLED BY                                                             */
1573 /*                                  Session server EHLO reply handler     */
1574 /*    _nx_smtp_rsp_ehlo             Session server HELO reply handler     */
1575 /*    _nx_smtp_rsp_helo                                                   */
1576 /*                                                                        */
1577 /*  RELEASE HISTORY                                                       */
1578 /*                                                                        */
1579 /*    DATE              NAME                      DESCRIPTION             */
1580 /*                                                                        */
1581 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1582 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1583 /*                                            resulting in version 6.1    */
1584 /*                                                                        */
1585 /**************************************************************************/
_nx_smtp_rsp_hello_command(NX_SMTP_CLIENT * client_ptr)1586 UINT  _nx_smtp_rsp_hello_command(NX_SMTP_CLIENT* client_ptr)
1587 {
1588 
1589 UINT     first_digit_server_reply;
1590 
1591     first_digit_server_reply = client_ptr -> nx_smtp_client_reply_code_status/ 100;
1592 
1593     /* Process the server reply starting with the first digit.  */
1594     if (first_digit_server_reply == 2)
1595     {
1596 
1597 
1598         /* Did server accept the EHLO/HELO command?  */
1599         if (client_ptr -> nx_smtp_client_reply_code_status == NX_SMTP_CODE_OK_TO_CONTINUE)
1600         {
1601 
1602             /* Set session to the next state (MAIL).  */
1603             client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_MAIL;
1604 
1605             /* Return successful session status.  */
1606             return NX_SUCCESS;
1607         }
1608     }
1609 
1610     /* If we are here, an error occurred. Indicate mail cannot be sent. */
1611     client_ptr -> nx_smtp_client_mail_status = NX_SMTP_HELLO_REPLY_ERROR;
1612 
1613     /* Set session state to QUIT.  */
1614     client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_QUIT;
1615 
1616     /* Return successful session status.  */
1617     return NX_SUCCESS;
1618 }
1619 
1620 
1621 
1622 /**************************************************************************/
1623 /*                                                                        */
1624 /*  FUNCTION                                               RELEASE        */
1625 /*                                                                        */
1626 /*    _nx_smtp_cmd_auth                                   PORTABLE C      */
1627 /*                                                           6.1          */
1628 /*  AUTHOR                                                                */
1629 /*                                                                        */
1630 /*    Yuxin Zhou, Microsoft Corporation                                   */
1631 /*                                                                        */
1632 /*  DESCRIPTION                                                           */
1633 /*                                                                        */
1634 /*    This function creates the text of the SMTP AUTH command text and    */
1635 /*    sends it to the SMTP server. If the session is already              */
1636 /*    authenticated, this function proceeds to the MAIL state (next stage */
1637 /*    of the SMTP protocol) instead.                                      */
1638 /*                                                                        */
1639 /*  INPUT                                                                 */
1640 /*                                                                        */
1641 /*    session_ptr                   Session to send mail to SMTP Server   */
1642 /*                                                                        */
1643 /*  OUTPUT                                                                */
1644 /*                                                                        */
1645 /*    NX_SUCCESS                            Successful completion status  */
1646 /*    status                                Actual completion status      */
1647 /*                                                                        */
1648 /*  CALLS                                                                 */
1649 /*                                                                        */
1650 /*    _nx_smtp_cmd_mail                     Send MAIL command to server   */
1651 /*    _nx_smtp_utility_send_to_server       Send data to server           */
1652 /*    memset                                Clear area of memory          */
1653 /*    memcpy                                Copy data to area of memory   */
1654 /*                                                                        */
1655 /*  CALLED BY                                                             */
1656 /*                                                                        */
1657 /*    _nx_smtp_client_process               Runs the SMTP session         */
1658 /*                                                                        */
1659 /*  RELEASE HISTORY                                                       */
1660 /*                                                                        */
1661 /*    DATE              NAME                      DESCRIPTION             */
1662 /*                                                                        */
1663 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1664 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
1665 /*                                            verified memcpy use cases,  */
1666 /*                                            resulting in version 6.1    */
1667 /*                                                                        */
1668 /**************************************************************************/
_nx_smtp_cmd_auth(NX_SMTP_CLIENT * client_ptr)1669 UINT  _nx_smtp_cmd_auth(NX_SMTP_CLIENT *client_ptr)
1670 {
1671 
1672 UINT            status = NX_SUCCESS;
1673 UINT            index;
1674 
1675     memset(&_nx_smtp_buffer[0], 0, NX_SMTP_BUFFER_SIZE);
1676 
1677     /* Is session already successfully authenticated?  */
1678     if (client_ptr -> nx_smtp_client_authentication_state == NX_SMTP_AUTHENTICATION_SUCCEEDED)
1679     {
1680 
1681         /* Yes, server will reject any authentication command; skip to MAIL state.  */
1682         client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_MAIL;
1683         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_MAIL;
1684 
1685         /* Call the session MAIL service.  */
1686         _nx_smtp_cmd_mail(client_ptr);
1687 
1688         /* Return successful session status.  */
1689         return NX_SUCCESS;
1690     }
1691 
1692     /* Mark the session authentication as in progress.  */
1693     client_ptr -> nx_smtp_client_authentication_state = NX_SMTP_AUTHENTICATION_IN_PROGRESS;
1694 
1695     /* Set the authentication prompt depending on the Client authentication type. */
1696     if (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_LOGIN)
1697     {
1698 
1699         memcpy(&_nx_smtp_buffer[0],  NX_SMTP_CLIENT_AUTH_LOGIN_TEXT, sizeof(NX_SMTP_CLIENT_AUTH_LOGIN_TEXT) - 1); /* Use case of memcpy is verified. */
1700         index = sizeof(NX_SMTP_CLIENT_AUTH_LOGIN_TEXT) - 1;
1701     }
1702     else if (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_CRAM_MD5)
1703     {
1704 
1705         memcpy(&_nx_smtp_buffer[0],  NX_SMTP_CLIENT_AUTH_CRAM_MD5_TEXT, sizeof(NX_SMTP_CLIENT_AUTH_CRAM_MD5_TEXT) - 1); /* Use case of memcpy is verified. */
1706         index = sizeof(NX_SMTP_CLIENT_AUTH_CRAM_MD5_TEXT) - 1;
1707     }
1708     else
1709     {
1710 
1711         memcpy(&_nx_smtp_buffer[0],  NX_SMTP_CLIENT_AUTH_PLAIN_TEXT, sizeof(NX_SMTP_CLIENT_AUTH_PLAIN_TEXT) - 1); /* Use case of memcpy is verified. */
1712         index = sizeof(NX_SMTP_CLIENT_AUTH_PLAIN_TEXT) - 1;
1713     }
1714 
1715     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
1716     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
1717 
1718     /* Send the AUTH command to the server.  */
1719     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
1720 
1721     /* Check for error.  */
1722     if (status != NX_SUCCESS)
1723     {
1724 
1725         return status;
1726     }
1727 
1728     /* Set session state to wait on the outcome of the EHLO response handler.  */
1729     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
1730 
1731     /* Return normal session status.  */
1732     return NX_SUCCESS;
1733 }
1734 
1735 
1736 /**************************************************************************/
1737 /*                                                                        */
1738 /*  FUNCTION                                               RELEASE        */
1739 /*                                                                        */
1740 /*    _nx_smtp_rsp_auth                                   PORTABLE C      */
1741 /*                                                           6.1.5        */
1742 /*  AUTHOR                                                                */
1743 /*                                                                        */
1744 /*    Yuxin Zhou, Microsoft Corporation                                   */
1745 /*                                                                        */
1746 /*  DESCRIPTION                                                           */
1747 /*                                                                        */
1748 /*    This function handles the server reply to the AUTH command and set  */
1749 /*    determine the next session state and next command to send to the    */
1750 /*    server.                                                             */
1751 /*                                                                        */
1752 /*    During the authentication process, it attempts to find a match for  */
1753 /*    the server authentication type and decodes each server              */
1754 /*    authentication challenge (e.g. USERNAME, PASSWORD). It then sets the*/
1755 /*    session authentication state depending on server acceptance of its  */
1756 /*    replies to its challenges.                                          */
1757 /*                                                                        */
1758 /*  INPUT                                                                 */
1759 /*                                                                        */
1760 /*    session_ptr                           SMTP Session for sending mail */
1761 /*                                                                        */
1762 /*  OUTPUT                                                                */
1763 /*                                                                        */
1764 /*    NX_SUCCESS                           Successful completion status   */
1765 /*    status                               Actual completion status       */
1766 /*                                                                        */
1767 /*  CALLS                                                                 */
1768 /*                                                                        */
1769 /*    _nx_smtp_utility_read_server_code     Parser for server reply       */
1770 /*    _nx_smtp_utility_authentication_challenge                           */
1771 /*                                          Respond to server             */
1772 /*                                                authentication challenge*/
1773 /*    _nx_smtp_rsp_auth                     When called by itself,respond */
1774 /*                                               to server authentication */
1775 /*                                               challenge                */
1776 /*    _nx_smtp_utility_send_to_server       Send data to server           */
1777 /*    nx_packet_release                     Release NetX receive packet   */
1778 /*                                                                        */
1779 /*  CALLED BY                                                             */
1780 /*                                                                        */
1781 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
1782 /*                                                                        */
1783 /*  RELEASE HISTORY                                                       */
1784 /*                                                                        */
1785 /*    DATE              NAME                      DESCRIPTION             */
1786 /*                                                                        */
1787 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1788 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1789 /*                                            resulting in version 6.1    */
1790 /*  03-02-2021     Yuxin Zhou               Modified comment(s),          */
1791 /*                                            fixed compiler warnings,    */
1792 /*                                            resulting in version 6.1.5  */
1793 /*                                                                        */
1794 /**************************************************************************/
_nx_smtp_rsp_auth(NX_SMTP_CLIENT * client_ptr)1795 UINT  _nx_smtp_rsp_auth(NX_SMTP_CLIENT *client_ptr)
1796 {
1797 
1798 UINT        status;
1799 UINT        server_reply_first_digit;
1800 UCHAR       *carriage_return_linefeed_ptr = NX_NULL;
1801 UINT        auth_length;
1802 
1803 
1804     /* Get the server response to the AUTH command.  */
1805     status   =  _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
1806 
1807     /* Check for error.  */
1808     if (status != NX_SUCCESS)
1809     {
1810 
1811         /* This is an server response or no packet received.  */
1812 
1813         /* Return error status.  */
1814         return(status);
1815     }
1816 
1817     /* Use the first digit to group possible server replies.  */
1818     server_reply_first_digit = client_ptr -> nx_smtp_client_reply_code_status / 100;
1819 
1820     /* Process the reply code from server.  */
1821     if (server_reply_first_digit == 2)
1822     {
1823 
1824         if (client_ptr -> nx_smtp_client_reply_code_status == NX_SMTP_CODE_AUTHENTICATION_SUCCESSFUL)
1825         {
1826 
1827             /* Advance to the MAIL state.  */
1828             client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_MAIL;
1829 
1830             /* Mark the session as authenticated successfully.  */
1831             client_ptr -> nx_smtp_client_authentication_state = NX_SMTP_AUTHENTICATION_SUCCEEDED;
1832         }
1833         else
1834         {
1835 
1836             /* The server returns a 2xx code. Determine if it is an error code. */
1837             if ((client_ptr -> nx_smtp_client_reply_code_status == NX_SMTP_CODE_CANNOT_VERIFY_RECIPIENT) ||
1838                 (client_ptr -> nx_smtp_client_reply_code_status == NX_SMTP_CODE_ACKNOWLEDGE_QUIT))
1839             {
1840 
1841                 /* It is. Abort. */
1842                 client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
1843 
1844                 /* Indicate mail cannot be sent. */
1845                 client_ptr -> nx_smtp_client_mail_status = NX_SMTP_AUTH_REPLY_ERROR;
1846             }
1847             else
1848             {
1849                 /* It is not the code expected. Discard and keep the SMTP Client in the same state. */
1850             }
1851 
1852             /* We are done with the packet now. */
1853             nx_packet_release(client_ptr -> nx_smtp_server_packet);
1854 
1855             return NX_SUCCESS;
1856         }
1857      }
1858      else if (server_reply_first_digit == 3)
1859      {
1860 
1861         /* Check if the server accepted our authentication type. */
1862         if (client_ptr -> nx_smtp_client_reply_code_status != NX_SMTP_CODE_AUTHENTICATION_TYPE_ACCEPTED)
1863         {
1864 
1865             /* It did not.  Or we may be out of synch with the SMTP Server, if we get a
1866                354 message for example. Abort the mail session. */
1867             client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
1868 
1869             /* Indicate mail cannot be sent. */
1870             client_ptr -> nx_smtp_client_mail_status = NX_SMTP_AUTH_REPLY_ERROR;
1871 
1872             /* We are done with the packet now. */
1873             nx_packet_release(client_ptr -> nx_smtp_server_packet);
1874 
1875             return NX_SUCCESS;
1876         }
1877         /* Authentication in progress.  */
1878 
1879      }
1880      else
1881      {
1882 
1883         /* Set session to the QUIT state.  */
1884         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
1885 
1886         /* Indicate mail cannot be sent. */
1887         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_AUTH_REPLY_ERROR;
1888 
1889         /* We are done with the packet now. */
1890         nx_packet_release(client_ptr -> nx_smtp_server_packet);
1891 
1892         return NX_SUCCESS;
1893     }
1894 
1895     /* Is authentication in progress?  */
1896     if (client_ptr -> nx_smtp_client_authentication_state != NX_SMTP_AUTHENTICATION_SUCCEEDED)
1897     {
1898 
1899         /* Set allowed authentication string length.  */
1900         auth_length = client_ptr -> nx_smtp_server_packet -> nx_packet_length;
1901 
1902         /* Find the end (e.g. CRLF) of the server reply.  */
1903         _nx_smtp_find_crlf(client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr,
1904                            auth_length, &carriage_return_linefeed_ptr, NX_FALSE);
1905 
1906         /* Check for invalid server reply (e.g. missing CRLF).  */
1907         if (carriage_return_linefeed_ptr== NX_NULL)
1908         {
1909 
1910             client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
1911 
1912             /* Indicate mail cannot be sent. */
1913             client_ptr -> nx_smtp_client_mail_status = NX_SMTP_SERVER_ERROR_REPLY;
1914 
1915             /* We are done with the packet now. */
1916             nx_packet_release(client_ptr -> nx_smtp_server_packet);
1917 
1918             /* Return completion status.  */
1919             return NX_SUCCESS;
1920         }
1921 
1922         /* Yes, process (decode) the server's challenge.  */
1923         status = _nx_smtp_utility_authentication_challenge(client_ptr, client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr,
1924                                                            (UINT)(carriage_return_linefeed_ptr - client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr));
1925 
1926         /* Did the session successfully handle server challenge?  */
1927         if (status == NX_SUCCESS)
1928         {
1929 
1930             /* Yes, set session to respond to the next server challenge.  */
1931             client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_AUTH_CHALLENGE;
1932         }
1933         /* Did the session have problems parsing the server challenge?  */
1934         else
1935         {
1936 
1937             client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
1938 
1939             /* Indicate mail cannot be sent. */
1940             client_ptr -> nx_smtp_client_mail_status = NX_SMTP_AUTH_REPLY_ERROR;
1941 
1942             nx_packet_release(client_ptr -> nx_smtp_server_packet);
1943 
1944             /* Return completion status.  */
1945             return NX_SUCCESS;
1946         }
1947     }
1948 
1949     /* We are done with the packet now. */
1950     nx_packet_release(client_ptr -> nx_smtp_server_packet);
1951 
1952     /* Return successful status.  */
1953     return NX_SUCCESS;
1954 }
1955 
1956 /**************************************************************************/
1957 /*                                                                        */
1958 /*  FUNCTION                                               RELEASE        */
1959 /*                                                                        */
1960 /*    _nx_smtp_cmd_auth_challenge                         PORTABLE C      */
1961 /*                                                           6.1.6        */
1962 /*  AUTHOR                                                                */
1963 /*                                                                        */
1964 /*    Yuxin Zhou, Microsoft Corporation                                   */
1965 /*                                                                        */
1966 /*  DESCRIPTION                                                           */
1967 /*                                                                        */
1968 /*    This function creates a reply to the server authentication challenge*/
1969 /*    It determines which challenge the server sent (e.g Username,        */
1970 /*    Password) and encodes the session response using base64 encryption. */
1971 /*                                                                        */
1972 /*  INPUT                                                                 */
1973 /*                                                                        */
1974 /*    session_ptr                           SMTP Session for sending mail */
1975 /*                                                                        */
1976 /*  OUTPUT                                                                */
1977 /*                                                                        */
1978 /*    NX_SUCCESS                            Successful completion status  */
1979 /*                                                                        */
1980 /*  CALLS                                                                 */
1981 /*                                                                        */
1982 /*    _nx_smtp_utility_send_to_server       Send data to server           */
1983 /*    _nx_utility_base64_encode             Base64 encode specified text  */
1984 /*    memcpy                                Copy data to area of memory   */
1985 /*                                                                        */
1986 /*  CALLED BY                                                             */
1987 /*                                                                        */
1988 /*    _nx_smtp_client_process               Runs the SMTP session         */
1989 /*                                                                        */
1990 /*  RELEASE HISTORY                                                       */
1991 /*                                                                        */
1992 /*    DATE              NAME                      DESCRIPTION             */
1993 /*                                                                        */
1994 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1995 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
1996 /*                                            buffer length verification, */
1997 /*                                            verified memcpy use cases,  */
1998 /*                                            resulting in version 6.1    */
1999 /*  04-02-2021     Yuxin Zhou               Modified comment(s), and      */
2000 /*                                            improved the logic of       */
2001 /*                                            parsing base64,             */
2002 /*                                            resulting in version 6.1.6  */
2003 /*                                                                        */
2004 /**************************************************************************/
_nx_smtp_cmd_auth_challenge(NX_SMTP_CLIENT * client_ptr)2005 UINT  _nx_smtp_cmd_auth_challenge(NX_SMTP_CLIENT *client_ptr)
2006 {
2007 
2008 UINT     status;
2009 UINT     index;
2010 UCHAR    auth_reply_encoded[NX_SMTP_CLIENT_AUTH_CHALLENGE_ENCODED_SIZE + 1];
2011 UINT     auth_reply_encoded_size;
2012 UINT     length;
2013 UINT     password_length;
2014 
2015     /* Initialize the encoded reply to NULL.  */
2016     memset(auth_reply_encoded, 0, sizeof(auth_reply_encoded));
2017 
2018     /* Verify string length.  */
2019     if (_nx_utility_string_length_check(client_ptr -> nx_smtp_password, &password_length, NX_SMTP_CLIENT_MAX_PASSWORD))
2020     {
2021         return(NX_SIZE_ERROR);
2022     }
2023 
2024     /* Did the server send us the Username prompt?  */
2025     if (client_ptr -> nx_smtp_client_authentication_reply == NX_SMTP_CLIENT_REPLY_TO_USERNAME_PROMPT)
2026     {
2027         if (_nx_utility_string_length_check(client_ptr -> nx_smtp_username, &length, NX_SMTP_CLIENT_MAX_USERNAME))
2028         {
2029             return(NX_SIZE_ERROR);
2030         }
2031 
2032 
2033         if (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_PLAIN)
2034         {
2035 
2036             UCHAR plain_auth_buffer[NX_SMTP_CLIENT_AUTH_CHALLENGE_SIZE];
2037 
2038             if (NX_SMTP_CLIENT_AUTH_CHALLENGE_SIZE < (length + 1 + length + 1 + password_length))
2039             {
2040 
2041                 /* Buffer size too small. */
2042                 return(NX_SMTP_INTERNAL_ERROR);
2043             }
2044 
2045             memset(&plain_auth_buffer[0], 0, NX_SMTP_CLIENT_AUTH_CHALLENGE_SIZE);
2046 
2047             /* Process the client name as per AUTH PLAIN syntax: authorization-id\0authentication-id\0password. */
2048             memcpy(&plain_auth_buffer[0], client_ptr -> nx_smtp_username,  length); /* Use case of memcpy is verified. */
2049             length++;
2050             memcpy(&plain_auth_buffer[length], client_ptr -> nx_smtp_username,  length);  /* Use case of memcpy is verified. */
2051             length += length;
2052             memcpy(&plain_auth_buffer[length], client_ptr -> nx_smtp_password, password_length); /* Use case of memcpy is verified. */
2053             length += password_length;
2054 
2055             /* Now encode the combined client username/password.  */
2056             _nx_utility_base64_encode(&plain_auth_buffer[0], length, auth_reply_encoded, sizeof(auth_reply_encoded), &auth_reply_encoded_size);
2057 
2058         }
2059         else
2060         {
2061 
2062             /* Just encode the client username.  */
2063             _nx_utility_base64_encode((UCHAR *)client_ptr -> nx_smtp_username, length, auth_reply_encoded, sizeof(auth_reply_encoded), &auth_reply_encoded_size);
2064         }
2065 
2066     }
2067     /* Or did the server send us the Password prompt?  */
2068     else if (client_ptr -> nx_smtp_client_authentication_reply == NX_SMTP_CLIENT_REPLY_TO_PASSWORD_PROMPT)
2069     {
2070 
2071         /* Encode the client password.  */
2072         _nx_utility_base64_encode((UCHAR *)client_ptr -> nx_smtp_password, password_length, auth_reply_encoded, sizeof(auth_reply_encoded), &auth_reply_encoded_size);
2073     }
2074 
2075     else
2076     {
2077 
2078         /* Unknown prompt: Send the '*' to terminate the authentication process.  */
2079         memcpy(auth_reply_encoded, NX_SMTP_CANCEL_AUTHENTICATION,  sizeof(NX_SMTP_CANCEL_AUTHENTICATION)); /* Use case of memcpy is verified. */
2080         auth_reply_encoded_size = sizeof(NX_SMTP_CANCEL_AUTHENTICATION) - 1;
2081     }
2082 
2083     if (sizeof(_nx_smtp_buffer) < (auth_reply_encoded_size + sizeof(NX_SMTP_LINE_TERMINATOR) - 1))
2084     {
2085 
2086         /* Buffer size too small. */
2087         return(NX_SMTP_INTERNAL_ERROR);
2088     }
2089 
2090     /* Format the encoded response.  */
2091     memcpy(&_nx_smtp_buffer[0],auth_reply_encoded, auth_reply_encoded_size); /* Use case of memcpy is verified. */
2092     index = auth_reply_encoded_size;
2093     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
2094     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
2095 
2096     /* Send the response back to the server.  */
2097     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
2098 
2099     /* Check for successful.  */
2100     if (status == NX_SUCCESS)
2101     {
2102 
2103         /* Set session state to wait on the outcome of the AUTH challenge handler.  */
2104         client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
2105     }
2106 
2107     /* Return completion status.  */
2108     return status;
2109 }
2110 
2111 
2112 /**************************************************************************/
2113 /*                                                                        */
2114 /*  FUNCTION                                               RELEASE        */
2115 /*                                                                        */
2116 /*    _nx_smtp_rsp_auth_challenge                         PORTABLE C      */
2117 /*                                                           6.1          */
2118 /*  AUTHOR                                                                */
2119 /*                                                                        */
2120 /*    Yuxin Zhou, Microsoft Corporation                                   */
2121 /*                                                                        */
2122 /*  DESCRIPTION                                                           */
2123 /*                                                                        */
2124 /*    This receives the server's response to the AUTH challenge sent by   */
2125 /*    the session previously and actually just calls the same session     */
2126 /*    AUTH server reply handler again.                                    */
2127 /*                                                                        */
2128 /*  INPUT                                                                 */
2129 /*                                                                        */
2130 /*    session_ptr                      SMTP Session for sending mail      */
2131 /*                                                                        */
2132 /*  OUTPUT                                                                */
2133 /*                                                                        */
2134 /*    status                           Actual completion status           */
2135 /*                                                                        */
2136 /*  CALLS                                                                 */
2137 /*                                                                        */
2138 /*   _nx_smtp_rsp_auth                 AUTH server reply handler          */
2139 /*                                                                        */
2140 /*  CALLED BY                                                             */
2141 /*                                                                        */
2142 /*    _nx_smtp_client_process          Runs the SMTP state machine        */
2143 /*                                                                        */
2144 /*  RELEASE HISTORY                                                       */
2145 /*                                                                        */
2146 /*    DATE              NAME                      DESCRIPTION             */
2147 /*                                                                        */
2148 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2149 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2150 /*                                            resulting in version 6.1    */
2151 /*                                                                        */
2152 /**************************************************************************/
_nx_smtp_rsp_auth_challenge(NX_SMTP_CLIENT * client_ptr)2153 UINT  _nx_smtp_rsp_auth_challenge(NX_SMTP_CLIENT *client_ptr)
2154 {
2155 
2156 UINT status;
2157 
2158 
2159     /* Run the session AUTH server reply handler directly.  */
2160     status = _nx_smtp_rsp_auth(client_ptr);
2161 
2162     /* Return completion status.  */
2163     return status;
2164 }
2165 
2166 
2167 /**************************************************************************/
2168 /*                                                                        */
2169 /*  FUNCTION                                               RELEASE        */
2170 /*                                                                        */
2171 /*    _nx_smtp_cmd_mail                                   PORTABLE C      */
2172 /*                                                           6.1          */
2173 /*  AUTHOR                                                                */
2174 /*                                                                        */
2175 /*    Yuxin Zhou, Microsoft Corporation                                   */
2176 /*                                                                        */
2177 /*  DESCRIPTION                                                           */
2178 /*                                                                        */
2179 /*    This function creates the MAIL command and sets the Client state to */
2180 /*    send it to the SMTP server.                                         */
2181 /*                                                                        */
2182 /*  INPUT                                                                 */
2183 /*                                                                        */
2184 /*    session_ptr                           SMTP Session for sending mail */
2185 /*                                                                        */
2186 /*  OUTPUT                                                                */
2187 /*                                                                        */
2188 /*    NX_SUCCESS                            Successful completion status  */
2189 /*    status                                Actual completion status      */
2190 /*    memcpy                                Copy data to area of memory   */
2191 /*                                                                        */
2192 /*  CALLS                                                                 */
2193 /*                                                                        */
2194 /*    _nx_smtp_utility_send_to_server       Send data to server           */
2195 /*                                                                        */
2196 /*  CALLED BY                                                             */
2197 /*                                                                        */
2198 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
2199 /*                                                                        */
2200 /*  RELEASE HISTORY                                                       */
2201 /*                                                                        */
2202 /*    DATE              NAME                      DESCRIPTION             */
2203 /*                                                                        */
2204 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2205 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2206 /*                                            verified memcpy use cases,  */
2207 /*                                            resulting in version 6.1    */
2208 /*                                                                        */
2209 /**************************************************************************/
_nx_smtp_cmd_mail(NX_SMTP_CLIENT * client_ptr)2210 UINT  _nx_smtp_cmd_mail(NX_SMTP_CLIENT *client_ptr)
2211 {
2212 
2213 UINT index;
2214 UINT status;
2215 UINT mail_from_length;
2216 NX_SMTP_CLIENT_MAIL *mail_ptr = &client_ptr -> nx_smtp_client_mail;
2217 
2218 
2219     memset(_nx_smtp_buffer, 0, NX_SMTP_BUFFER_SIZE);
2220 
2221     if (_nx_utility_string_length_check(mail_ptr -> nx_smtp_client_mail_from_address, &mail_from_length, NX_SMTP_BUFFER_SIZE))
2222     {
2223         return(NX_SIZE_ERROR);
2224     }
2225 
2226     /* Check if authentication status still left as 'in progress'.  */
2227     if (client_ptr -> nx_smtp_client_authentication_state == NX_SMTP_AUTHENTICATION_IN_PROGRESS)
2228     {
2229 
2230         /* For some reason, authentication did not complete. Reset status here.  */
2231         client_ptr -> nx_smtp_client_authentication_state = NX_SMTP_NOT_AUTHENTICATED;
2232     }
2233 
2234     /* Validate message size. */
2235     if((sizeof(NX_SMTP_COMMAND_MAIL) + mail_from_length +
2236         sizeof(NX_SMTP_LINE_TERMINATOR) + 2) > NX_SMTP_BUFFER_SIZE)
2237     {
2238         /* Message size exceeds buffer size. */
2239         return(NX_SMTP_INTERNAL_ERROR);
2240     }
2241 
2242     /* Create the command text.  */
2243     memcpy(&_nx_smtp_buffer[0], NX_SMTP_COMMAND_MAIL, sizeof(NX_SMTP_COMMAND_MAIL) - 1); /* Use case of memcpy is verified. */
2244     index = sizeof(NX_SMTP_COMMAND_MAIL) - 1;
2245 
2246     _nx_smtp_buffer[index++] = ':';
2247     _nx_smtp_buffer[index++] = '<';
2248     memcpy(&_nx_smtp_buffer[index], mail_ptr -> nx_smtp_client_mail_from_address, mail_from_length); /* Use case of memcpy is verified. */
2249     index += mail_from_length;
2250     _nx_smtp_buffer[index++] = '>';
2251 
2252     _nx_smtp_buffer[index++] = ' ';
2253     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
2254     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
2255 
2256     /* Send the session command we constructed above.  */
2257     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
2258 
2259     /* Check for error.  */
2260     if (status != NX_SUCCESS)
2261     {
2262 
2263         /* Return error status.*/
2264         return status;
2265     }
2266 
2267     /* Set session state to wait on the outcome of the MAIL response handler.  */
2268     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
2269 
2270     /* Return successful session status.  */
2271     return(NX_SUCCESS);
2272 }
2273 
2274 
2275 /**************************************************************************/
2276 /*                                                                        */
2277 /*  FUNCTION                                               RELEASE        */
2278 /*                                                                        */
2279 /*    _nx_smtp_rsp_mail                                   PORTABLE C      */
2280 /*                                                           6.1          */
2281 /*  AUTHOR                                                                */
2282 /*                                                                        */
2283 /*    Yuxin Zhou, Microsoft Corporation                                   */
2284 /*                                                                        */
2285 /*  DESCRIPTION                                                           */
2286 /*                                                                        */
2287 /*    This receives the server's response to the MAIL command; it         */
2288 /*    extracts the server reply code and reply text and store both to the */
2289 /*    Client session. It will also set the next SMTP command to send to   */
2290 /*    the server.                                                         */
2291 /*                                                                        */
2292 /*  INPUT                                                                 */
2293 /*                                                                        */
2294 /*    session_ptr                           SMTP Session for sending mail */
2295 /*                                                                        */
2296 /*  OUTPUT                                                                */
2297 /*                                                                        */
2298 /*    NX_SUCCESS                            Successful completion status  */
2299 /*    status                                Actual completion status      */
2300 /*                                                                        */
2301 /*  CALLS                                                                 */
2302 /*                                                                        */
2303 /*    _nx_smtp_utility_read_server_code     Parse the server reply        */
2304 /*                                                                        */
2305 /*  CALLED BY                                                             */
2306 /*                                                                        */
2307 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
2308 /*                                                                        */
2309 /*  RELEASE HISTORY                                                       */
2310 /*                                                                        */
2311 /*    DATE              NAME                      DESCRIPTION             */
2312 /*                                                                        */
2313 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2314 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2315 /*                                            resulting in version 6.1    */
2316 /*                                                                        */
2317 /**************************************************************************/
_nx_smtp_rsp_mail(NX_SMTP_CLIENT * client_ptr)2318 UINT  _nx_smtp_rsp_mail(NX_SMTP_CLIENT *client_ptr)
2319 {
2320 
2321 UINT  status;
2322 
2323     /* Get the server response to the MAIL command.  */
2324     status   =  _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
2325 
2326     /* Check for error.  */
2327     if (status != NX_SUCCESS)
2328     {
2329 
2330         /* This is an invalid line or corrupted transmission from the server.  */
2331 
2332         /* Return error status.  */
2333         return(status);
2334     }
2335 
2336     /* Did server accept the MAIL command?  */
2337     if (client_ptr -> nx_smtp_client_reply_code_status == NX_SMTP_CODE_OK_TO_CONTINUE)
2338     {
2339 
2340         /* Yes, set the session to the RCPT state.  */
2341         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_RCPT;
2342     }
2343     else
2344     {
2345 
2346         /* Set session state to QUIT.  */
2347         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_QUIT;
2348 
2349         /* Indicate mail cannot be sent. */
2350         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_MAIL_REPLY_ERROR;
2351     }
2352 
2353     /* We are done with the packet now. */
2354     nx_packet_release(client_ptr -> nx_smtp_server_packet);
2355 
2356     /* Return successful session status.  */
2357     return(NX_SUCCESS);
2358 }
2359 
2360 
2361 /**************************************************************************/
2362 /*                                                                        */
2363 /*  FUNCTION                                               RELEASE        */
2364 /*                                                                        */
2365 /*    _nx_smtp_cmd_rcpt                                   PORTABLE C      */
2366 /*                                                           6.1          */
2367 /*  AUTHOR                                                                */
2368 /*                                                                        */
2369 /*    Yuxin Zhou, Microsoft Corporation                                   */
2370 /*                                                                        */
2371 /*  DESCRIPTION                                                           */
2372 /*                                                                        */
2373 /*    This function creates the RCPT command and sets the Client state to */
2374 /*    send it to the SMTP server.                                         */
2375 /*                                                                        */
2376 /*  INPUT                                                                 */
2377 /*                                                                        */
2378 /*    session_ptr                           SMTP Session for sending mail */
2379 /*                                                                        */
2380 /*  OUTPUT                                                                */
2381 /*                                                                        */
2382 /*    NX_SUCCESS                            Successful completion status  */
2383 /*    status                                Actual completion status      */
2384 /*                                                                        */
2385 /*  CALLS                                                                 */
2386 /*                                                                        */
2387 /*    _nx_smtp_utility_send_to_server       Send data to server           */
2388 /*    memcpy                                Copy data to area of memory   */
2389 /*                                                                        */
2390 /*  CALLED BY                                                             */
2391 /*                                                                        */
2392 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
2393 /*                                                                        */
2394 /*  RELEASE HISTORY                                                       */
2395 /*                                                                        */
2396 /*    DATE              NAME                      DESCRIPTION             */
2397 /*                                                                        */
2398 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2399 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2400 /*                                            verified memcpy use cases,  */
2401 /*                                            resulting in version 6.1    */
2402 /*                                                                        */
2403 /**************************************************************************/
_nx_smtp_cmd_rcpt(NX_SMTP_CLIENT * client_ptr)2404 UINT  _nx_smtp_cmd_rcpt(NX_SMTP_CLIENT *client_ptr)
2405 {
2406 
2407 UINT                        status;
2408 UINT                        index;
2409 UINT                        recipient_length;
2410 NX_SMTP_CLIENT_MAIL         *mail_ptr;
2411 
2412 
2413     mail_ptr = &(client_ptr -> nx_smtp_client_mail);
2414 
2415     if (_nx_utility_string_length_check(mail_ptr -> nx_smtp_client_mail_recipient_address, &recipient_length, NX_SMTP_BUFFER_SIZE))
2416     {
2417         return(NX_SIZE_ERROR);
2418     }
2419 
2420     memset(_nx_smtp_buffer, 0, NX_SMTP_BUFFER_SIZE);
2421 
2422     /* Validate message size. */
2423     if((sizeof(NX_SMTP_COMMAND_RCPT) + recipient_length +
2424         sizeof(NX_SMTP_LINE_TERMINATOR) + 2) > NX_SMTP_BUFFER_SIZE)
2425     {
2426         /* Message size exceeds buffer size. */
2427         return(NX_SMTP_INTERNAL_ERROR);
2428     }
2429 
2430     /* Create the command text.  */
2431     memcpy(&_nx_smtp_buffer[0], NX_SMTP_COMMAND_RCPT, sizeof(NX_SMTP_COMMAND_RCPT) - 1); /* Use case of memcpy is verified. */
2432     index = sizeof(NX_SMTP_COMMAND_RCPT) - 1;
2433 
2434     _nx_smtp_buffer[index++] = ':';
2435     _nx_smtp_buffer[index++] = '<';
2436     memcpy(&_nx_smtp_buffer[index],  mail_ptr -> nx_smtp_client_mail_recipient_address, /* Use case of memcpy is verified. */
2437            recipient_length);
2438     index += recipient_length;
2439     _nx_smtp_buffer[index++] = '>';
2440     _nx_smtp_buffer[index++] = ' ';
2441     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
2442     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
2443 
2444     /* Send the RCPT command.  */
2445     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
2446 
2447     /* Check for error.  */
2448     if (status != NX_SUCCESS)
2449     {
2450 
2451         return status;
2452     }
2453 
2454     /* Set session state to wait next response from server.  */
2455     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
2456 
2457     /* Return normal session status.  */
2458     return NX_SUCCESS;
2459 }
2460 
2461 
2462 /**************************************************************************/
2463 /*                                                                        */
2464 /*  FUNCTION                                               RELEASE        */
2465 /*                                                                        */
2466 /*    _nx_smtp_rsp_rcpt                                   PORTABLE C      */
2467 /*                                                           6.1          */
2468 /*  AUTHOR                                                                */
2469 /*                                                                        */
2470 /*    Yuxin Zhou, Microsoft Corporation                                   */
2471 /*                                                                        */
2472 /*  DESCRIPTION                                                           */
2473 /*                                                                        */
2474 /*    This service handles the server's response to the RCPT command and  */
2475 /*    set the next session state and next command to send to the server.  */
2476 /*                                                                        */
2477 /*  INPUT                                                                 */
2478 /*                                                                        */
2479 /*    session_ptr                        SMTP Session for sending mail    */
2480 /*                                                                        */
2481 /*  OUTPUT                                                                */
2482 /*                                                                        */
2483 /*    NX_SUCCESS                         Successful completion status     */
2484 /*    status                             Actual completion status         */
2485 /*                                                                        */
2486 /*  CALLS                                                                 */
2487 /*                                                                        */
2488 /*   _nx_smtp_utility_read_server_code   Parse the server reply           */
2489 /*                                                                        */
2490 /*  CALLED BY                                                             */
2491 /*                                                                        */
2492 /*    _nx_smtp_client_process            Runs the SMTP state machine      */
2493 /*                                                                        */
2494 /*  RELEASE HISTORY                                                       */
2495 /*                                                                        */
2496 /*    DATE              NAME                      DESCRIPTION             */
2497 /*                                                                        */
2498 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2499 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2500 /*                                            resulting in version 6.1    */
2501 /*                                                                        */
2502 /**************************************************************************/
_nx_smtp_rsp_rcpt(NX_SMTP_CLIENT * client_ptr)2503 UINT  _nx_smtp_rsp_rcpt(NX_SMTP_CLIENT *client_ptr)
2504 {
2505 
2506 UINT  status;
2507 
2508 
2509     /* Get server response to RCPT command.  */
2510     status = _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
2511 
2512     /* Check for error.  */
2513     if (status != NX_SUCCESS)
2514     {
2515 
2516         /* Return error status.  */
2517         return(status);
2518     }
2519 
2520     /* Did server accept RCPT command?  */
2521     if (client_ptr -> nx_smtp_client_reply_code_status != NX_SMTP_CODE_OK_TO_CONTINUE)
2522     {
2523         /* NO, Set session state to QUIT.  */
2524         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
2525 
2526         /* Indicate mail cannot be sent. */
2527         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_RCPT_REPLY_ERROR;
2528     }
2529     else
2530     {
2531 
2532         /* Ok for server to send the mail message */
2533         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_DATA;
2534     }
2535 
2536     /* We are done with the packet now. */
2537     nx_packet_release(client_ptr -> nx_smtp_server_packet);
2538 
2539     /* Return successful session status.  */
2540     return NX_SUCCESS;
2541 }
2542 
2543 
2544 /**************************************************************************/
2545 /*                                                                        */
2546 /*  FUNCTION                                               RELEASE        */
2547 /*                                                                        */
2548 /*    _nx_smtp_cmd_data                                   PORTABLE C      */
2549 /*                                                           6.1          */
2550 /*  AUTHOR                                                                */
2551 /*                                                                        */
2552 /*    Yuxin Zhou, Microsoft Corporation                                   */
2553 /*                                                                        */
2554 /*  DESCRIPTION                                                           */
2555 /*                                                                        */
2556 /*    This function sets the DATA command text, verifies the mail to send */
2557 /*    has a valid recipient and sends it to the  SMTP server.             */
2558 /*                                                                        */
2559 /*  INPUT                                                                 */
2560 /*                                                                        */
2561 /*    session_ptr                           SMTP Session for sending mail */
2562 /*                                                                        */
2563 /*  OUTPUT                                                                */
2564 /*                                                                        */
2565 /*    NX_SUCCESS                            Successful completion status  */
2566 /*    status                                Actual completion status      */
2567 /*                                                                        */
2568 /*  CALLS                                                                 */
2569 /*                                                                        */
2570 /*    _nx_smtp_utility_send_to_server       Send SMTP commend to server   */
2571 /*    memcpy                                Copy data to area of memory   */
2572 /*                                                                        */
2573 /*  CALLED BY                                                             */
2574 /*                                                                        */
2575 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
2576 /*                                                                        */
2577 /*  RELEASE HISTORY                                                       */
2578 /*                                                                        */
2579 /*    DATE              NAME                      DESCRIPTION             */
2580 /*                                                                        */
2581 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2582 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2583 /*                                            verified memcpy use cases,  */
2584 /*                                            resulting in version 6.1    */
2585 /*                                                                        */
2586 /**************************************************************************/
_nx_smtp_cmd_data(NX_SMTP_CLIENT * client_ptr)2587 UINT  _nx_smtp_cmd_data(NX_SMTP_CLIENT *client_ptr)
2588 {
2589 
2590 UINT     status;
2591 UINT     index;
2592 
2593 
2594     memset(_nx_smtp_buffer, 0, NX_SMTP_BUFFER_SIZE);
2595 
2596     /* Format the DATA command.  */
2597     memcpy(&_nx_smtp_buffer[0], NX_SMTP_COMMAND_DATA, sizeof(NX_SMTP_COMMAND_DATA) - 1); /* Use case of memcpy is verified. */
2598     index = sizeof(NX_SMTP_COMMAND_DATA) - 1;
2599     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
2600     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
2601 
2602     /* Send the DATA command.  */
2603     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
2604 
2605     /* Check for error.  */
2606     if (status != NX_SUCCESS)
2607     {
2608 
2609         return status;
2610     }
2611 
2612     /* Set session state to wait next response from server.  */
2613     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
2614 
2615     /* Return normal session status.  */
2616     return NX_SUCCESS;
2617 }
2618 
2619 
2620 /**************************************************************************/
2621 /*                                                                        */
2622 /*  FUNCTION                                               RELEASE        */
2623 /*                                                                        */
2624 /*    _nx_smtp_rsp_data                                   PORTABLE C      */
2625 /*                                                           6.1          */
2626 /*  AUTHOR                                                                */
2627 /*                                                                        */
2628 /*    Yuxin Zhou, Microsoft Corporation                                   */
2629 /*                                                                        */
2630 /*  DESCRIPTION                                                           */
2631 /*                                                                        */
2632 /*    This function handles the server reply to the DATA command and set  */
2633 /*    the next SMTP Client command to send to the server.                 */
2634 /*                                                                        */
2635 /*  INPUT                                                                 */
2636 /*                                                                        */
2637 /*    session_ptr                           SMTP Session for sending mail */
2638 /*                                                                        */
2639 /*  OUTPUT                                                                */
2640 /*                                                                        */
2641 /*    NX_SUCCESS                            Successful completion status  */
2642 /*    status                                Actual completion status      */
2643 /*                                                                        */
2644 /*  CALLS                                                                 */
2645 /*                                                                        */
2646 /*   _nx_smtp_utility_read_server_code      Parse the server reply        */
2647 /*                                                                        */
2648 /*  CALLED BY                                                             */
2649 /*                                                                        */
2650 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
2651 /*                                                                        */
2652 /*  RELEASE HISTORY                                                       */
2653 /*                                                                        */
2654 /*    DATE              NAME                      DESCRIPTION             */
2655 /*                                                                        */
2656 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2657 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2658 /*                                            resulting in version 6.1    */
2659 /*                                                                        */
2660 /**************************************************************************/
_nx_smtp_rsp_data(NX_SMTP_CLIENT * client_ptr)2661 UINT  _nx_smtp_rsp_data(NX_SMTP_CLIENT *client_ptr)
2662 {
2663 
2664 UINT            status;
2665 
2666 
2667     /* Get the response to DATA command.  */
2668     status = _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
2669 
2670     /* Check for errors.  */
2671     if (status != NX_SUCCESS)
2672     {
2673 
2674         /* Return error status.  */
2675         return (status);
2676     }
2677 
2678     if (client_ptr -> nx_smtp_client_reply_code_status == NX_SMTP_CODE_SEND_MAIL_INPUT)
2679     {
2680 
2681         /* Yes, set session state to next step.  */
2682         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_MESSAGE;
2683     }
2684     else
2685     {
2686 
2687         /* No, any other 3xy code in inappropriate. Quit the session.  */
2688         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
2689 
2690         /* Indicate mail cannot be sent. */
2691         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_DATA_REPLY_ERROR;
2692     }
2693 
2694     /* We are done with the packet now. */
2695     nx_packet_release(client_ptr -> nx_smtp_server_packet);
2696 
2697     /* Return successful session status.  */
2698     return NX_SUCCESS;
2699 }
2700 
2701 
2702 /**************************************************************************/
2703 /*                                                                        */
2704 /*  FUNCTION                                               RELEASE        */
2705 /*                                                                        */
2706 /*    _nx_smtp_cmd_message                                PORTABLE C      */
2707 /*                                                           6.1          */
2708 /*  AUTHOR                                                                */
2709 /*                                                                        */
2710 /*    Yuxin Zhou, Microsoft Corporation                                   */
2711 /*                                                                        */
2712 /*  DESCRIPTION                                                           */
2713 /*                                                                        */
2714 /*    This function handles the mail message text handling for message    */
2715 /*    text.  It attempts to fit as much of each message into each packet  */
2716 /*    as possible.                                                        */
2717 /*                                                                        */
2718 /*  INPUT                                                                 */
2719 /*                                                                        */
2720 /*    session_ptr                           Session for sending mail      */
2721 /*                                                                        */
2722 /*  OUTPUT                                                                */
2723 /*                                                                        */
2724 /*    NX_SUCCESS                            Successful completion status  */
2725 /*    NX_NOT_ENABLED                        IPv6 not enabled              */
2726 /*    status                                Actual completion status      */
2727 /*                                                                        */
2728 /*  CALLS                                                                 */
2729 /*                                                                        */
2730 /*    _nx_smtp_utility_send_to_server       Send data to server           */
2731 /*                                                                        */
2732 /*  CALLED BY                                                             */
2733 /*                                                                        */
2734 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
2735 /*                                                                        */
2736 /*  RELEASE HISTORY                                                       */
2737 /*                                                                        */
2738 /*    DATE              NAME                      DESCRIPTION             */
2739 /*                                                                        */
2740 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2741 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2742 /*                                            resulting in version 6.1    */
2743 /*                                                                        */
2744 /**************************************************************************/
_nx_smtp_cmd_message(NX_SMTP_CLIENT * client_ptr)2745 UINT  _nx_smtp_cmd_message(NX_SMTP_CLIENT *client_ptr)
2746 {
2747 
2748 UINT                        status;
2749 ULONG                       data_left_to_transmit;
2750 ULONG                       packet_payload;
2751 CHAR                        *data_to_send;
2752 NX_PACKET_POOL              *pool_ptr;
2753 NX_SMTP_CLIENT_MAIL         *mail_ptr;
2754 
2755 
2756     /* Set local variable for convenience.  */
2757     mail_ptr = &client_ptr -> nx_smtp_client_mail;
2758 
2759     /* Set session state to wait next response from server.  */
2760     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
2761 
2762     pool_ptr  = client_ptr -> nx_smtp_client_packet_pool_ptr;
2763 
2764     /* Compute packet payload after IP and TCP headers are subtracted.  */
2765     if (client_ptr -> nx_smtp_server_address.nxd_ip_version == NX_IP_VERSION_V4)
2766     {
2767 
2768 #ifndef NX_DISABLE_IPV4
2769         packet_payload = pool_ptr -> nx_packet_pool_payload_size - sizeof(NX_TCP_HEADER) - sizeof(NX_IPV4_HEADER);
2770 #else
2771         return NX_NOT_ENABLED;
2772 #endif /* NX_DISABLE_IPV4 */
2773     }
2774     else
2775     {
2776 #ifdef FEATURE_NX_IPV6
2777         packet_payload = pool_ptr -> nx_packet_pool_payload_size - sizeof(NX_TCP_HEADER) - sizeof(NX_IPV6_HEADER);
2778 #else
2779         return NX_NOT_ENABLED;
2780 #endif
2781     }
2782 
2783 
2784     /* Send the Mail header */
2785     status = _nx_smtp_utility_send_header_to_server(client_ptr, NX_SMTP_CLIENT_SEND_TIMEOUT);
2786     if(status)
2787         return(status);
2788 
2789     /* Set up local variable of size of mail message. */
2790     data_left_to_transmit = mail_ptr -> nx_smtp_client_mail_body_length;
2791 
2792     /* Set a local pointer to (rest of) mail message to send. */
2793     data_to_send = mail_ptr -> nx_smtp_client_mail_body;
2794 
2795     /* Send the next chunk of mail text buffer till nothing is left.  */
2796     while(data_left_to_transmit)
2797     {
2798 
2799         /* Check if remaining mail text will fit in a packet.*/
2800         if (packet_payload >= data_left_to_transmit)
2801         {
2802 
2803             /* Yes, send it off! This will load the specified data into an packet from the SMTP client packet pool.  */
2804             status =  _nx_smtp_utility_send_to_server(client_ptr, data_to_send, data_left_to_transmit,
2805                                                       NX_SMTP_CLIENT_SEND_TIMEOUT);
2806 
2807             /* Check for error.  */
2808             if (status != NX_SUCCESS)
2809             {
2810 
2811                 /* Return error status.  */
2812                 return status;
2813             }
2814 
2815             break;
2816         }
2817 
2818         /* No, break up mail message into multiple packets.  */
2819         else
2820         {
2821 
2822             /* Fill up the packet with as much data as it will hold and send it off! */
2823             status =  _nx_smtp_utility_send_to_server(client_ptr, data_to_send, packet_payload,
2824                                                       NX_SMTP_CLIENT_SEND_TIMEOUT);
2825 
2826             /* Check for error.  */
2827             if (status != NX_SUCCESS)
2828             {
2829 
2830                 /* Return error status.  */
2831                 return status;
2832             }
2833 
2834             /* Update pointer to remainder of message to send, update how much is left to send. */
2835             data_left_to_transmit -= packet_payload;
2836             data_to_send += packet_payload;
2837         }
2838     }
2839 
2840     /* Send end of message (EOM) to server or it will handle subsequent commands as message text.  */
2841     status =  _nx_smtp_utility_send_to_server(client_ptr, NX_SMTP_EOM, sizeof(NX_SMTP_EOM) - 1, NX_SMTP_CLIENT_SEND_TIMEOUT);
2842 
2843     /* Return normal session status.  */
2844     return status;
2845 }
2846 
2847 
2848 /**************************************************************************/
2849 /*                                                                        */
2850 /*  FUNCTION                                               RELEASE        */
2851 /*                                                                        */
2852 /*    _nx_smtp_rsp_message                                PORTABLE C      */
2853 /*                                                           6.1          */
2854 /*  AUTHOR                                                                */
2855 /*                                                                        */
2856 /*    Yuxin Zhou, Microsoft Corporation                                   */
2857 /*                                                                        */
2858 /*  DESCRIPTION                                                           */
2859 /*                                                                        */
2860 /*    This receives the server's response to sending it mail message data.*/
2861 /*    It extracts the server reply code and reply text and store both to  */
2862 /*    the Client session. It then sets the next session state, sets up    */
2863 /*    the next command to send to the server.                             */
2864 /*                                                                        */
2865 /*    If the server accepts the mail message, this function determines if */
2866 /*    if there is more session mail to transact, and if so sets the next  */
2867 /*    Client mail.                                                        */
2868 /*                                                                        */
2869 /*  INPUT                                                                 */
2870 /*                                                                        */
2871 /*    session_ptr                           Session for sending mail      */
2872 /*                                                                        */
2873 /*  OUTPUT                                                                */
2874 /*                                                                        */
2875 /*    NX_SUCCESS                            Successful completion status  */
2876 /*    status                                Actual completion status      */
2877 /*                                                                        */
2878 /*  CALLS                                                                 */
2879 /*                                                                        */
2880 /*    _nx_smtp_utility_read_server_code     Parse the server reply code   */
2881 /*                                                                        */
2882 /*  CALLED BY                                                             */
2883 /*                                                                        */
2884 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
2885 /*                                                                        */
2886 /*  RELEASE HISTORY                                                       */
2887 /*                                                                        */
2888 /*    DATE              NAME                      DESCRIPTION             */
2889 /*                                                                        */
2890 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2891 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2892 /*                                            resulting in version 6.1    */
2893 /*                                                                        */
2894 /**************************************************************************/
_nx_smtp_rsp_message(NX_SMTP_CLIENT * client_ptr)2895 UINT  _nx_smtp_rsp_message(NX_SMTP_CLIENT *client_ptr)
2896 {
2897 
2898 UINT     status;
2899 
2900 
2901     /* Get the server reply to receiving session mail message data.  */
2902     status = _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_MESSAGE_TIMEOUT, NX_TRUE);
2903 
2904     /* Check for error.  */
2905     if (status != NX_SUCCESS)
2906     {
2907 
2908         /* Return the error status.  */
2909         return(status);
2910     }
2911 
2912     /* Process server reply code by first digit.  */
2913     if (client_ptr -> nx_smtp_client_reply_code_status == NX_SMTP_CODE_OK_TO_CONTINUE)
2914     {
2915 
2916         /* Message accepted by server. Mark the Client mail as sent.  */
2917         client_ptr -> nx_smtp_client_mail_status = NX_SUCCESS;
2918     }
2919     else
2920     {
2921 
2922         /* Indicate mail cannot be sent. */
2923         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_MESSAGE_REPLY_ERROR;
2924     }
2925 
2926     /* We're done with this session */
2927     client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_QUIT;
2928 
2929     /* We are done with the packet now. */
2930     nx_packet_release(client_ptr -> nx_smtp_server_packet);
2931 
2932     /* Return successful session status.  */
2933     return(NX_SUCCESS);
2934 }
2935 
2936 
2937 /**************************************************************************/
2938 /*                                                                        */
2939 /*  FUNCTION                                               RELEASE        */
2940 /*                                                                        */
2941 /*    _nx_smtp_cmd_quit                                   PORTABLE C      */
2942 /*                                                           6.1          */
2943 /*  AUTHOR                                                                */
2944 /*                                                                        */
2945 /*    Yuxin Zhou, Microsoft Corporation                                   */
2946 /*                                                                        */
2947 /*  DESCRIPTION                                                           */
2948 /*                                                                        */
2949 /*    This function creates the QUIT command text and and sends the Quit  */
2950 /*    command to the  SMTP server.                                        */
2951 /*                                                                        */
2952 /*  INPUT                                                                 */
2953 /*                                                                        */
2954 /*    session_ptr                           SMTP Session for sending mail */
2955 /*                                                                        */
2956 /*  OUTPUT                                                                */
2957 /*                                                                        */
2958 /*    NX_SUCCESS                            Successful completion status  */
2959 /*    status                                Actual completion status      */
2960 /*                                                                        */
2961 /*  CALLS                                                                 */
2962 /*                                                                        */
2963 /*    _nx_smtp_utility_send_to_server       Send data to server           */
2964 /*    memcpy                                Copy data to area of memory   */
2965 /*                                                                        */
2966 /*  CALLED BY                                                             */
2967 /*                                                                        */
2968 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
2969 /*                                                                        */
2970 /*  RELEASE HISTORY                                                       */
2971 /*                                                                        */
2972 /*    DATE              NAME                      DESCRIPTION             */
2973 /*                                                                        */
2974 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2975 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2976 /*                                            verified memcpy use cases,  */
2977 /*                                            resulting in version 6.1    */
2978 /*                                                                        */
2979 /**************************************************************************/
_nx_smtp_cmd_quit(NX_SMTP_CLIENT * client_ptr)2980 UINT  _nx_smtp_cmd_quit(NX_SMTP_CLIENT *client_ptr)
2981 {
2982 
2983 UINT     status;
2984 UINT     index;
2985 
2986 
2987     memset(_nx_smtp_buffer, 0, NX_SMTP_BUFFER_SIZE);
2988 
2989     /* Format the QUIT command.  */
2990     memcpy(&_nx_smtp_buffer[0], NX_SMTP_COMMAND_QUIT, sizeof(NX_SMTP_COMMAND_QUIT) - 1); /* Use case of memcpy is verified. */
2991     index = sizeof(NX_SMTP_COMMAND_QUIT) - 1;
2992     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR)); /* Use case of memcpy is verified. */
2993     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
2994 
2995     /* Send the QUIT command.  */
2996     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
2997 
2998     /* Check for error.  */
2999     if (status != NX_SUCCESS)
3000     {
3001 
3002         /* Return error status.  */
3003         return status;
3004     }
3005 
3006     /* Set session state to wait on the outcome of the EHLO response handler.  */
3007     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
3008 
3009     /* Return normal session status.  */
3010     return NX_SUCCESS;
3011 }
3012 
3013 
3014 /**************************************************************************/
3015 /*                                                                        */
3016 /*  FUNCTION                                               RELEASE        */
3017 /*                                                                        */
3018 /*    _nx_smtp_rsp_quit                                   PORTABLE C      */
3019 /*                                                           6.1          */
3020 /*  AUTHOR                                                                */
3021 /*                                                                        */
3022 /*    Yuxin Zhou, Microsoft Corporation                                   */
3023 /*                                                                        */
3024 /*  DESCRIPTION                                                           */
3025 /*                                                                        */
3026 /*    This function handles the server reply to the SMTP QUIT command and */
3027 /*    sets the session state to the session has terminated normally.      */
3028 /*                                                                        */
3029 /*  INPUT                                                                 */
3030 /*                                                                        */
3031 /*    session_ptr                           SMTP Session for sending mail */
3032 /*                                                                        */
3033 /*  OUTPUT                                                                */
3034 /*                                                                        */
3035 /*    NX_SUCCESS                            Successful completion status  */
3036 /*    status                                Actual completion status      */
3037 /*                                                                        */
3038 /*  CALLS                                                                 */
3039 /*                                                                        */
3040 /*   _nx_smtp_utility_read_server_code      Parse the server reply        */
3041 /*                                                                        */
3042 /*  CALLED BY                                                             */
3043 /*                                                                        */
3044 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
3045 /*                                                                        */
3046 /*  RELEASE HISTORY                                                       */
3047 /*                                                                        */
3048 /*    DATE              NAME                      DESCRIPTION             */
3049 /*                                                                        */
3050 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3051 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3052 /*                                            resulting in version 6.1    */
3053 /*                                                                        */
3054 /**************************************************************************/
_nx_smtp_rsp_quit(NX_SMTP_CLIENT * client_ptr)3055 UINT  _nx_smtp_rsp_quit(NX_SMTP_CLIENT *client_ptr)
3056 {
3057 
3058 UINT    status;
3059 
3060 
3061     /* Get server response to QUIT command.  */
3062     status = _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
3063 
3064     /* Check for error status.  */
3065     if (status != NX_SUCCESS)
3066     {
3067 
3068         /* Return the error status.  */
3069         return(status);
3070     }
3071 
3072     /* Set the session state to normal termination. Normal is when the SMTP Client can
3073        receive SMTP server replies and regardless if mail can be sent, can at least
3074        terminate the session with the Quit command and normal TCP socket disconnect.  */
3075     client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_COMPLETED_NORMALLY;
3076 
3077     /* We are done with the packet now. */
3078     nx_packet_release(client_ptr -> nx_smtp_server_packet);
3079 
3080     /* Return successful session status.  */
3081     return NX_SUCCESS;
3082 }
3083 
3084 
3085 /**************************************************************************/
3086 /*                                                                        */
3087 /*  FUNCTION                                               RELEASE        */
3088 /*                                                                        */
3089 /*    _nx_smtp_cmd_rset                                   PORTABLE C      */
3090 /*                                                           6.1          */
3091 /*  AUTHOR                                                                */
3092 /*                                                                        */
3093 /*    Yuxin Zhou, Microsoft Corporation                                   */
3094 /*                                                                        */
3095 /*  DESCRIPTION                                                           */
3096 /*                                                                        */
3097 /*    This functions creates the RSET command for the Client task to send */
3098 /*    it to the SMTP server.                                              */
3099 /*                                                                        */
3100 /*  INPUT                                                                 */
3101 /*                                                                        */
3102 /*    session_ptr                           SMTP Session for sending mail */
3103 /*                                                                        */
3104 /*  OUTPUT                                                                */
3105 /*                                                                        */
3106 /*    NX_SUCCESS                            Successful completion status  */
3107 /*                                                                        */
3108 /*  CALLS                                                                 */
3109 /*                                                                        */
3110 /*    _nx_smtp_utility_send_to_server       Send data to server           */
3111 /*    memcpy                                Copy data to area of memory   */
3112 /*                                                                        */
3113 /*  CALLED BY                                                             */
3114 /*                                                                        */
3115 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
3116 /*                                                                        */
3117 /*  RELEASE HISTORY                                                       */
3118 /*                                                                        */
3119 /*    DATE              NAME                      DESCRIPTION             */
3120 /*                                                                        */
3121 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3122 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
3123 /*                                            verified memcpy use cases,  */
3124 /*                                            resulting in version 6.1    */
3125 /*                                                                        */
3126 /**************************************************************************/
_nx_smtp_cmd_rset(NX_SMTP_CLIENT * client_ptr)3127 UINT  _nx_smtp_cmd_rset(NX_SMTP_CLIENT *client_ptr)
3128 {
3129 
3130 ULONG    timeout;
3131 UINT     status;
3132 UINT     index;
3133 
3134 
3135     memset(_nx_smtp_buffer, 0, NX_SMTP_BUFFER_SIZE);
3136 
3137     /* Get TCP send timeout.  */
3138     timeout =  NX_SMTP_ENVELOPE_TIMEOUT;
3139 
3140     /* Format the RSET command.  */
3141     memcpy(&_nx_smtp_buffer[0], NX_SMTP_COMMAND_RSET, sizeof(NX_SMTP_COMMAND_RSET) - 1); /* Use case of memcpy is verified. */
3142     index = sizeof(NX_SMTP_COMMAND_RSET) - 1;
3143     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
3144     index += sizeof( NX_SMTP_LINE_TERMINATOR) - 1;
3145 
3146     /* Send the RSET command.  */
3147     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, timeout);
3148 
3149     /* Check for error.  */
3150     if (status != NX_SUCCESS)
3151     {
3152 
3153         return status;
3154     }
3155 
3156     /* Set session state to wait on the outcome of the EHLO response handler.  */
3157     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
3158 
3159     /* Return normal session status.  */
3160     return NX_SUCCESS;
3161 }
3162 
3163 
3164 /**************************************************************************/
3165 /*                                                                        */
3166 /*  FUNCTION                                               RELEASE        */
3167 /*                                                                        */
3168 /*    _nx_smtp_rsp_rset                                   PORTABLE C      */
3169 /*                                                           6.1          */
3170 /*  AUTHOR                                                                */
3171 /*                                                                        */
3172 /*    Yuxin Zhou, Microsoft Corporation                                   */
3173 /*                                                                        */
3174 /*  DESCRIPTION                                                           */
3175 /*                                                                        */
3176 /*    This function handles the RSET server reply.                        */
3177 /*                                                                        */
3178 /*    Resetting an SMTP session means clearing the Client mail transaction*/
3179 /*    including recipients and mail text.                                 */
3180 /*                                                                        */
3181 /*  INPUT                                                                 */
3182 /*                                                                        */
3183 /*    session_ptr                           SMTP Session for sending mail */
3184 /*                                                                        */
3185 /*  OUTPUT                                                                */
3186 /*                                                                        */
3187 /*    NX_SUCCESS                            Successful completion status  */
3188 /*    status                                Actual completion status      */
3189 /*                                                                        */
3190 /*  CALLS                                                                 */
3191 /*                                                                        */
3192 /*   _nx_smtp_utility_read_server_code      Parse the server reply        */
3193 /*                                                                        */
3194 /*  CALLED BY                                                             */
3195 /*                                                                        */
3196 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
3197 /*                                                                        */
3198 /*  RELEASE HISTORY                                                       */
3199 /*                                                                        */
3200 /*    DATE              NAME                      DESCRIPTION             */
3201 /*                                                                        */
3202 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3203 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3204 /*                                            resulting in version 6.1    */
3205 /*                                                                        */
3206 /**************************************************************************/
_nx_smtp_rsp_rset(NX_SMTP_CLIENT * client_ptr)3207 UINT  _nx_smtp_rsp_rset(NX_SMTP_CLIENT *client_ptr)
3208 {
3209 
3210 UINT  status;
3211 
3212 
3213     /* Get server response to RSET command.  */
3214     status =  _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
3215 
3216     /* Check for error.  */
3217     if (status != NX_SUCCESS)
3218     {
3219 
3220         /* Return error status.  */
3221         return(status);
3222     }
3223 
3224     /* Did the session receive the 250 OK from the server?  */
3225     if (client_ptr -> nx_smtp_client_reply_code_status != NX_SMTP_CODE_OK_TO_CONTINUE)
3226     {
3227 
3228         /* Yes, set the session state to QUIT.  */
3229         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_QUIT;
3230         /* Indicate mail cannot be sent. */
3231         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_SERVER_ERROR_CODE_RECEIVED;
3232     }
3233     else
3234     {
3235 
3236         /* Yes, session accepted the RSET command with the 250 code.
3237            Reset session state back to MAIL.  */
3238         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_MAIL;
3239 
3240     }
3241 
3242     /* Return successful session status.  */
3243     return NX_SUCCESS;
3244 }
3245 
3246 
3247 /**************************************************************************/
3248 /*                                                                        */
3249 /*  FUNCTION                                               RELEASE        */
3250 /*                                                                        */
3251 /*    _nx_smtp_cmd_noop                                   PORTABLE C      */
3252 /*                                                           6.1          */
3253 /*  AUTHOR                                                                */
3254 /*                                                                        */
3255 /*    Yuxin Zhou, Microsoft Corporation                                   */
3256 /*                                                                        */
3257 /*  DESCRIPTION                                                           */
3258 /*                                                                        */
3259 /*    This function creates the SMTP NOOP command text and sends it to the*/
3260 /*    SMTP server.                                                        */
3261 /*                                                                        */
3262 /*  INPUT                                                                 */
3263 /*                                                                        */
3264 /*    session_ptr                           SMTP Session for sending mail */
3265 /*                                                                        */
3266 /*  OUTPUT                                                                */
3267 /*                                                                        */
3268 /*    NX_SUCCESS                            Successful completion status  */
3269 /*                                                                        */
3270 /*  CALLS                                                                 */
3271 /*                                                                        */
3272 /*    _nx_smtp_utility_send_to_server       Send data to server           */
3273 /*    memcpy                                Copy data to area of memory   */
3274 /*                                                                        */
3275 /*  CALLED BY                                                             */
3276 /*                                                                        */
3277 /*    _nx_smtp_client_process               Runs the SMTP state machine   */
3278 /*                                                                        */
3279 /*  RELEASE HISTORY                                                       */
3280 /*                                                                        */
3281 /*    DATE              NAME                      DESCRIPTION             */
3282 /*                                                                        */
3283 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3284 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
3285 /*                                            verified memcpy use cases,  */
3286 /*                                            resulting in version 6.1    */
3287 /*                                                                        */
3288 /**************************************************************************/
_nx_smtp_cmd_noop(NX_SMTP_CLIENT * client_ptr)3289 UINT  _nx_smtp_cmd_noop(NX_SMTP_CLIENT *client_ptr)
3290 {
3291 
3292 UINT     status;
3293 UINT     index;
3294 
3295 
3296     memset(_nx_smtp_buffer, 0, NX_SMTP_BUFFER_SIZE);
3297 
3298     /* Format the NOOP command.  */
3299     memcpy(&_nx_smtp_buffer[0], NX_SMTP_COMMAND_NOOP, sizeof(NX_SMTP_COMMAND_NOOP) - 1); /* Use case of memcpy is verified. */
3300     index = sizeof(NX_SMTP_COMMAND_NOOP) - 1;
3301     memcpy(&_nx_smtp_buffer[index],  NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */
3302     index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1;
3303 
3304     /* Send the NOOP command.  */
3305     status =  _nx_smtp_utility_send_to_server(client_ptr, _nx_smtp_buffer, index, NX_SMTP_CLIENT_SEND_TIMEOUT);
3306 
3307     /* Check for error.  */
3308     if (status != NX_SUCCESS)
3309     {
3310 
3311         return status;
3312     }
3313 
3314     /* Set session state to wait on the outcome of the EHLO response handler.  */
3315     client_ptr -> nx_smtp_client_cmd_state =  NX_SMTP_CLIENT_STATE_AWAITING_REPLY;
3316 
3317     /* Return normal session status.  */
3318     return NX_SUCCESS;
3319 }
3320 
3321 
3322 
3323 /**************************************************************************/
3324 /*                                                                        */
3325 /*  FUNCTION                                               RELEASE        */
3326 /*                                                                        */
3327 /*    _nx_smtp_rsp_noop                                   PORTABLE C      */
3328 /*                                                           6.1          */
3329 /*  AUTHOR                                                                */
3330 /*                                                                        */
3331 /*    Yuxin Zhou, Microsoft Corporation                                   */
3332 /*                                                                        */
3333 /*  DESCRIPTION                                                           */
3334 /*                                                                        */
3335 /*    This function handles the NOOP server reply. It will not            */
3336 /*    automatically advance the session state like most other SMTP client */
3337 /*    commands. However, an indication of server problems will set the    */
3338 /*    session state to QUIT.                                              */
3339 /*                                                                        */
3340 /*  INPUT                                                                 */
3341 /*                                                                        */
3342 /*    session_ptr                       TCP connection to send mail       */
3343 /*                                                                        */
3344 /*  OUTPUT                                                                */
3345 /*                                                                        */
3346 /*    NX_SUCCESS                        Successful completion status      */
3347 /*    status                            Actual completion status          */
3348 /*                                                                        */
3349 /*  CALLS                                                                 */
3350 /*                                                                        */
3351 /*   _nx_smtp_utility_read_server_code  Parse the server reply            */
3352 /*                                                                        */
3353 /*  CALLED BY                                                             */
3354 /*                                                                        */
3355 /*    _nx_smtp_client_process           Runs the SMTP state machine       */
3356 /*                                                                        */
3357 /*  RELEASE HISTORY                                                       */
3358 /*                                                                        */
3359 /*    DATE              NAME                      DESCRIPTION             */
3360 /*                                                                        */
3361 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3362 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3363 /*                                            resulting in version 6.1    */
3364 /*                                                                        */
3365 /**************************************************************************/
_nx_smtp_rsp_noop(NX_SMTP_CLIENT * client_ptr)3366 UINT  _nx_smtp_rsp_noop(NX_SMTP_CLIENT *client_ptr)
3367 {
3368 
3369 UINT              status;
3370 UINT              first_digit_server_reply;
3371 
3372 
3373     /* Get the response for NOOP command.  */
3374     status =  _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE);
3375 
3376     /* Check for error.  */
3377     if (status != NX_SUCCESS)
3378     {
3379 
3380         /* Return the error status.  */
3381         return(status);
3382     }
3383 
3384     /* Get category of server reply from the first digit.  */
3385     first_digit_server_reply = client_ptr -> nx_smtp_client_reply_code_status / 100;
3386 
3387     /* Is the server experiencing problems forcing the session to abort?  */
3388     if (first_digit_server_reply == 4)
3389     {
3390 
3391         /* Yes, set the session state to quit.  */
3392         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_QUIT;
3393 
3394         /* Indicate mail cannot be sent. */
3395         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_SERVER_ERROR_CODE_RECEIVED;
3396     }
3397 
3398     /* Return successful session status.  */
3399     return NX_SUCCESS;
3400 }
3401 
3402 /**************************************************************************/
3403 /*                                                                        */
3404 /*  FUNCTION                                               RELEASE        */
3405 /*                                                                        */
3406 /*    _nx_smtp_utility_read_server_code                   PORTABLE C      */
3407 /*                                                           6.1          */
3408 /*  AUTHOR                                                                */
3409 /*                                                                        */
3410 /*    Yuxin Zhou, Microsoft Corporation                                   */
3411 /*                                                                        */
3412 /*  DESCRIPTION                                                           */
3413 /*                                                                        */
3414 /*    This function parses the 3 digit SMTP server code and stores the    */
3415 /*    text of the server reply if there is any to the session buffer.     */
3416 /*    Its use is intended primarily for session server reply handlers.    */
3417 /*                                                                        */
3418 /*  INPUT                                                                 */
3419 /*                                                                        */
3420 /*    session_ptr                   Session to send mail to SMTP Server   */
3421 /*    timeout                       Timeout on receiving server reply     */
3422 /*    receive_all_lines             Indicates if SMTP Client should expect*/
3423 /*                                    one packet or multiple packets e.g. */
3424 /*                                    a multi packet server reply.        */
3425 /*                                                                        */
3426 /*  OUTPUT                                                                */
3427 /*                                                                        */
3428 /*    NX_SUCCESS                        Successful completion status      */
3429 /*    status                            Actual completion status          */
3430 /*                                                                        */
3431 /*  CALLS                                                                 */
3432 /*                                                                        */
3433 /*   _nx_smtp_parse_response            Parse an argument from text       */
3434 /*   nx_tcp_socket_receive              Receive data over TCP socket      */
3435 /*   nx_packet_release                  Release packet to packet pool     */
3436 /*   memset                             Clear specified area of memory    */
3437 /*                                                                        */
3438 /*  CALLED BY                                                             */
3439 /*                                                                        */
3440 /*    Session server reply handlers     Handle server replies to SMTP     */
3441 /*                                            commands in the session     */
3442 /*                                                                        */
3443 /*  RELEASE HISTORY                                                       */
3444 /*                                                                        */
3445 /*    DATE              NAME                      DESCRIPTION             */
3446 /*                                                                        */
3447 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3448 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3449 /*                                            resulting in version 6.1    */
3450 /*                                                                        */
3451 /**************************************************************************/
_nx_smtp_utility_read_server_code(NX_SMTP_CLIENT * client_ptr,ULONG timeout,UINT receive_all_lines)3452 UINT  _nx_smtp_utility_read_server_code(NX_SMTP_CLIENT *client_ptr, ULONG timeout, UINT  receive_all_lines)
3453 {
3454 
3455 UINT         status;
3456 NX_PACKET    *packet_ptr;
3457 UCHAR        server_code[NX_SMTP_SERVER_REPLY_CODE_SIZE + 1];
3458 UCHAR        *work_ptr;
3459 UINT         buffer_length;
3460 
3461     NX_PARAMETER_NOT_USED(receive_all_lines);
3462 
3463     /* Initialize argument to NULL.  */
3464     memset(server_code, 0, NX_SMTP_SERVER_REPLY_CODE_SIZE + 1);
3465 
3466     /* Process all packets received as part of server reply. A server response may
3467        have several 'lines' in it e.g. 250-EHLO\r\n250-AUTH LOGIN\r\n250 HELP,
3468       and this may be spread over multiple packets. */
3469 
3470     /* Wait to receive the next packet.  */
3471     status = nx_tcp_socket_receive(&(client_ptr -> nx_smtp_client_socket), &packet_ptr, timeout);
3472 
3473     /* Check for errors.  */
3474     if (status != NX_SUCCESS)
3475     {
3476 
3477         /* Set session state to QUIT.  */
3478         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_QUIT;
3479 
3480         /* Return error status.  */
3481         return status;
3482     }
3483 
3484 #ifndef NX_DISABLE_PACKET_CHAIN
3485     if (packet_ptr -> nx_packet_next)
3486     {
3487 
3488         /* Chained packet is not supported. */
3489         nx_packet_release(packet_ptr);
3490 
3491         /* Set session state to QUIT.  */
3492         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_QUIT;
3493 
3494         /* Indicate mail cannot be sent. */
3495         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_SERVER_ERROR_REPLY;
3496 
3497         /* While there was an error with the packet, the SMTP Client is ok. So just return
3498            completion status and we quit the session. */
3499         return NX_SUCCESS;
3500     }
3501 #endif /* NX_DISABLE_PACKET_CHAIN */
3502 
3503     /* Save the location of the server response buffer. */
3504     client_ptr -> nx_smtp_server_packet = packet_ptr;
3505 
3506     work_ptr = client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr;
3507     buffer_length = client_ptr -> nx_smtp_server_packet -> nx_packet_length;
3508 
3509     /* Yes, parse the server code.  Note that with SMTP protocol, the server reply
3510        may be multiple lines/packets. To determine if we have the end of the reply
3511        we look for the command code followed by a space (not a hyphen). */
3512     status = _nx_smtp_parse_response(client_ptr, work_ptr, 1, buffer_length, &server_code[0],
3513                                      NX_SMTP_SERVER_REPLY_CODE_SIZE, NX_FALSE);
3514 
3515     /* Was a server reply code found in the first line?  */
3516     if (status != NX_SUCCESS)
3517     {
3518 
3519         /* No, it wasn't. */
3520         nx_packet_release(packet_ptr);
3521 
3522         /* Set session state to QUIT.  */
3523         client_ptr -> nx_smtp_client_rsp_state =  NX_SMTP_CLIENT_STATE_QUIT;
3524 
3525         /* Indicate mail cannot be sent. */
3526         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_SERVER_ERROR_REPLY;
3527 
3528         /* While there was an error with the packet, the SMTP Client is ok. So just return
3529            completion status and we quit the session. */
3530         return NX_SUCCESS;
3531     }
3532 
3533     /* Convert server code from text to unsigned int and store to session.  */
3534     client_ptr -> nx_smtp_client_reply_code_status =  strtoul((const char *)server_code, NULL, 10);
3535 
3536     /* Return completion status.  */
3537     return (NX_SUCCESS);
3538 }
3539 
3540 /**************************************************************************/
3541 /*                                                                        */
3542 /*  FUNCTION                                               RELEASE        */
3543 /*                                                                        */
3544 /*    _nx_smtp_utility_send_to_server                     PORTABLE C      */
3545 /*                                                           6.1          */
3546 /*  AUTHOR                                                                */
3547 /*                                                                        */
3548 /*    Yuxin Zhou, Microsoft Corporation                                   */
3549 /*                                                                        */
3550 /*  DESCRIPTION                                                           */
3551 /*                                                                        */
3552 /*    This function compiles the message/command to send the SMTP server. */
3553 /*    It returns a non success status if packet allocation fails or an    */
3554 /*    error results from creating the SMTP command packet.                */
3555 /*                                                                        */
3556 /*   INPUT                                                                */
3557 /*                                                                        */
3558 /*    session_ptr                   Session to send mail to SMTP Server   */
3559 /*    buffer_ptr                    Pointer to buffer for to send         */
3560 /*    buffer_length                 Size of buffer                        */
3561 /*    timeout                       Timeout for sending data out          */
3562 /*                                                                        */
3563 /*  OUTPUT                                                                */
3564 /*                                                                        */
3565 /*    NX_SUCCESS                      Successful completion               */
3566 /*    status                          Actual completion status            */
3567 /*                                                                        */
3568 /*  CALLS                                                                 */
3569 /*                                                                        */
3570 /*   nx_packet_allocate              Allocate packet from specified pool  */
3571 /*   nx_packet_data_append           Appends buffer to packet data        */
3572 /*   nx_packet_release               Releases send packet back to pool    */
3573 /*   nx_tcp_socket_send              Sends packet out over TCP socket     */
3574 /*                                                                        */
3575 /*  CALLED BY                                                             */
3576 /*                                                                        */
3577 /*   _nx_smtp_session_run            Runs the SMTP state machine          */
3578 /*   Session server reply handlers   Handle server reply so SMTP command  */
3579 /*   Session SMTP command services   Send SMTP commands to server         */
3580 /*                                                                        */
3581 /*  RELEASE HISTORY                                                       */
3582 /*                                                                        */
3583 /*    DATE              NAME                      DESCRIPTION             */
3584 /*                                                                        */
3585 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3586 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3587 /*                                            resulting in version 6.1    */
3588 /*                                                                        */
3589 /**************************************************************************/
_nx_smtp_utility_send_to_server(NX_SMTP_CLIENT * client_ptr,CHAR * buffer_ptr,UINT buffer_length,ULONG timeout)3590 UINT  _nx_smtp_utility_send_to_server(NX_SMTP_CLIENT *client_ptr, CHAR *buffer_ptr, UINT buffer_length, ULONG timeout)
3591 {
3592 
3593 UINT            status;
3594 NX_PACKET       *packet_ptr;
3595 UINT            packet_type;
3596 
3597 
3598     if (client_ptr -> nx_smtp_server_address.nxd_ip_version == NX_IP_VERSION_V6)
3599         packet_type = NX_IPv6_TCP_PACKET;
3600     else
3601         packet_type = NX_IPv4_TCP_PACKET;
3602 
3603     /* Allocate a packet.  */
3604     status =  nx_packet_allocate(client_ptr -> nx_smtp_client_packet_pool_ptr,
3605                                  &packet_ptr, packet_type, NX_SMTP_CLIENT_PACKET_TIMEOUT);
3606 
3607     /* Check for error.  */
3608     if (status != NX_SUCCESS)
3609     {
3610 
3611         /* Abort the session. If we cannot allocate a packet we cannot send a QUIT message. */
3612         client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_IDLE;
3613         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_IDLE;
3614 
3615         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_PACKET_ALLOCATE_ERROR;
3616 
3617         /* Return error status.  */
3618         return(status);
3619     }
3620 
3621     /* Add message to packet data.  */
3622     status = nx_packet_data_append(packet_ptr, buffer_ptr, buffer_length,
3623                                    client_ptr -> nx_smtp_client_packet_pool_ptr,
3624                                    NX_SMTP_CLIENT_PACKET_TIMEOUT);
3625     /* Check for error.  */
3626     if (status != NX_SUCCESS)
3627     {
3628 
3629         /* Release the packet.  */
3630         nx_packet_release(packet_ptr);
3631 
3632         /* Abort further processing. This error is most likely a packet allocate. */
3633         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_IDLE;
3634         client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_IDLE;
3635 
3636         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_INTERNAL_ERROR;
3637 
3638         /* Return error status.  */
3639         return(status);
3640     }
3641 
3642     /* Send the packet out.  */
3643     status =  nx_tcp_socket_send(&client_ptr -> nx_smtp_client_socket, packet_ptr, timeout);
3644 
3645     /* Check for error.  */
3646     if (status != NX_SUCCESS)
3647     {
3648 
3649         /* Release the packet.  */
3650         nx_packet_release(packet_ptr);
3651 
3652         /* Abort further processing. If we are unable to send, we won't be able to send a quit message either. */
3653         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_IDLE;
3654         client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_IDLE;
3655 
3656         /* Return error status.  */
3657         return(status);
3658     }
3659 
3660     /* Return successful session status.  */
3661     return(NX_SUCCESS);
3662 }
3663 
3664 
3665 
3666 /**************************************************************************/
3667 /*                                                                        */
3668 /*  FUNCTION                                               RELEASE        */
3669 /*                                                                        */
3670 /*    _nx_smtp_utility_send_to_server                     PORTABLE C      */
3671 /*                                                           6.1          */
3672 /*  AUTHOR                                                                */
3673 /*                                                                        */
3674 /*    Yuxin Zhou, Microsoft Corporation                                   */
3675 /*                                                                        */
3676 /*  DESCRIPTION                                                           */
3677 /*                                                                        */
3678 /*    This function compiles the message/command to send the SMTP server. */
3679 /*    It returns a non success status if packet allocation fails or an    */
3680 /*    error results from creating the SMTP command packet.                */
3681 /*                                                                        */
3682 /*   INPUT                                                                */
3683 /*                                                                        */
3684 /*    session_ptr                   Session to send mail to SMTP Server   */
3685 /*    buffer_ptr                    Pointer to buffer for to send         */
3686 /*    buffer_length                 Size of buffer                        */
3687 /*    timeout                       Timeout for sending data out          */
3688 /*                                                                        */
3689 /*  OUTPUT                                                                */
3690 /*                                                                        */
3691 /*    NX_SUCCESS                      Successful completion               */
3692 /*    status                          Actual completion status            */
3693 /*                                                                        */
3694 /*  CALLS                                                                 */
3695 /*                                                                        */
3696 /*   nx_packet_allocate              Allocate packet from specified pool  */
3697 /*   nx_packet_data_append           Appends buffer to packet data        */
3698 /*   nx_packet_release               Releases send packet back to pool    */
3699 /*   nx_tcp_socket_send              Sends packet out over TCP socket     */
3700 /*                                                                        */
3701 /*  CALLED BY                                                             */
3702 /*                                                                        */
3703 /*   _nx_smtp_session_run            Runs the SMTP state machine          */
3704 /*   Session server reply handlers   Handle server reply so SMTP command  */
3705 /*   Session SMTP command services   Send SMTP commands to server         */
3706 /*                                                                        */
3707 /*  RELEASE HISTORY                                                       */
3708 /*                                                                        */
3709 /*    DATE              NAME                      DESCRIPTION             */
3710 /*                                                                        */
3711 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3712 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3713 /*                                            resulting in version 6.1    */
3714 /*                                                                        */
3715 /**************************************************************************/
_nx_smtp_utility_send_header_to_server(NX_SMTP_CLIENT * client_ptr,ULONG timeout)3716 UINT  _nx_smtp_utility_send_header_to_server(NX_SMTP_CLIENT *client_ptr, ULONG timeout)
3717 {
3718 
3719 UINT                 status;
3720 NX_PACKET           *packet_ptr = NX_NULL;
3721 UINT                 packet_type;
3722 NX_SMTP_CLIENT_MAIL *mail_ptr;
3723 NX_PACKET_POOL      *pool_ptr;
3724 UINT                 recipient_length;
3725 UINT                 mail_from_length;
3726 UINT                 subject_length;
3727 
3728 
3729     mail_ptr = &client_ptr -> nx_smtp_client_mail;
3730 
3731     if (client_ptr -> nx_smtp_server_address.nxd_ip_version == NX_IP_VERSION_V6)
3732         packet_type = NX_IPv6_TCP_PACKET;
3733     else
3734         packet_type = NX_IPv4_TCP_PACKET;
3735 
3736     /* Verify string length.  */
3737     if (_nx_utility_string_length_check(mail_ptr -> nx_smtp_client_mail_recipient_address, &recipient_length, NX_SMTP_BUFFER_SIZE))
3738     {
3739         return(NX_SIZE_ERROR);
3740     }
3741 
3742     if (_nx_utility_string_length_check(mail_ptr -> nx_smtp_client_mail_from_address, &mail_from_length, NX_SMTP_BUFFER_SIZE))
3743     {
3744         return(NX_SIZE_ERROR);
3745     }
3746 
3747     if (_nx_utility_string_length_check(mail_ptr -> nx_smtp_client_mail_subject, &subject_length, NX_SMTP_BUFFER_SIZE))
3748     {
3749         return(NX_SIZE_ERROR);
3750     }
3751 
3752 
3753     pool_ptr = client_ptr -> nx_smtp_client_packet_pool_ptr;
3754 
3755     /* Allocate a packet.  */
3756     status =  nx_packet_allocate(pool_ptr, &packet_ptr, packet_type, NX_SMTP_CLIENT_PACKET_TIMEOUT);
3757 
3758     /* Check for error.  */
3759     if (status == NX_SUCCESS)
3760     {
3761         if (/* Add "To:  <recipient_address> CRLF" */
3762            (nx_packet_data_append(packet_ptr, NX_SMTP_TO_STRING, sizeof(NX_SMTP_TO_STRING) - 1,
3763                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3764            (nx_packet_data_append(packet_ptr, mail_ptr -> nx_smtp_client_mail_recipient_address,
3765                                   recipient_length,
3766                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3767            (nx_packet_data_append(packet_ptr, NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1,
3768                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3769            /* Add "From:  <from_address> CRLF" */
3770            (nx_packet_data_append(packet_ptr, NX_SMTP_FROM_STRING, sizeof(NX_SMTP_FROM_STRING) - 1,
3771                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3772            (nx_packet_data_append(packet_ptr, mail_ptr -> nx_smtp_client_mail_from_address,
3773                                   mail_from_length,
3774                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3775            (nx_packet_data_append(packet_ptr, NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1,
3776                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3777            /* Add "Subject:  Subject_line CRLF" */
3778            (nx_packet_data_append(packet_ptr, NX_SMTP_SUBJECT_STRING, sizeof(NX_SMTP_SUBJECT_STRING) - 1,
3779                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3780            (nx_packet_data_append(packet_ptr, mail_ptr -> nx_smtp_client_mail_subject,
3781                                   subject_length,
3782                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3783            (nx_packet_data_append(packet_ptr, NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1,
3784                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS) &&
3785            /* Add the rest of the mail header components. */
3786            (nx_packet_data_append(packet_ptr, NX_SMTP_MAIL_HEADER_COMPONENTS, sizeof(NX_SMTP_MAIL_HEADER_COMPONENTS) - 1,
3787                                   pool_ptr, NX_SMTP_CLIENT_PACKET_TIMEOUT) == NX_SUCCESS))
3788         {
3789             /* Send the packet out.  */
3790             status =  nx_tcp_socket_send(&client_ptr -> nx_smtp_client_socket, packet_ptr, timeout);
3791 
3792             if(status)
3793             {
3794                 /* Send failed. */
3795                 status = NX_SMTP_INTERNAL_ERROR;
3796             }
3797         }
3798         else
3799         {
3800             /* One of the Mail header components failed to be appended. */
3801             status = NX_SMTP_INTERNAL_ERROR;
3802         }
3803     }
3804 
3805     if(status)
3806     {
3807 
3808         /* Abort the session. If we cannot allocate a packet we cannot send a QUIT message. */
3809         client_ptr -> nx_smtp_client_cmd_state = NX_SMTP_CLIENT_STATE_IDLE;
3810         client_ptr -> nx_smtp_client_rsp_state = NX_SMTP_CLIENT_STATE_IDLE;
3811 
3812         client_ptr -> nx_smtp_client_mail_status = NX_SMTP_INTERNAL_ERROR;
3813 
3814         if(packet_ptr)
3815         {
3816             /* Release the packet.  */
3817             nx_packet_release(packet_ptr);
3818         }
3819     }
3820 
3821 
3822     /* Return successful session status.  */
3823     return(NX_SUCCESS);
3824 }
3825 
3826 
3827 /**************************************************************************/
3828 /*                                                                        */
3829 /*  FUNCTION                                               RELEASE        */
3830 /*                                                                        */
3831 /*    _nx_smtp_utility_authentication_challenge           PORTABLE C      */
3832 /*                                                           6.1.6        */
3833 /*  AUTHOR                                                                */
3834 /*                                                                        */
3835 /*    Yuxin Zhou, Microsoft Corporation                                   */
3836 /*                                                                        */
3837 /*  DESCRIPTION                                                           */
3838 /*                                                                        */
3839 /*    This function handles parsing and decoding the server challenge,    */
3840 /*    and setting up the client response to the challenge.  It does not   */
3841 /*    alter the session state or determine the next session command.      */
3842 /*                                                                        */
3843 /*  INPUT                                                                 */
3844 /*                                                                        */
3845 /*    session_ptr                   Session to send mail to SMTP Server   */
3846 /*    server_challenge              Buffer containing server challenge    */
3847 /*    length                        Size of server challenge buffer       */
3848 /*                                                                        */
3849 /*  OUTPUT                                                                */
3850 /*                                                                        */
3851 /*    NX_SUCCESS                     Successful completion status         */
3852 /*    NX_SMTP_PARAM_ERROR            Server parsing (parameter) error     */
3853 /*                                                                        */
3854 /*  CALLS                                                                 */
3855 /*                                                                        */
3856 /*    _nx_smtp_parse_response       Parses argument from buffer text      */
3857 /*    _nx_utility_base64_decode     Decodes base64 text                   */
3858 /*    memset                        Clears specified area of memory       */
3859 /*    memcmp                        Compares data between areas of memory */
3860 /*                                                                        */
3861 /*  CALLED BY                                                             */
3862 /*                                                                        */
3863 /*    _nx_smtp_rsp_auth             AUTH server reply handler             */
3864 /*                                                                        */
3865 /*  RELEASE HISTORY                                                       */
3866 /*                                                                        */
3867 /*    DATE              NAME                      DESCRIPTION             */
3868 /*                                                                        */
3869 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3870 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3871 /*                                            resulting in version 6.1    */
3872 /*  04-02-2021     Yuxin Zhou               Modified comment(s), and      */
3873 /*                                            improved the logic of       */
3874 /*                                            parsing base64,             */
3875 /*                                            resulting in version 6.1.6  */
3876 /*                                                                        */
3877 /**************************************************************************/
_nx_smtp_utility_authentication_challenge(NX_SMTP_CLIENT * client_ptr,UCHAR * server_challenge,UINT length)3878 UINT  _nx_smtp_utility_authentication_challenge(NX_SMTP_CLIENT *client_ptr, UCHAR *server_challenge, UINT length)
3879 {
3880 
3881 UCHAR  encrypted_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1];
3882 UCHAR  decoded_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1];
3883 UINT   encrypted_server_prompt_size;
3884 UINT   decoded_server_prompt_size;
3885 
3886     if (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_PLAIN)
3887     {
3888         /* Set the session to reply to a username challenge.  */
3889         client_ptr -> nx_smtp_client_authentication_reply = NX_SMTP_CLIENT_REPLY_TO_USERNAME_PROMPT;
3890 
3891         /* Return successful session status.  */
3892         return NX_SUCCESS;
3893     }
3894 
3895     /* Clear buffers for storing encrypted and decoded server challenges.  */
3896     memset(encrypted_server_prompt, 0, NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1);
3897     memset(decoded_server_prompt, 0, NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1);
3898 
3899     /* Parse the 2nd argument for the server challenge we need to decode.  */
3900     _nx_smtp_parse_response(client_ptr, &server_challenge[0], 2, length, &encrypted_server_prompt[0],
3901                             NX_SMTP_SERVER_CHALLENGE_MAX_STRING, NX_FALSE);
3902 
3903     /* Was a valid argument parsed?  */
3904     if (*encrypted_server_prompt == NX_NULL)
3905     {
3906 
3907         /* No , unable to parse server prompt.  */
3908 
3909         /* Return error status.  */
3910         return NX_SMTP_INVALID_SERVER_REPLY;
3911     }
3912 
3913     /* Calculate the name length.  */
3914     if (_nx_utility_string_length_check((CHAR *)encrypted_server_prompt, &encrypted_server_prompt_size, NX_SMTP_SERVER_CHALLENGE_MAX_STRING))
3915     {
3916         return NX_SMTP_INVALID_SERVER_REPLY;
3917     }
3918 
3919     /* Decode the parsed server challenge.  */
3920     _nx_utility_base64_decode(encrypted_server_prompt, encrypted_server_prompt_size, decoded_server_prompt, sizeof(decoded_server_prompt), &decoded_server_prompt_size);
3921 
3922     /* Is this a username prompt?  */
3923     if ((decoded_server_prompt_size == 9) &&
3924         ((decoded_server_prompt[0] == 'U') || (decoded_server_prompt[0] == 'u')) &&
3925         ((decoded_server_prompt[1] == 'S') || (decoded_server_prompt[1] == 's')) &&
3926         ((decoded_server_prompt[2] == 'E') || (decoded_server_prompt[2] == 'e')) &&
3927         ((decoded_server_prompt[3] == 'R') || (decoded_server_prompt[3] == 'r')) &&
3928         ((decoded_server_prompt[4] == 'N') || (decoded_server_prompt[4] == 'n')) &&
3929         ((decoded_server_prompt[5] == 'A') || (decoded_server_prompt[5] == 'a')) &&
3930         ((decoded_server_prompt[6] == 'M') || (decoded_server_prompt[6] == 'm')) &&
3931         ((decoded_server_prompt[7] == 'E') || (decoded_server_prompt[7] == 'e')) &&
3932         (decoded_server_prompt[8] == ':'))
3933     {
3934 
3935         /* Yes, set the session to reply to a username challenge.  */
3936         client_ptr -> nx_smtp_client_authentication_reply = NX_SMTP_CLIENT_REPLY_TO_USERNAME_PROMPT;
3937     }
3938     /* Is this a password prompt?  */
3939     else if ((decoded_server_prompt_size == 9) &&
3940              ((decoded_server_prompt[0] == 'P') || (decoded_server_prompt[0] == 'p')) &&
3941              ((decoded_server_prompt[1] == 'A') || (decoded_server_prompt[1] == 'a')) &&
3942              ((decoded_server_prompt[2] == 'S') || (decoded_server_prompt[2] == 's')) &&
3943              ((decoded_server_prompt[3] == 'S') || (decoded_server_prompt[3] == 's')) &&
3944              ((decoded_server_prompt[4] == 'W') || (decoded_server_prompt[4] == 'w')) &&
3945              ((decoded_server_prompt[5] == 'O') || (decoded_server_prompt[5] == 'o')) &&
3946              ((decoded_server_prompt[6] == 'R') || (decoded_server_prompt[6] == 'r')) &&
3947              ((decoded_server_prompt[7] == 'D') || (decoded_server_prompt[7] == 'd')) &&
3948              (decoded_server_prompt[8] == ':'))
3949     {
3950 
3951         /* Yes, set the session to reply to a password challenge.  */
3952         client_ptr -> nx_smtp_client_authentication_reply = NX_SMTP_CLIENT_REPLY_TO_PASSWORD_PROMPT;
3953     }
3954     else
3955     {
3956 
3957         /* Indicate invalid authentication from server.  */
3958         return NX_SMTP_CLIENT_REPLY_TO_UNKNOWN_PROMPT;
3959     }
3960 
3961     /* Return successful session status.  */
3962     return NX_SUCCESS;
3963 }
3964 
3965 
3966 /**************************************************************************/
3967 /*                                                                        */
3968 /*  FUNCTION                                               RELEASE        */
3969 /*                                                                        */
3970 /*    _nx_smtp_utility_parse_server_services              PORTABLE C      */
3971 /*                                                           6.1.6        */
3972 /*  AUTHOR                                                                */
3973 /*                                                                        */
3974 /*    Yuxin Zhou, Microsoft Corporation                                   */
3975 /*                                                                        */
3976 /*  DESCRIPTION                                                           */
3977 /*                                                                        */
3978 /*    This function checks for the AUTH option in the server response. If */
3979 /*    authentication is offered, it attempts to find a match between      */
3980 /*    authentication options offered by the server and the client         */
3981 /*    authentication type. If no match between client and server is found,*/
3982 /*    or no authentication is listed in the server response, it sets the  */
3983 /*    client authentication type to PLAIN.                                */
3984 /*                                                                        */
3985 /*  INPUT                                                                 */
3986 /*                                                                        */
3987 /*    session_ptr                   Session to send mail to SMTP Server   */
3988 /*                                                                        */
3989 /*  OUTPUT                                                                */
3990 /*                                                                        */
3991 /*    None                                                                */
3992 /*                                                                        */
3993 /*  CALLS                                                                 */
3994 /*                                                                        */
3995 /*    strstr                        Search for a string within a string   */
3996 /*                                                                        */
3997 /*  CALLED BY                                                             */
3998 /*                                                                        */
3999 /*    _nx_smtp_rsp_ehlo             EHLO server reply handler             */
4000 /*                                                                        */
4001 /*  RELEASE HISTORY                                                       */
4002 /*                                                                        */
4003 /*    DATE              NAME                      DESCRIPTION             */
4004 /*                                                                        */
4005 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4006 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4007 /*                                            resulting in version 6.1    */
4008 /*  04-02-2021     Yuxin Zhou               Modified comment(s),          */
4009 /*                                            improved boundary check,    */
4010 /*                                            resulting in version 6.1.6  */
4011 /*                                                                        */
4012 /**************************************************************************/
_nx_smtp_utility_parse_server_services(NX_SMTP_CLIENT * client_ptr)4013 VOID  _nx_smtp_utility_parse_server_services(NX_SMTP_CLIENT *client_ptr)
4014 {
4015 
4016 UINT   plain_option = NX_FALSE;
4017 UINT   login_option = NX_FALSE;
4018 UCHAR  *work_ptr;
4019 UCHAR  *temp_ptr;
4020 ULONG  length, new_length;
4021 UINT   i;
4022 UINT   found = NX_FALSE;
4023 
4024 
4025     /* Does the server list an authentication type, and  does the client want authentication? */
4026 
4027     /* Set local variable for convenience. */
4028     length = client_ptr -> nx_smtp_server_packet -> nx_packet_length;
4029 
4030     /* Find the location of the AUTH command. */
4031     work_ptr = client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr;
4032 
4033     /* Check length. */
4034     if (length <= 4)
4035     {
4036         return;
4037     }
4038 
4039     for (i = 0; i < length - 4; i++)
4040     {
4041         if (
4042              ((*work_ptr == 'A') || (*work_ptr == 'a')) &&
4043              ((*(work_ptr + 1) == 'U') || (*(work_ptr + 1) == 'u')) &&
4044              ((*(work_ptr + 2) == 'T') || (*(work_ptr + 2) == 't')) &&
4045              ((*(work_ptr + 3) == 'H') || (*(work_ptr + 3) == 'h'))
4046            )
4047         {
4048 
4049             found = NX_TRUE;
4050             work_ptr += 4;
4051             break;
4052         }
4053 
4054         work_ptr++;
4055     }
4056 
4057     /* Check if this packet has the AUTH keyword. */
4058     if (!found )
4059     {
4060 
4061         /* It does not. So leave the Client authentication type as is. */
4062         return;
4063     }
4064 
4065     /* Check if the client prefers no authentication. */
4066     if (found && (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_NONE))
4067     {
4068 
4069         /* There is an AUTH keyword but the client prefers not to authenticate. */
4070         return;
4071     }
4072 
4073     /* Save the location where the search stopped. */
4074     temp_ptr = work_ptr;
4075 
4076     found = NX_FALSE;
4077     new_length = length - (ULONG)(temp_ptr - client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr);
4078 
4079     /* Check length. */
4080     if (new_length < 5)
4081     {
4082         return;
4083     }
4084     else
4085     {
4086         new_length -= 5;
4087     }
4088 
4089     /* Search for supported authentication types. */
4090     for (i = 0; i < new_length; i++)
4091     {
4092         if (
4093              ((*work_ptr == 'L') || (*work_ptr == 'l')) &&
4094              ((*(work_ptr + 1) == 'O') || (*(work_ptr + 1) == 'o')) &&
4095              ((*(work_ptr + 2) == 'G') || (*(work_ptr + 2) == 'g')) &&
4096              ((*(work_ptr + 3) == 'I') || (*(work_ptr + 3) == 'i')) &&
4097              ((*(work_ptr + 4) == 'N') || (*(work_ptr + 4) == 'n'))
4098            )
4099         {
4100             found = NX_TRUE;
4101             break;
4102         }
4103 
4104         work_ptr++;
4105     }
4106 
4107     /* Is there a LOGIN option offered? */
4108     if (found)
4109     {
4110         /* Yes, set the login option flag. */
4111         login_option = NX_TRUE;
4112     }
4113 
4114     found = NX_FALSE;
4115 
4116     /* Restore the location for a new search. */
4117     work_ptr = temp_ptr;
4118 
4119     for (i = 0; i < new_length; i++)
4120     {
4121         if (
4122              ((*work_ptr == 'P') || (*work_ptr == 'p')) &&
4123              ((*(work_ptr + 1) == 'L') || (*(work_ptr + 1) == 'l')) &&
4124              ((*(work_ptr + 2) == 'A') || (*(work_ptr + 2) == 'a')) &&
4125              ((*(work_ptr + 3) == 'I') || (*(work_ptr + 3) == 'i')) &&
4126              ((*(work_ptr + 4) == 'N') || (*(work_ptr + 4) == 'n'))
4127            )
4128         {
4129             found = NX_TRUE;
4130             break;
4131         }
4132 
4133         work_ptr++;
4134     }
4135 
4136     /* Is there a PLAIN option offered?  */
4137     if (found)
4138     {
4139         /* Yes, set the plain option flag. */
4140         plain_option = NX_TRUE;
4141     }
4142 
4143     /* Compare Server list of authentication types to client preferred authentication type. */
4144 
4145     /* Handle the case of the client prefers LOGIN authentication. */
4146     if (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_LOGIN)
4147     {
4148 
4149         /* Yes; Check if server supports offers LOGIN authentication. */
4150         if (login_option)
4151         {
4152 
4153             return;
4154         }
4155         else
4156         {
4157             /* Switch client to plain authentication. */
4158             client_ptr -> nx_smtp_client_authentication_type = NX_SMTP_CLIENT_AUTH_PLAIN;
4159 
4160             return;
4161         }
4162     }
4163 
4164     /* Check if server listed PLAIN authentication. */
4165     if (plain_option && (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_PLAIN))
4166     {
4167         /* Yes, and there's a match, we're done here.  */
4168         return;
4169     }
4170 
4171     /* If we are here, the server offers LOGIN authentication but the Client preference is something else. */
4172     if (login_option)
4173     {
4174 
4175         /* Switch client to LOGIN authentication. */
4176         client_ptr -> nx_smtp_client_authentication_type = NX_SMTP_CLIENT_AUTH_LOGIN;
4177 
4178         return;
4179     }
4180 
4181     /* Handle the case of no matches between server/client.  Assume the server requires authentication
4182        and set Client type to plain. */
4183     client_ptr -> nx_smtp_client_authentication_type = NX_SMTP_CLIENT_AUTH_PLAIN;
4184 
4185     /* Return.  */
4186     return;
4187 
4188 }
4189 
4190 /**************************************************************************/
4191 /*                                                                        */
4192 /*  FUNCTION                                               RELEASE        */
4193 /*                                                                        */
4194 /*    _nx_smtp_parse_response                             PORTABLE C      */
4195 /*                                                           6.1.6        */
4196 /*  AUTHOR                                                                */
4197 /*                                                                        */
4198 /*    Yuxin Zhou, Microsoft Corporation                                   */
4199 /*                                                                        */
4200 /*  DESCRIPTION                                                           */
4201 /*                                                                        */
4202 /*  This function parses the argument specified by the argument index     */
4203 /*  from the supplied buffer. The first argument is at index 1.           */
4204 /*  If the specified argument can't be found the argument pointer at NULL.*/
4205 /*                                                                        */
4206 /*  Carriage return/line feeds can be treated as word word separator if   */
4207 /*  specified by the crlf_are_word_breaks parameter. For OK TO CONTINUE   */
4208 /*  messages (250), this function searches the whole message for the last */
4209 /*  occurance of the server code e.g. code followed by a space.           */
4210 /*                                                                        */
4211 /*  Carriage return/line feeds are removed if found on the end of the     */
4212 /*  parsed argument.                                                      */
4213 /*                                                                        */
4214 /*  INPUT                                                                 */
4215 /*                                                                        */
4216 /*    client_ptr                        Pointer to client instance        */
4217 /*    buffer                            Pointer to buffer to parse        */
4218 /*    argument_index                    Identify which argument to parse  */
4219 /*    buffer_length                     Size of buffer to parse           */
4220 /*    argument                          Argument to parse from buffer     */
4221 /*    argument_length                   Size of argument buffer           */
4222 /*    crlf_are_word_breaks              Treat \r\n's as word breaks       */
4223 /*                                                                        */
4224 /*  OUTPUT                                                                */
4225 /*                                                                        */
4226 /*     NX_SUCCESS                       Successfully parsed reply code or */
4227 /*                                        authentication challenge        */
4228 /*     NX_SMTP_INVALID_PARAM            Invalid input                     */
4229 /*                                                                        */
4230 /*  CALLS                                                                 */
4231 /*                                                                        */
4232 /*    toupper                           Convert chars to upper case       */
4233 /*                                                                        */
4234 /*  CALLED BY                                                             */
4235 /*                                                                        */
4236 /*    Application Code                                                    */
4237 /*                                                                        */
4238 /*  RELEASE HISTORY                                                       */
4239 /*                                                                        */
4240 /*    DATE              NAME                      DESCRIPTION             */
4241 /*                                                                        */
4242 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4243 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4244 /*                                            resulting in version 6.1    */
4245 /*  04-02-2021     Yuxin Zhou               Modified comment(s),          */
4246 /*                                            improved boundary check,    */
4247 /*                                            resulting in version 6.1.6  */
4248 /*                                                                        */
4249 /**************************************************************************/
_nx_smtp_parse_response(NX_SMTP_CLIENT * client_ptr,UCHAR * buffer,UINT argument_index,UINT buffer_length,UCHAR * argument,UINT argument_length,UINT crlf_are_word_breaks)4250 UINT  _nx_smtp_parse_response(NX_SMTP_CLIENT *client_ptr, UCHAR *buffer, UINT argument_index,
4251                               UINT buffer_length, UCHAR *argument,
4252                               UINT argument_length, UINT crlf_are_word_breaks)
4253 {
4254 
4255 
4256 UINT i = 0;
4257 UINT j = 0;
4258 UINT argument_char_count = 0;
4259 UCHAR *work_ptr;
4260 UINT is_last_code;
4261 
4262 
4263     /* Check for invalid input parameters.  */
4264     if ((buffer == NX_NULL) || (buffer_length == 0) || (argument_index == 0))
4265     {
4266 
4267         return NX_SMTP_INVALID_PARAM;
4268     }
4269 
4270     work_ptr = argument;
4271 
4272     /* Is this the first word?
4273        The first word is the reply code, not an SMTP command parameter */
4274     if (argument_index == 1)
4275     {
4276 
4277         /* Yes, search each character up to the end of the buffer for
4278            the first separator.  */
4279         while (i < buffer_length)
4280         {
4281 
4282             /* Have we reached a word break?  */
4283             if (
4284                  (argument[0] != 0) &&
4285                  ((*buffer == ' ') || (*buffer == '-'))
4286                )
4287             {
4288                 /* Yes, this marks the end of the first argument (word).  */
4289                 break;
4290             }
4291 
4292             /* Are we starting a number?  */
4293             else if ((*buffer >= 0x30) && (*buffer <= 0x39))
4294             {
4295 
4296                 if (work_ptr >= argument + argument_length)
4297                 {
4298                     return(NX_SMTP_INTERNAL_ERROR);
4299                 }
4300 
4301                 /* Yes, copy to buffer. */
4302                 *work_ptr = *buffer;
4303                 work_ptr++;
4304             }
4305             else
4306             {
4307                 /* Not a number. make sure the argument buffer is reset */
4308                 memset(&argument[0], 0, argument_length);
4309                 work_ptr = argument;
4310             }
4311 
4312             /* Get the next character in the buffer.  */
4313             buffer++;
4314             i++;
4315         }
4316     }
4317     else
4318     {
4319         /*  No, we're not parsing the first argument. This is a special case for parsing
4320             the server authentication challenge, not just the reply code.  */
4321 
4322         /*  Mark the start of the argument at the separator after
4323             the end of the previous argument.  */
4324         while ((j < argument_index) && (i < buffer_length))
4325         {
4326 
4327             /* Keep track of the number of separators in the buffer */
4328             /* OD0A marks the end of a line usually in SMTP */
4329 
4330             /* Did we hit a line terminator?  */
4331             if ((*buffer == 0x0D) && (*(buffer + 1) == 0x0A))
4332             {
4333 
4334                 /* Yes, Update the count of separators.  */
4335                 j++;
4336 
4337                 /* Are line terminators as word breaks?  */
4338                 if (crlf_are_word_breaks  == NX_FALSE)
4339                 {
4340 
4341                     /* No, this is the end of the search buffer.
4342                       Argument not parsed from buffer, return error.  */
4343                     return NX_SMTP_INVALID_SERVER_REPLY;
4344                 }
4345 
4346                 /* Get the next character after '\n' byte in the buffer.  */
4347                 i++;
4348                 buffer++;
4349             }
4350             /* Did we hit a space or a dash in the first argument?  */
4351             else if ((*buffer == ' ') || ((*buffer == '-') && (j == 0)))
4352             {
4353 
4354                 /* Yes; these are counted as separators (note that dashes found in arguments
4355                    after the first argument are NOT considered separators.  */
4356                 j++;
4357             }
4358             else
4359             {
4360 
4361                 /* No, is this the argument to parse?  */
4362                 if (j == (argument_index - 1))
4363                 {
4364                     /* Yes; did we go past the argument size limit before the next word break?  */
4365                     if (argument_char_count >= argument_length)
4366                     {
4367 
4368                         /* Yes, unable to finish parsing this buffer. Return error.  */
4369                         return NX_SMTP_INVALID_SERVER_REPLY;
4370                     }
4371 
4372                     /* No, copy the next character into the argument.  */
4373                     argument_char_count++;
4374 
4375                     /* Convert to uppercase if the caller requests.  */
4376                     *argument++ = *buffer;
4377                 }
4378             }
4379 
4380             /* Get the next character in the buffer.  */
4381             buffer++;
4382             i++;
4383         }
4384     }
4385 
4386     /* Determine if this is the last 250 in the message (e.g. followed by a space, not hyphen) */
4387     work_ptr = buffer - 3;
4388 
4389     if ((*work_ptr == '2') && (*(work_ptr + 1) == '5') && (*(work_ptr + 2) == '0') && (*(work_ptr + 3) == '-'))
4390     {
4391 
4392         UINT status;
4393 
4394         /* Parse the rest of the buffer to see if this packet contains the last 250 code. */
4395         status = _nx_smtp_parse_250_response(buffer, buffer_length - i, &is_last_code);
4396         if (status)
4397         {
4398             /* Error with parsing response. */
4399             return status;
4400         }
4401 
4402         /* Did we parse the whole 250 response? */
4403         if (is_last_code != NX_TRUE)
4404         {
4405             /* NO, so we are waiting for another 250 packet. */
4406             client_ptr -> nx_smtp_client_mute = NX_TRUE;
4407         }
4408         else
4409         {
4410 
4411             /* YES, so we are NOT waiting for a packet with the last 250 code. */
4412             client_ptr -> nx_smtp_client_mute = NX_FALSE;
4413         }
4414     }
4415     else if ((*work_ptr == '2') && (*(work_ptr + 1) == '5') && (*(work_ptr + 2) == '0') && (*(work_ptr + 3) == ' '))
4416     {
4417         client_ptr -> nx_smtp_client_mute = NX_FALSE;
4418     }
4419 
4420     return NX_SUCCESS;
4421 }
4422 
4423 /**************************************************************************/
4424 /*                                                                        */
4425 /*  FUNCTION                                               RELEASE        */
4426 /*                                                                        */
4427 /*    _nx_smtp_parse_250_response                         PORTABLE C      */
4428 /*                                                           6.1          */
4429 /*  AUTHOR                                                                */
4430 /*                                                                        */
4431 /*    Yuxin Zhou, Microsoft Corporation                                   */
4432 /*                                                                        */
4433 /*  DESCRIPTION                                                           */
4434 /*                                                                        */
4435 /*  This function is called to search the rest of the message for the last*/
4436 /*  instance of the server code 250. The first 250 has been found but     */
4437 /*  followed by a hyphen, indicating more 250's in the message.           */
4438 /*                                                                        */
4439 /*  INPUT                                                                 */
4440 /*                                                                        */
4441 /*    buffer_ptr                        Pointer to buffer to parse        */
4442 /*    buffer_length                     Size of buffer to parse           */
4443 /*    is_last_code                      Indicate if last 250 found        */
4444 /*                                                                        */
4445 /*  OUTPUT                                                                */
4446 /*                                                                        */
4447 /*     NX_SUCCESS                       Successfully parsed last code     */
4448 /*                                                                        */
4449 /*                                                                        */
4450 /*  CALLED BY                                                             */
4451 /*                                                                        */
4452 /*    _nx_smtp_parse_response          Parse (any) code in server message */
4453 /*                                                                        */
4454 /*  RELEASE HISTORY                                                       */
4455 /*                                                                        */
4456 /*    DATE              NAME                      DESCRIPTION             */
4457 /*                                                                        */
4458 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4459 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4460 /*                                            resulting in version 6.1    */
4461 /*                                                                        */
4462 /**************************************************************************/
_nx_smtp_parse_250_response(UCHAR * buffer_ptr,UINT buffer_length,UINT * is_last_code)4463 UINT _nx_smtp_parse_250_response(UCHAR *buffer_ptr, UINT buffer_length, UINT *is_last_code)
4464 {
4465 
4466     *is_last_code = NX_FALSE;
4467 
4468     /* Are there more 250 codes in this buffer? Advance the buffer
4469        pointer and search for a 250 followed by a space. */
4470 
4471     while (buffer_length > 3)
4472     {
4473         /* Find next 250[sp] in the buffer */
4474         if ((*buffer_ptr == '2') &&
4475             (*(buffer_ptr + 1) == '5') &&
4476             (*(buffer_ptr + 2) == '0') &&
4477             (*(buffer_ptr + 3) == ' '))
4478         {
4479             *is_last_code = NX_TRUE;
4480             break;
4481         }
4482         else
4483         {
4484             buffer_ptr++;
4485             buffer_length--;
4486         }
4487     }
4488 
4489     return NX_SUCCESS;
4490 }
4491 
4492 /**************************************************************************/
4493 /*                                                                        */
4494 /*  FUNCTION                                               RELEASE        */
4495 /*                                                                        */
4496 /*    _nx_smtp_find_crlf                                  PORTABLE C      */
4497 /*                                                           6.1          */
4498 /*  AUTHOR                                                                */
4499 /*                                                                        */
4500 /*    Yuxin Zhou, Microsoft Corporation                                   */
4501 /*                                                                        */
4502 /*  DESCRIPTION                                                           */
4503 /*                                                                        */
4504 /*  This function returns a pointer to the first carriage return/line     */
4505 /*  feed (CRLF) sequence found in the buffer.  If no CRLF is found within */
4506 /*  length specified, the CRLF pointer is left at NULL. If specified the  */
4507 /*  search can start at the end of the buffer and work backwards to the   */
4508 /*  first CRLF found.                                                     */
4509 /*                                                                        */
4510 /*  INPUT                                                                 */
4511 /*                                                                        */
4512 /*    buffer                          Pointer to buffer to search         */
4513 /*    length                          Size of buffer to search            */
4514 /*    CRLF                            Pointer to CRLF found in buffer     */
4515 /*    in_reverse                      Search buffer in reverse direction  */
4516 /*                                                                        */
4517 /*  OUTPUT                                                                */
4518 /*                                                                        */
4519 /*    None                                                                */
4520 /*                                                                        */
4521 /*  CALLS                                                                 */
4522 /*                                                                        */
4523 /*    None                                                                */
4524 /*                                                                        */
4525 /*  CALLED BY                                                             */
4526 /*                                                                        */
4527 /*    Application Code                                                    */
4528 /*                                                                        */
4529 /*  RELEASE HISTORY                                                       */
4530 /*                                                                        */
4531 /*    DATE              NAME                      DESCRIPTION             */
4532 /*                                                                        */
4533 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4534 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4535 /*                                            resulting in version 6.1    */
4536 /*                                                                        */
4537 /**************************************************************************/
_nx_smtp_find_crlf(UCHAR * buffer,UINT length,UCHAR ** CRLF,UINT in_reverse)4538 VOID  _nx_smtp_find_crlf(UCHAR *buffer, UINT length, UCHAR **CRLF, UINT in_reverse)
4539 {
4540 
4541 UINT i = 0;
4542 
4543     *CRLF = NULL;
4544 
4545     if ((buffer == NX_NULL) || (length == 0))
4546     {
4547         return;
4548     }
4549 
4550 
4551     /* Search for CRLF from end to start of buffer (reverse) */
4552     if (in_reverse == NX_TRUE)
4553     {
4554 
4555         /* Move pointer out to the end of the buffer.  */
4556         buffer += length - 1;
4557 
4558         while (i < length - 1)
4559         {
4560             if (*(buffer - 1) == 0x0D && *buffer == 0x0A)
4561             {
4562                 /* Set the location of CRLF sequence.  */
4563                 *CRLF = buffer -  1;
4564                 break;
4565             }
4566 
4567             /* Move the pointer back one.  */
4568             buffer--;
4569 
4570             /* Keep track how many bytes we've gone.  */
4571             i++;
4572         }
4573     }
4574     /* Search for CRLF starting at the beginning of the buffer */
4575     else
4576     {
4577         while( i < length - 1)
4578         {
4579             if (*buffer == 0x0D && *(buffer + 1) == 0x0A)
4580             {
4581                 /* Set the location of CRLF sequence.  */
4582                 *CRLF = buffer;
4583 
4584                 break;
4585             }
4586             i++;
4587             buffer++;
4588         }
4589     }
4590 
4591     return ;
4592 }
4593