1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11 /**************************************************************************/
12 /**************************************************************************/
13 /** */
14 /** NetX POP3 Client Component */
15 /** */
16 /** Post Office Protocol Version 3 (POP3) */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 /**************************************************************************/
22 /* */
23 /* APPLICATION INTERFACE DEFINITION RELEASE */
24 /* */
25 /* nxd_pop3_client.c PORTABLE C */
26 /* 6.1 */
27 /* AUTHOR */
28 /* */
29 /* Yuxin Zhou, Microsoft Corporation */
30 /* */
31 /* DESCRIPTION */
32 /* */
33 /* This file defines the NetX Post Office Protocol (POP3) */
34 /* Client component, including all data types and external references. */
35 /* It is assumed that tx_api.h, tx_port.h, nx_api.h, and nx_port.h, */
36 /* have already been included. */
37 /* */
38 /* RELEASE HISTORY */
39 /* */
40 /* DATE NAME DESCRIPTION */
41 /* */
42 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
43 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
44 /* resulting in version 6.1 */
45 /* */
46 /**************************************************************************/
47
48 #define NX_POP3_CLIENT_SOURCE_CODE
49
50 /* Force error checking to be disabled in this module */
51
52 #ifndef NX_DISABLE_ERROR_CHECKING
53 #define NX_DISABLE_ERROR_CHECKING
54 #endif
55
56
57 #include "nx_api.h"
58 #include "nx_md5.h"
59 #include "nx_ip.h"
60 #include "nxd_pop3_client.h"
61 #include "nx_ipv6.h"
62 #include <ctype.h>
63
64 /* The following array of state handlers is indexed by the state. */
65
66 /**************************************************************************/
67 /* */
68 /* FUNCTION RELEASE */
69 /* */
70 /* _nxe_pop3_client_create PORTABLE C */
71 /* 6.1 */
72 /* AUTHOR */
73 /* */
74 /* Yuxin Zhou, Microsoft Corporation */
75 /* */
76 /* DESCRIPTION */
77 /* */
78 /* This function performs error checking on the create POP3 client */
79 /* service (IPv4 only). */
80 /* */
81 /* Note: The string lengths of client_name and client_password are */
82 /* limited by internal buffer size. */
83 /* */
84 /* INPUT */
85 /* */
86 /* client_ptr Pointer to client struct */
87 /* APOP_authentication 1=enable APOP; 0=disable APOP */
88 /* ip_ptr Pointer to client IP instance */
89 /* packet_pool_ptr Pointer to client packet pool */
90 /* server_ip_address POP3 server IP address */
91 /* server_port POP3 server port */
92 /* client_name Client POP3 user name */
93 /* client_password Client POP3 password */
94 /* */
95 /* OUTPUT */
96 /* */
97 /* NX_PTR_ERROR Invalid pointer parameter */
98 /* status Actual completion status */
99 /* */
100 /* CALLS */
101 /* */
102 /* _nx_pop3_client_create Creates the POP3 client */
103 /* */
104 /* CALLED BY */
105 /* */
106 /* Application Code */
107 /* */
108 /* RELEASE HISTORY */
109 /* */
110 /* DATE NAME DESCRIPTION */
111 /* */
112 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
113 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
114 /* resulting in version 6.1 */
115 /* */
116 /**************************************************************************/
_nxe_pop3_client_create(NX_POP3_CLIENT * client_ptr,UINT APOP_authentication,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool_ptr,ULONG server_ip_address,ULONG server_port,CHAR * client_name,CHAR * client_password)117 UINT _nxe_pop3_client_create(NX_POP3_CLIENT *client_ptr, UINT APOP_authentication, NX_IP *ip_ptr,
118 NX_PACKET_POOL *packet_pool_ptr, ULONG server_ip_address, ULONG server_port, CHAR *client_name,
119 CHAR *client_password)
120 {
121
122 #ifndef NX_DISABLE_IPV4
123 UINT status;
124
125
126 /* Check for valid input pointers. */
127 if ((ip_ptr == NX_NULL) || (client_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) || (client_name == NX_NULL) ||
128 (client_password == NX_NULL))
129 {
130
131 /* Return pointer error. */
132 return(NX_PTR_ERROR);
133 }
134
135 if ((ip_ptr -> nx_ip_id != NX_IP_ID) || (server_ip_address == 0) || (server_port == 0))
136 {
137
138 return NX_POP3_PARAM_ERROR;
139 }
140
141 /* Call the actual client create service. */
142 status = _nx_pop3_client_create(client_ptr,
143 APOP_authentication,
144 ip_ptr, packet_pool_ptr,
145 server_ip_address, server_port, client_name,
146 client_password);
147
148 /* Return completion status. */
149 return(status);
150 #else
151 NX_PARAMETER_NOT_USED(client_ptr);
152 NX_PARAMETER_NOT_USED(APOP_authentication);
153 NX_PARAMETER_NOT_USED(ip_ptr);
154 NX_PARAMETER_NOT_USED(packet_pool_ptr);
155 NX_PARAMETER_NOT_USED(server_ip_address);
156 NX_PARAMETER_NOT_USED(server_port);
157 NX_PARAMETER_NOT_USED(client_name);
158 NX_PARAMETER_NOT_USED(client_password);
159
160 return(NX_NOT_SUPPORTED);
161 #endif /* NX_DISABLE_IPV4 */
162 }
163
164
165 /**************************************************************************/
166 /* */
167 /* FUNCTION RELEASE */
168 /* */
169 /* _nx_pop3_client_create PORTABLE C */
170 /* 6.1 */
171 /* AUTHOR */
172 /* */
173 /* Yuxin Zhou, Microsoft Corporation */
174 /* */
175 /* DESCRIPTION */
176 /* */
177 /* This function creates a POP3 Client on the specified IP instance. */
178 /* */
179 /* Note: The string lengths of client_name and client_password are */
180 /* limited by internal buffer size. */
181 /* */
182 /* INPUT */
183 /* */
184 /* client_ptr Pointer to client struct */
185 /* APOP_authentication 1=enable APOP; 0=disable APOP */
186 /* ip_ptr Pointer to client IP instance */
187 /* packet_pool_ptr Pointer to client packet pool */
188 /* server_ip_address POP3 server IP address */
189 /* server_port POP3 server port */
190 /* client_name Client POP3 user name */
191 /* client_password Client POP3 password */
192 /* */
193 /* OUTPUT */
194 /* */
195 /* NX_SUCCESS Successful completion status */
196 /* */
197 /* CALLED BY */
198 /* */
199 /* Application Code */
200 /* */
201 /* CALLS */
202 /* */
203 /* _nxd_pop3_client_create Duo Client POP3 create service */
204 /* */
205 /* RELEASE HISTORY */
206 /* */
207 /* DATE NAME DESCRIPTION */
208 /* */
209 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
210 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
211 /* resulting in version 6.1 */
212 /* */
213 /**************************************************************************/
_nx_pop3_client_create(NX_POP3_CLIENT * client_ptr,UINT APOP_authentication,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool_ptr,ULONG server_ip_address,ULONG server_port,CHAR * client_name,CHAR * client_password)214 UINT _nx_pop3_client_create(NX_POP3_CLIENT *client_ptr, UINT APOP_authentication, NX_IP *ip_ptr,
215 NX_PACKET_POOL *packet_pool_ptr, ULONG server_ip_address, ULONG server_port, CHAR *client_name,
216 CHAR *client_password)
217 {
218
219 #ifndef NX_DISABLE_IPV4
220 UINT status;
221 NXD_ADDRESS server_address;
222
223 server_address.nxd_ip_address.v4 = server_ip_address;
224 server_address.nxd_ip_version = NX_IP_VERSION_V4;
225
226 status = _nxd_pop3_client_create(client_ptr,
227 APOP_authentication,
228 ip_ptr, packet_pool_ptr,
229 &server_address, server_port, client_name,
230 client_password);
231
232 return status;
233 #else
234 NX_PARAMETER_NOT_USED(client_ptr);
235 NX_PARAMETER_NOT_USED(APOP_authentication);
236 NX_PARAMETER_NOT_USED(ip_ptr);
237 NX_PARAMETER_NOT_USED(packet_pool_ptr);
238 NX_PARAMETER_NOT_USED(server_ip_address);
239 NX_PARAMETER_NOT_USED(server_port);
240 NX_PARAMETER_NOT_USED(client_name);
241 NX_PARAMETER_NOT_USED(client_password);
242
243 return(NX_NOT_SUPPORTED);
244 #endif /* NX_DISABLE_IPV4 */
245 }
246
247
248 /**************************************************************************/
249 /* */
250 /* FUNCTION RELEASE */
251 /* */
252 /* _nxde_pop3_client_create PORTABLE C */
253 /* 6.1 */
254 /* AUTHOR */
255 /* */
256 /* Yuxin Zhou, Microsoft Corporation */
257 /* */
258 /* DESCRIPTION */
259 /* */
260 /* This function performs error checking on the create POP3 client */
261 /* service (supports IPv6 and IPv4). */
262 /* */
263 /* Note: The string lengths of client_name and client_password are */
264 /* limited by internal buffer size. */
265 /* */
266 /* INPUT */
267 /* */
268 /* client_ptr Pointer to client struct */
269 /* APOP_authentication 1=enable APOP; 0=disable APOP */
270 /* ip_ptr Pointer to client IP instance */
271 /* packet_pool_ptr Pointer to client packet pool */
272 /* server_duo_address POP3 server IPv6/IPv4 address */
273 /* server_port POP3 server port */
274 /* client_name Client POP3 user name */
275 /* client_password Client POP3 password */
276 /* */
277 /* OUTPUT */
278 /* */
279 /* NX_PTR_ERROR Invalid pointer parameter */
280 /* status Actual completion status */
281 /* */
282 /* CALLS */
283 /* */
284 /* _nxd_pop3_client_create Creates the POP3 client */
285 /* */
286 /* CALLED BY */
287 /* */
288 /* Application Code */
289 /* */
290 /* RELEASE HISTORY */
291 /* */
292 /* DATE NAME DESCRIPTION */
293 /* */
294 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
295 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
296 /* resulting in version 6.1 */
297 /* */
298 /**************************************************************************/
_nxde_pop3_client_create(NX_POP3_CLIENT * client_ptr,UINT APOP_authentication,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool_ptr,NXD_ADDRESS * server_ip_address,ULONG server_port,CHAR * client_name,CHAR * client_password)299 UINT _nxde_pop3_client_create(NX_POP3_CLIENT *client_ptr, UINT APOP_authentication, NX_IP *ip_ptr,
300 NX_PACKET_POOL *packet_pool_ptr, NXD_ADDRESS *server_ip_address, ULONG server_port, CHAR *client_name,
301 CHAR *client_password)
302 {
303
304 UINT status;
305
306
307 /* Check for valid input pointers. */
308 if ((ip_ptr == NX_NULL) || (client_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) || (server_ip_address == NX_NULL) ||
309 (client_name == NX_NULL) || (client_password == NX_NULL))
310 {
311
312 /* Return pointer error. */
313 return(NX_PTR_ERROR);
314 }
315
316 if ((ip_ptr -> nx_ip_id != NX_IP_ID) || (server_port == 0))
317 {
318
319 return NX_POP3_PARAM_ERROR;
320 }
321
322 /* Call the actual client create service. */
323 status = _nxd_pop3_client_create(client_ptr,
324 APOP_authentication,
325 ip_ptr, packet_pool_ptr,
326 server_ip_address, server_port, client_name,
327 client_password);
328
329 /* Return completion status. */
330 return(status);
331
332 }
333
334
335 /**************************************************************************/
336 /* */
337 /* FUNCTION RELEASE */
338 /* */
339 /* _nxd_pop3_client_create PORTABLE C */
340 /* 6.1 */
341 /* AUTHOR */
342 /* */
343 /* Yuxin Zhou, Microsoft Corporation */
344 /* */
345 /* DESCRIPTION */
346 /* */
347 /* This function creates a POP3 Client on the specified IP instance. */
348 /* This supports both IPv6 and IPv4 POP3 server connections. */
349 /* */
350 /* Note: The string lengths of client_name and client_password are */
351 /* limited by internal buffer size. */
352 /* */
353 /* INPUT */
354 /* */
355 /* client_ptr Pointer to client struct */
356 /* APOP_authentication 1=enable APOP; 0=disable APOP */
357 /* ip_ptr Pointer to client IP instance */
358 /* packet_pool_ptr Pointer to client packet pool */
359 /* server_ip_address POP3 server IP address */
360 /* server_port POP3 server port */
361 /* client_name Client POP3 user name */
362 /* client_password Client POP3 password */
363 /* */
364 /* OUTPUT */
365 /* */
366 /* NX_SUCCESS Successful completion status */
367 /* */
368 /* CALLED BY */
369 /* */
370 /* Application Code */
371 /* */
372 /* CALLS */
373 /* */
374 /* nx_tcp_socket_create NetX TCP socket create service */
375 /* _nxd_pop3_client_connect Connect POP3 Client to Server */
376 /* */
377 /* RELEASE HISTORY */
378 /* */
379 /* DATE NAME DESCRIPTION */
380 /* */
381 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
382 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
383 /* verified memcpy use cases, */
384 /* resulting in version 6.1 */
385 /* */
386 /**************************************************************************/
_nxd_pop3_client_create(NX_POP3_CLIENT * client_ptr,UINT APOP_authentication,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool_ptr,NXD_ADDRESS * server_ip_address,ULONG server_port,CHAR * client_name,CHAR * client_password)387 UINT _nxd_pop3_client_create(NX_POP3_CLIENT *client_ptr, UINT APOP_authentication, NX_IP *ip_ptr,
388 NX_PACKET_POOL *packet_pool_ptr, NXD_ADDRESS *server_ip_address, ULONG server_port, CHAR *client_name,
389 CHAR *client_password)
390
391 {
392
393 UINT status;
394 UINT client_name_length;
395 UINT client_password_length;
396
397
398 client_ptr -> nx_pop3_client_ready_to_download = NX_FALSE;
399
400 if (_nx_utility_string_length_check(client_name, &client_name_length, NX_POP3_MAX_USERNAME) ||
401 _nx_utility_string_length_check(client_password, &client_password_length, NX_POP3_MAX_PASSWORD))
402 {
403
404 return NX_POP3_PARAM_ERROR;
405 }
406
407 /* Null the members of NX_POP3_CLIENT. */
408 memset(client_ptr, 0, sizeof(NX_POP3_CLIENT));
409
410 /* Configure Client identification. */
411 memset(client_ptr -> nx_pop3_client_name, 0, NX_POP3_MAX_USERNAME);
412 memcpy(client_ptr -> nx_pop3_client_name, client_name, client_name_length); /* Use case of memcpy is verified. */
413 memset(client_ptr -> nx_pop3_client_password, 0, NX_POP3_MAX_PASSWORD);
414 memcpy(client_ptr -> nx_pop3_client_password, client_password, client_password_length); /* Use case of memcpy is verified. */
415
416 /* Configure Client POP3 authentication options. */
417 client_ptr -> nx_pop3_client_enable_APOP_authentication = APOP_authentication;
418
419 /* Create a tcp socket to send/receive POP3 data. */
420 status = nx_tcp_socket_create(ip_ptr, &client_ptr -> nx_pop3_client_tcp_socket, "POP3 Client socket",
421 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
422 NX_POP3_CLIENT_TCP_WINDOW_SIZE,
423 NX_NULL, NX_NULL);
424
425 /* Check for error. */
426 if (status != NX_SUCCESS)
427 {
428
429 /* Return error status. */
430 return(status);
431 }
432
433 /* Configure Client NetX and TCP/IP options. */
434 client_ptr -> nx_pop3_client_packet_pool_ptr = packet_pool_ptr;
435
436 status = _nxd_pop3_client_connect(client_ptr, server_ip_address, server_port);
437
438 /* Return successful completion status. */
439 return(status);
440 }
441
442
443
444 /**************************************************************************/
445 /* */
446 /* FUNCTION RELEASE */
447 /* */
448 /* _nxe_pop3_client_delete PORTABLE C */
449 /* 6.1 */
450 /* AUTHOR */
451 /* */
452 /* Yuxin Zhou, Microsoft Corporation */
453 /* */
454 /* DESCRIPTION */
455 /* */
456 /* This function performs error checking on the POP3 Client delete */
457 /* service. */
458 /* */
459 /* INPUT */
460 /* */
461 /* client_ptr Pointer to client struct */
462 /* */
463 /* OUTPUT */
464 /* */
465 /* NX_PTR_ERROR Invalid pointer input */
466 /* status Actual completion status */
467 /* */
468 /* CALLED BY */
469 /* */
470 /* Application Code */
471 /* */
472 /* CALLS */
473 /* */
474 /* _nx_pop3_client_delete Actual Client delete service */
475 /* */
476 /* RELEASE HISTORY */
477 /* */
478 /* DATE NAME DESCRIPTION */
479 /* */
480 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
481 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
482 /* resulting in version 6.1 */
483 /* */
484 /**************************************************************************/
_nxe_pop3_client_delete(NX_POP3_CLIENT * client_ptr)485 UINT _nxe_pop3_client_delete(NX_POP3_CLIENT *client_ptr)
486 {
487
488 UINT status;
489
490
491 /* Check for valid input parameter. */
492 if (client_ptr == NX_NULL)
493 {
494
495 /* Return error status. */
496 return(NX_PTR_ERROR);
497 }
498
499 /* Call client create function. */
500 status = _nx_pop3_client_delete(client_ptr);
501
502 /* Return completion status. */
503 return(status);
504 }
505
506
507 /**************************************************************************/
508 /* */
509 /* FUNCTION RELEASE */
510 /* */
511 /* _nx_pop3_client_delete PORTABLE C */
512 /* 6.1 */
513 /* AUTHOR */
514 /* */
515 /* Yuxin Zhou, Microsoft Corporation */
516 /* */
517 /* DESCRIPTION */
518 /* */
519 /* This function deletes the specified POP3 Client. */
520 /* */
521 /* INPUT */
522 /* */
523 /* client_ptr Pointer to client struct */
524 /* */
525 /* OUTPUT */
526 /* */
527 /* NX_SUCCESS Successful completion status */
528 /* status Actual completion status */
529 /* */
530 /* CALLED BY */
531 /* */
532 /* Application Code */
533 /* */
534 /* CALLS */
535 /* */
536 /* nx_tcp_socket_disconnect Closes the TCP connection */
537 /* nx_tcp_client_socket_unbind Releases (unbinds) the TCP port */
538 /* nx_tcp_socket_delete Deletes unbound TCP socket */
539 /* */
540 /* RELEASE HISTORY */
541 /* */
542 /* DATE NAME DESCRIPTION */
543 /* */
544 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
545 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
546 /* resulting in version 6.1 */
547 /* */
548 /**************************************************************************/
_nx_pop3_client_delete(NX_POP3_CLIENT * client_ptr)549 UINT _nx_pop3_client_delete(NX_POP3_CLIENT *client_ptr)
550 {
551
552 if (client_ptr -> nx_pop3_client_message_ptr)
553 {
554 nx_packet_release(client_ptr -> nx_pop3_client_message_ptr);
555 }
556
557 /* Yes, so disconnect client socket from server. */
558 nx_tcp_socket_disconnect(&client_ptr -> nx_pop3_client_tcp_socket, NX_POP3_CLIENT_DISCONNECT_TIMEOUT);
559
560 /* Unbind the port from client socket. */
561 nx_tcp_client_socket_unbind(&client_ptr -> nx_pop3_client_tcp_socket);
562
563 /* Release client socket. */
564 nx_tcp_socket_delete(&client_ptr -> nx_pop3_client_tcp_socket);
565
566 /* Clear the members of NX_POP3_CLIENT. */
567 memset(client_ptr, 0, sizeof(NX_POP3_CLIENT));
568
569 /* Return completion status. */
570 return(NX_SUCCESS);
571 }
572
573
574 /**************************************************************************/
575 /* */
576 /* FUNCTION RELEASE */
577 /* */
578 /* _nxe_pop3_client_mail_items_get PORTABLE C */
579 /* 6.1 */
580 /* AUTHOR */
581 /* */
582 /* Yuxin Zhou, Microsoft Corporation */
583 /* */
584 /* DESCRIPTION */
585 /* */
586 /* This function performs error checking for the get mail items in */
587 /* client mailbox service. */
588 /* */
589 /* INPUT */
590 /* */
591 /* client_ptr Pointer to client struct */
592 /* number_mail_items Pointer to items in mailbox */
593 /* maildrop_total_size Pointer to total mailbox size */
594 /* */
595 /* OUTPUT */
596 /* */
597 /* NX_PTR_ERROR Invalid pointer parameter */
598 /* status Actual completion status */
599 /* */
600 /* CALLS */
601 /* */
602 /* _nxe_pop3_client_mail_items_get Actual get mail items service */
603 /* */
604 /* CALLED BY */
605 /* */
606 /* Application Code */
607 /* */
608 /* RELEASE HISTORY */
609 /* */
610 /* DATE NAME DESCRIPTION */
611 /* */
612 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
613 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
614 /* resulting in version 6.1 */
615 /* */
616 /**************************************************************************/
_nxe_pop3_client_mail_items_get(NX_POP3_CLIENT * client_ptr,UINT * number_mail_items,ULONG * maildrop_total_size)617 UINT _nxe_pop3_client_mail_items_get(NX_POP3_CLIENT *client_ptr, UINT *number_mail_items, ULONG *maildrop_total_size)
618 {
619
620 UINT status;
621
622
623 /* Check for invalid pointer inpu. */
624 if ((client_ptr == NX_NULL) || (number_mail_items == NX_NULL) || (maildrop_total_size == NX_NULL))
625 {
626
627 return NX_PTR_ERROR;
628 }
629
630 status = _nx_pop3_client_mail_items_get(client_ptr, number_mail_items, maildrop_total_size);
631
632 return status;
633 }
634
635
636 /**************************************************************************/
637 /* */
638 /* FUNCTION RELEASE */
639 /* */
640 /* _nx_pop3_client_mail_items_get PORTABLE C */
641 /* 6.1 */
642 /* AUTHOR */
643 /* */
644 /* Yuxin Zhou, Microsoft Corporation */
645 /* */
646 /* DESCRIPTION */
647 /* */
648 /* This function retrieves the number of items and total size in bytes */
649 /* of mail data in the Client's mailbox. */
650 /* */
651 /* INPUT */
652 /* */
653 /* client_ptr Pointer to client struct */
654 /* number_mail_items Pointer to items in mailbox */
655 /* maildrop_total_size Pointer to total mailbox size */
656 /* */
657 /* OUTPUT */
658 /* */
659 /* NX_PTR_ERROR Invalid pointer parameter */
660 /* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
661 /* Packet too small for command */
662 /* status Actual completion status */
663 /* */
664 /* CALLS */
665 /* */
666 /* nx_packet_allocate Allocate packet from packet pool */
667 /* nx_packet_release Release packet back to pool */
668 /* nx_tcp_socket_send Send packet out TCP socket */
669 /* nx_tcp_socket_receive Retrieve packet from TCP socket */
670 /* _nx_pop3_parse_response Extract word from server response */
671 /* */
672 /* CALLED BY */
673 /* */
674 /* Application Code */
675 /* */
676 /* RELEASE HISTORY */
677 /* */
678 /* DATE NAME DESCRIPTION */
679 /* */
680 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
681 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
682 /* verified memcpy use cases, */
683 /* resulting in version 6.1 */
684 /* */
685 /**************************************************************************/
_nx_pop3_client_mail_items_get(NX_POP3_CLIENT * client_ptr,UINT * number_mail_items,ULONG * maildrop_total_size)686 UINT _nx_pop3_client_mail_items_get(NX_POP3_CLIENT *client_ptr, UINT *number_mail_items, ULONG *maildrop_total_size)
687 {
688
689 UINT status;
690 NX_PACKET *packet_ptr, *recv_packet_ptr;
691 CHAR *buffer;
692 CHAR argument[10];
693 UINT packet_type;
694
695 /* Determine type of packet to allocate. */
696 if (client_ptr -> nx_pop3_client_tcp_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
697 packet_type = NX_IPv6_TCP_PACKET;
698 else
699 packet_type = NX_IPv4_TCP_PACKET;
700
701 /* Allocate a packet. */
702 status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
703 &packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
704
705 /* Check for error. */
706 if (status != NX_SUCCESS)
707 {
708
709 /* Return the error condition. */
710 return(status);
711 }
712
713 /* Check for sufficient packet buffer size for command. */
714 if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_STAT) - 1) + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= packet_ptr -> nx_packet_data_end)
715 {
716
717 /* Release the packet. */
718 nx_packet_release(packet_ptr);
719
720 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
721 }
722
723 /* Send the STAT command. */
724 buffer = (CHAR *)(packet_ptr -> nx_packet_prepend_ptr);
725
726 memcpy(buffer, NX_POP3_COMMAND_STAT, (sizeof(NX_POP3_COMMAND_STAT) - 1)); /* Use case of memcpy is verified. */
727 packet_ptr -> nx_packet_length = (sizeof(NX_POP3_COMMAND_STAT) - 1);
728 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_STAT) - 1);
729 buffer += (sizeof(NX_POP3_COMMAND_STAT) - 1);
730
731 memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
732 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
733 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
734 buffer += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
735
736 /* Send the packet out. */
737 status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
738
739 /* Check for error. */
740 if (status != NX_SUCCESS)
741 {
742
743 /* Release the packet. */
744 nx_packet_release(packet_ptr);
745
746 /* Return the error condition. */
747 return(status);
748 }
749
750 /* Clear existing Client maildrop data. */
751 client_ptr -> nx_pop3_client_total_message_size = 0;
752 client_ptr -> nx_pop3_client_maildrop_items = 0;
753
754 /* Receive server reply. */
755 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
756
757 /* Check for error. */
758 if (status != NX_SUCCESS)
759 {
760
761 /* Return error condition. */
762 return(status);
763 }
764
765 #ifndef NX_DISABLE_PACKET_CHAIN
766 if (recv_packet_ptr -> nx_packet_next)
767 {
768
769 /* Chained packet is not supported. */
770 nx_packet_release(recv_packet_ptr);
771 return(NX_INVALID_PACKET);
772 }
773 #endif /* NX_DISABLE_PACKET_CHAIN */
774
775 /* Set a pointer to the packet data. */
776 buffer = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
777
778 /* Parse the first argument of the server reply. */
779 _nx_pop3_parse_response(buffer, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
780
781 /* Initialize status to server error received. */
782 status = NX_POP3_SERVER_ERROR_STATUS;
783
784 /* Did the server accept the Client command? */
785 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
786 {
787
788 /* Yes. Clear memory for parsing the mail item count. */
789 memset(argument, 0, 5);
790
791 /* Get the number of messages. */
792 _nx_pop3_parse_response(buffer, 2, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
793
794 /* Check if argument parsed successfully. */
795 if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
796 {
797
798 /* It was; update session maildrop items. */
799 client_ptr -> nx_pop3_client_maildrop_items = strtoul(argument, NULL, 10);
800
801 /* Get total mail message data next. */
802 memset(argument, 0, 5);
803
804 /* Get the size in bytes of message data. */
805 _nx_pop3_parse_response(buffer, 3, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
806
807 /* Check if argument parsed successfully. */
808 if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
809 {
810
811 /* It was; update total message data. */
812 client_ptr -> nx_pop3_client_total_message_size = strtoul(argument, NULL, 10);
813
814 status = NX_SUCCESS;
815 }
816 }
817 }
818
819 *maildrop_total_size = client_ptr -> nx_pop3_client_total_message_size;
820 *number_mail_items = client_ptr -> nx_pop3_client_maildrop_items;
821
822 nx_packet_release(recv_packet_ptr);
823
824 /* Return completion status. */
825 return status;
826 }
827
828
829 /**************************************************************************/
830 /* */
831 /* FUNCTION RELEASE */
832 /* */
833 /* _nxe_pop3_client_get_mail_item PORTABLE C */
834 /* 6.1 */
835 /* AUTHOR */
836 /* */
837 /* Yuxin Zhou, Microsoft Corporation */
838 /* */
839 /* DESCRIPTION */
840 /* */
841 /* This function performs error checking for the get mail item size */
842 /* service. */
843 /* */
844 /* INPUT */
845 /* */
846 /* client_ptr Pointer to client struct */
847 /* mail_item Index into POP3 mailbox */
848 /* item_size Pointer to mail size */
849 /* */
850 /* OUTPUT */
851 /* */
852 /* NX_PTR_ERROR Invalid pointer parameter */
853 /* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
854 /* status Actual completion status */
855 /* */
856 /* CALLS */
857 /* */
858 /* _nx_pop3_client_get_mail_size Actual get mail size service */
859 /* */
860 /* CALLED BY */
861 /* */
862 /* Application Code */
863 /* */
864 /* RELEASE HISTORY */
865 /* */
866 /* DATE NAME DESCRIPTION */
867 /* */
868 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
869 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
870 /* resulting in version 6.1 */
871 /* */
872 /**************************************************************************/
_nxe_pop3_client_mail_item_size_get(NX_POP3_CLIENT * client_ptr,UINT mail_item,ULONG * size)873 UINT _nxe_pop3_client_mail_item_size_get(NX_POP3_CLIENT *client_ptr, UINT mail_item, ULONG *size)
874 {
875
876 UINT status;
877
878
879 /* Check for invalid pointer input. */
880 if ((client_ptr == NX_NULL) || (size == NX_NULL))
881 {
882
883 return NX_PTR_ERROR;
884 }
885
886 /* Check for an invalid index. */
887 if (mail_item == 0)
888 {
889 return NX_POP3_CLIENT_INVALID_INDEX;
890 }
891
892 status = _nx_pop3_client_mail_item_size_get(client_ptr, mail_item, size);
893
894 return status;
895 }
896
897
898 /**************************************************************************/
899 /* */
900 /* FUNCTION RELEASE */
901 /* */
902 /* _nx_pop3_client_mail_item_size_get PORTABLE C */
903 /* 6.1 */
904 /* AUTHOR */
905 /* */
906 /* Yuxin Zhou, Microsoft Corporation */
907 /* */
908 /* DESCRIPTION */
909 /* */
910 /* This function sends a LIST command for the specified mail item and */
911 /* processes the server response for size of the requested item. Note */
912 /* that there is considerable discrepancy between reported size and */
913 /* actual size, with the reported size usually 15% or more larger than */
914 /* actual. */
915 /* */
916 /* INPUT */
917 /* */
918 /* client_ptr Pointer to client struct */
919 /* mail_item Index into POP3 mailbox */
920 /* size Pointer to mail item size */
921 /* */
922 /* OUTPUT */
923 /* */
924 /* NX_PTR_ERROR Invalid pointer parameter */
925 /* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
926 /* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
927 /* Packet too small for command */
928 /* status Actual completion status */
929 /* */
930 /* CALLS */
931 /* */
932 /* nx_packet_allocate Allocate packet from packet pool */
933 /* nx_packet_release Release packet back to pool */
934 /* nx_tcp_socket_send Send packet out TCP socket */
935 /* nx_tcp_socket_receive Retrieve packet from TCP socket */
936 /* _nx_pop3_parse_response Extract word from server response */
937 /* _nx_pop3_server_number_convert Convert integer to ascii */
938 /* */
939 /* CALLED BY */
940 /* */
941 /* Application Code */
942 /* */
943 /* RELEASE HISTORY */
944 /* */
945 /* DATE NAME DESCRIPTION */
946 /* */
947 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
948 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
949 /* verified memcpy use cases, */
950 /* resulting in version 6.1 */
951 /* */
952 /**************************************************************************/
_nx_pop3_client_mail_item_size_get(NX_POP3_CLIENT * client_ptr,UINT mail_item,ULONG * size)953 UINT _nx_pop3_client_mail_item_size_get(NX_POP3_CLIENT *client_ptr, UINT mail_item, ULONG *size)
954 {
955
956 NX_PACKET *packet_ptr, *recv_packet_ptr;
957 CHAR *buffer_ptr;
958 UINT num_size;
959 UINT status;
960 CHAR argument[10];
961 UINT packet_type;
962
963
964 /* Initialize mail box to having zero items. */
965 *size = 0;
966
967 /* Verify mail_item is valid index (less than total number items in mailbox. */
968 if (mail_item > client_ptr -> nx_pop3_client_maildrop_items)
969 {
970 return NX_POP3_INVALID_MAIL_ITEM;
971 }
972
973 /* Determine which packet type to allocate. */
974 if (client_ptr -> nx_pop3_client_tcp_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
975 packet_type = NX_IPv6_TCP_PACKET;
976 else
977 packet_type = NX_IPv4_TCP_PACKET;
978
979 /* Allocate a packet. */
980 status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
981 &packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
982
983 /* Check for error. */
984 if (status != NX_SUCCESS)
985 {
986
987 /* Return the error condition. */
988 return(status);
989 }
990
991 num_size = _nx_pop3_server_number_convert(mail_item, &argument[0]);
992
993 /* Determine if the packet payload is large enough for LIST command. */
994 if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_LIST) - 1) + 1 +
995 num_size + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= packet_ptr -> nx_packet_data_end)
996 {
997
998 /* Release the packet. */
999 nx_packet_release(packet_ptr);
1000
1001 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
1002 }
1003
1004 buffer_ptr = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
1005
1006 /* Send LIST mail_item query to server */
1007 memcpy(buffer_ptr, NX_POP3_COMMAND_LIST, (sizeof(NX_POP3_COMMAND_LIST) - 1)); /* Use case of memcpy is verified. */
1008 packet_ptr -> nx_packet_length = (sizeof(NX_POP3_COMMAND_LIST) - 1);
1009 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_LIST) - 1);
1010 buffer_ptr += (sizeof(NX_POP3_COMMAND_LIST) - 1);
1011
1012 memcpy(buffer_ptr, " ", 1); /* Use case of memcpy is verified. */
1013 packet_ptr -> nx_packet_length++;
1014 packet_ptr -> nx_packet_append_ptr++;
1015 buffer_ptr++;
1016
1017 memcpy(buffer_ptr, &argument[0], num_size); /* Use case of memcpy is verified. */
1018 packet_ptr -> nx_packet_length += num_size;
1019 packet_ptr -> nx_packet_append_ptr += num_size;
1020 buffer_ptr += num_size;
1021
1022 memcpy(buffer_ptr, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
1023 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1024 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1025 buffer_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1026
1027 /* Send the packet out. */
1028 status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
1029
1030 /* Check for error. */
1031 if (status != NX_SUCCESS)
1032 {
1033
1034 /* Release the packet. */
1035 nx_packet_release(packet_ptr);
1036
1037 /* Return the error condition. */
1038 return(status);
1039 }
1040
1041 /* Receive server reply over session socket. */
1042 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
1043
1044 /* Check for error. */
1045 if (status != NX_SUCCESS)
1046 {
1047
1048 /* Return error condition. */
1049 return(status);
1050 }
1051
1052 #ifndef NX_DISABLE_PACKET_CHAIN
1053 if (recv_packet_ptr -> nx_packet_next)
1054 {
1055
1056 /* Chained packet is not supported. */
1057 nx_packet_release(recv_packet_ptr);
1058 return(NX_INVALID_PACKET);
1059 }
1060 #endif /* NX_DISABLE_PACKET_CHAIN */
1061
1062 /* Set a pointer to the packet data. */
1063 buffer_ptr = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
1064
1065 /* Initialize status to bad reply error condition. */
1066 status = NX_POP3_SERVER_ERROR_STATUS;
1067
1068 /* Parse the first argument of the server reply. */
1069 _nx_pop3_parse_response(buffer_ptr, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
1070
1071 /* Did the server accept the Client command? */
1072 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
1073 {
1074
1075 /* Clear memory for parsing the mail item count. */
1076 memset(argument, 0, 5);
1077
1078 /* Extact the message size. */
1079 _nx_pop3_parse_response(buffer_ptr, 2, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
1080
1081 /* Check if argument parsed successfully. */
1082 if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
1083 {
1084
1085 /* It was; verify it matches the input mail index. */
1086 UINT server_maildrop_items = strtoul(argument, NULL, 10);
1087
1088 if (mail_item == server_maildrop_items)
1089 {
1090
1091 /* It does. Parse the message size. */
1092 _nx_pop3_parse_response(buffer_ptr, 3, recv_packet_ptr -> nx_packet_length,
1093 (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
1094
1095 if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
1096 {
1097
1098 *size = strtoul(argument, NULL, 10);
1099
1100 status = NX_SUCCESS;
1101 }
1102 }
1103 }
1104 }
1105
1106 /* Done with the server response, delete the packet. */
1107 nx_packet_release(recv_packet_ptr);
1108
1109 return status;
1110 }
1111
1112 /**************************************************************************/
1113 /* */
1114 /* FUNCTION RELEASE */
1115 /* */
1116 /* _nxe_pop3_client_mail_item_get PORTABLE C */
1117 /* 6.1 */
1118 /* AUTHOR */
1119 /* */
1120 /* Yuxin Zhou, Microsoft Corporation */
1121 /* */
1122 /* DESCRIPTION */
1123 /* */
1124 /* This function performs error checking for the get mail item */
1125 /* service. */
1126 /* */
1127 /* INPUT */
1128 /* */
1129 /* client_ptr Pointer to client struct */
1130 /* mail_item Index into POP3 mailbox */
1131 /* item_size Pointer to mail size */
1132 /* */
1133 /* OUTPUT */
1134 /* */
1135 /* NX_PTR_ERROR Invalid pointer parameter */
1136 /* status Actual completion status */
1137 /* */
1138 /* CALLS */
1139 /* */
1140 /* _nx_pop3_client_mail_item_get Actual get mail service */
1141 /* */
1142 /* CALLED BY */
1143 /* */
1144 /* Application Code */
1145 /* */
1146 /* RELEASE HISTORY */
1147 /* */
1148 /* DATE NAME DESCRIPTION */
1149 /* */
1150 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1151 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1152 /* resulting in version 6.1 */
1153 /* */
1154 /**************************************************************************/
_nxe_pop3_client_mail_item_get(NX_POP3_CLIENT * client_ptr,UINT mail_item,ULONG * item_size)1155 UINT _nxe_pop3_client_mail_item_get(NX_POP3_CLIENT *client_ptr, UINT mail_item, ULONG *item_size)
1156 {
1157
1158 UINT status;
1159
1160 /* Check for invalid pointer input. */
1161 if ((client_ptr == NX_NULL) || (item_size == NX_NULL))
1162 {
1163
1164 return NX_PTR_ERROR;
1165 }
1166
1167 /* Check for an invalid index. */
1168 if (mail_item == 0)
1169 {
1170 return NX_POP3_CLIENT_INVALID_INDEX;
1171 }
1172
1173 status = _nx_pop3_client_mail_item_get(client_ptr, mail_item, item_size);
1174
1175 return status;
1176 }
1177
1178 /**************************************************************************/
1179 /* */
1180 /* FUNCTION RELEASE */
1181 /* */
1182 /* _nx_pop3_client_mail_item_get PORTABLE C */
1183 /* 6.1 */
1184 /* AUTHOR */
1185 /* */
1186 /* Yuxin Zhou, Microsoft Corporation */
1187 /* */
1188 /* DESCRIPTION */
1189 /* */
1190 /* This function sends the RETR command to the server for the specified*/
1191 /* mail item, and returns the server response. If accepted, it will */
1192 /* parse the mail item size as well. */
1193 /* */
1194 /* INPUT */
1195 /* */
1196 /* client_ptr Pointer to client struct */
1197 /* mail_item Index into POP3 mailbox */
1198 /* item_size Pointer to mail size */
1199 /* */
1200 /* OUTPUT */
1201 /* */
1202 /* NX_PTR_ERROR Invalid pointer parameter */
1203 /* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
1204 /* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
1205 /* Packet too small for command */
1206 /* status Actual completion status */
1207 /* */
1208 /* CALLS */
1209 /* */
1210 /* nx_packet_allocate Allocate packet from packet pool */
1211 /* nx_packet_release Release packet back to pool */
1212 /* nx_tcp_socket_send Send packet out TCP socket */
1213 /* nx_tcp_socket_receive Retrieve packet from TCP socket */
1214 /* _nx_pop3_parse_response Extract word from server response */
1215 /* _nx_pop3_server_number_convert Convert integer to ascii */
1216 /* */
1217 /* CALLED BY */
1218 /* */
1219 /* Application Code */
1220 /* */
1221 /* RELEASE HISTORY */
1222 /* */
1223 /* DATE NAME DESCRIPTION */
1224 /* */
1225 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1226 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
1227 /* verified memcpy use cases, */
1228 /* resulting in version 6.1 */
1229 /* */
1230 /**************************************************************************/
_nx_pop3_client_mail_item_get(NX_POP3_CLIENT * client_ptr,UINT mail_item,ULONG * item_size)1231 UINT _nx_pop3_client_mail_item_get(NX_POP3_CLIENT *client_ptr, UINT mail_item, ULONG *item_size)
1232 {
1233
1234 UINT status;
1235 UINT size;
1236 NX_PACKET *packet_ptr, *recv_packet_ptr;
1237 CHAR *buffer;
1238 CHAR argument[10];
1239 UINT packet_type;
1240
1241
1242 client_ptr -> nx_pop3_client_ready_to_download = NX_FALSE;
1243
1244 /* Verify mail_item is valid index (less than total number items in mailbox. */
1245 if (mail_item > client_ptr -> nx_pop3_client_maildrop_items)
1246 {
1247 return NX_POP3_INVALID_MAIL_ITEM;
1248 }
1249
1250 /* Allocate a packet. */
1251 if (client_ptr -> nx_pop3_client_tcp_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
1252 packet_type = NX_IPv6_TCP_PACKET;
1253 else
1254 packet_type = NX_IPv4_TCP_PACKET;
1255
1256 /* Allocate a packet. */
1257 status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
1258 &packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
1259
1260 /* Check for error. */
1261 if (status != NX_SUCCESS)
1262 {
1263
1264 /* Return the error condition. */
1265 return(status);
1266 }
1267
1268 /* Check packet payload can hold the Client message. . */
1269 if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_RETR) - 1) + 1) >= packet_ptr -> nx_packet_data_end)
1270 {
1271
1272 /* Release the packet. */
1273 nx_packet_release(packet_ptr);
1274
1275 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
1276 }
1277
1278 buffer = (CHAR *)(packet_ptr -> nx_packet_prepend_ptr);
1279
1280 /* Send a RETR command to the server. */
1281 memcpy(packet_ptr -> nx_packet_prepend_ptr, NX_POP3_COMMAND_RETR, (sizeof(NX_POP3_COMMAND_RETR) - 1)); /* Use case of memcpy is verified. */
1282 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_RETR) - 1);
1283 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_RETR) - 1);
1284 buffer += (sizeof(NX_POP3_COMMAND_RETR) - 1);
1285
1286 memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
1287 packet_ptr -> nx_packet_length++;
1288 packet_ptr -> nx_packet_append_ptr++;
1289 buffer++;
1290
1291 /* Convert the mail item index to ascii. */
1292 size = _nx_pop3_server_number_convert(mail_item, &argument[0]);
1293 if ((buffer + size + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= (CHAR *)packet_ptr -> nx_packet_data_end)
1294 {
1295
1296 /* Release the packet. */
1297 nx_packet_release(packet_ptr);
1298
1299 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
1300 }
1301
1302 memcpy(buffer, &argument[0], size); /* Use case of memcpy is verified. */
1303 packet_ptr -> nx_packet_length += size;
1304 packet_ptr -> nx_packet_append_ptr += size;
1305 buffer += size;
1306
1307 memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
1308 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1309 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1310 buffer += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1311
1312 /* Send the packet out. */
1313 status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
1314
1315 /* Check for error. */
1316 if (status != NX_SUCCESS)
1317 {
1318
1319 /* Release the packet. */
1320 nx_packet_release(packet_ptr);
1321
1322 /* Return the error condition. */
1323 return(status);
1324 }
1325
1326 /* Receive server reply over Client socket. */
1327 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
1328
1329 /* Check for error. */
1330 if (status != NX_SUCCESS)
1331 {
1332
1333 /* Return error condition. */
1334 return(status);
1335 }
1336
1337 #ifndef NX_DISABLE_PACKET_CHAIN
1338 if (recv_packet_ptr -> nx_packet_next)
1339 {
1340
1341 /* Chained packet is not supported. */
1342 nx_packet_release(recv_packet_ptr);
1343 return(NX_INVALID_PACKET);
1344 }
1345 #endif /* NX_DISABLE_PACKET_CHAIN */
1346
1347 /* Set a pointer to the packet data. */
1348 buffer = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
1349
1350 /* Parse the first argument of the server reply. */
1351 _nx_pop3_parse_response(buffer, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument,
1352 sizeof(argument), NX_FALSE, NX_FALSE);
1353
1354 /* Did the server accept the Client command? */
1355 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
1356 {
1357
1358 client_ptr -> nx_pop3_client_ready_to_download = NX_TRUE;
1359 *item_size = 0;
1360
1361 /* Yes. Clear memory for parsing the mail item size. */
1362 memset(argument, 0, sizeof(argument));
1363
1364 /* Get the number of szie of the message. . */
1365 _nx_pop3_parse_response(buffer, 2, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument,
1366 sizeof(argument) - 1, NX_FALSE, NX_FALSE);
1367
1368 /* Check if argument parsed successfully. */
1369 if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
1370 {
1371
1372 /* It was; set the size of th e mail item. */
1373 *item_size = strtoul(argument, NULL, 10);
1374 }
1375
1376 while (((ULONG)buffer < ((ULONG)recv_packet_ptr -> nx_packet_append_ptr - 1)) &&
1377 ((*buffer != 0x0D) || (*(buffer + 1) != 0x0A)))
1378 {
1379 buffer++;
1380 }
1381
1382 buffer += 2;
1383
1384 if ((UCHAR *)buffer == recv_packet_ptr -> nx_packet_append_ptr)
1385 {
1386 nx_packet_release(recv_packet_ptr);
1387 }
1388 else
1389 {
1390 client_ptr -> nx_pop3_client_message_ptr = recv_packet_ptr;
1391 recv_packet_ptr -> nx_packet_length -=
1392 (ULONG)buffer - (ULONG)recv_packet_ptr -> nx_packet_prepend_ptr;
1393 recv_packet_ptr -> nx_packet_prepend_ptr = (UCHAR *)buffer;
1394 }
1395
1396 return NX_SUCCESS;
1397 }
1398 else
1399 {
1400 nx_packet_release(recv_packet_ptr);
1401 return NX_POP3_SERVER_ERROR_STATUS;
1402 }
1403
1404 }
1405
1406
1407 /**************************************************************************/
1408 /* */
1409 /* FUNCTION RELEASE */
1410 /* */
1411 /* _nxe_pop3_client_mail_item_message_get PORTABLE C */
1412 /* 6.1 */
1413 /* AUTHOR */
1414 /* */
1415 /* Yuxin Zhou, Microsoft Corporation */
1416 /* */
1417 /* DESCRIPTION */
1418 /* */
1419 /* This function performs error checking for the get message data */
1420 /* service. */
1421 /* */
1422 /* INPUT */
1423 /* */
1424 /* client_ptr Pointer to client struct */
1425 /* recv_packet_ptr Pointer to received PP3 packet */
1426 /* bytes_retrieved Size of message data in packet */
1427 /* final_packet Indicates if last packet */
1428 /* NX_FALSE = not the last packet */
1429 /* NX_TRUE = is the last packet */
1430 /* */
1431 /* OUTPUT */
1432 /* */
1433 /* NX_PTR_ERROR Invalid pointer parameter */
1434 /* status Actual completion status */
1435 /* */
1436 /* CALLS */
1437 /* */
1438 /* _nx_pop3_client_mail_item_message_data_get */
1439 /* Actual get message data service */
1440 /* */
1441 /* CALLED BY */
1442 /* */
1443 /* Application Code */
1444 /* */
1445 /* RELEASE HISTORY */
1446 /* */
1447 /* DATE NAME DESCRIPTION */
1448 /* */
1449 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1450 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1451 /* resulting in version 6.1 */
1452 /* */
1453 /**************************************************************************/
_nxe_pop3_client_mail_item_message_get(NX_POP3_CLIENT * client_ptr,NX_PACKET ** recv_packet_ptr,ULONG * bytes_retrieved,UINT * final_packet)1454 UINT _nxe_pop3_client_mail_item_message_get(NX_POP3_CLIENT *client_ptr, NX_PACKET **recv_packet_ptr, ULONG *bytes_retrieved, UINT *final_packet)
1455 {
1456
1457 UINT status;
1458
1459
1460 if ((client_ptr == NX_NULL) || (recv_packet_ptr == NX_NULL) || (bytes_retrieved == NX_NULL) || (final_packet == NX_NULL))
1461 {
1462
1463 return NX_PTR_ERROR;
1464 }
1465
1466 status = _nx_pop3_client_mail_item_message_get(client_ptr, recv_packet_ptr, bytes_retrieved, final_packet);
1467
1468 return status;
1469 }
1470
1471
1472 /**************************************************************************/
1473 /* */
1474 /* FUNCTION RELEASE */
1475 /* */
1476 /* _nx_pop3_client_mail_item_message_get PORTABLE C */
1477 /* 6.1 */
1478 /* AUTHOR */
1479 /* */
1480 /* Yuxin Zhou, Microsoft Corporation */
1481 /* */
1482 /* DESCRIPTION */
1483 /* */
1484 /* This function retrieves message packets from the POP3 Client TCP */
1485 /* socket and returns them to the caller without further processing. */
1486 /* It is up to the caller to strip off the trailing end of message tag */
1487 /* \r\n.\r\n if one is appended to the message. Note the end of */
1488 /* message is included in the packet length. */
1489 /* */
1490 /* When packets are received with only the end of message tag (EOM), */
1491 /* this function returns zero bytes retrieved and sets final_packet to */
1492 /* true. */
1493 /* */
1494 /* If the status return is NX_SUCCESS, the caller MUST release the */
1495 /* packet, even if there bytes_retrieved is set to zero. */
1496 /* */
1497 /* INPUT */
1498 /* */
1499 /* client_ptr Pointer to client struct */
1500 /* recv_packet_ptr Pointer to received packet */
1501 /* bytes_retrieved Received packet length */
1502 /* final_packet If last packet of message */
1503 /* */
1504 /* OUTPUT */
1505 /* */
1506 /* NX_PTR_ERROR Invalid pointer parameter */
1507 /* status Actual completion status */
1508 /* */
1509 /* CALLS */
1510 /* */
1511 /* None */
1512 /* */
1513 /* CALLED BY */
1514 /* */
1515 /* Application Code */
1516 /* */
1517 /* RELEASE HISTORY */
1518 /* */
1519 /* DATE NAME DESCRIPTION */
1520 /* */
1521 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1522 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1523 /* resulting in version 6.1 */
1524 /* */
1525 /**************************************************************************/
_nx_pop3_client_mail_item_message_get(NX_POP3_CLIENT * client_ptr,NX_PACKET ** recv_packet_ptr,ULONG * bytes_retrieved,UINT * final_packet)1526 UINT _nx_pop3_client_mail_item_message_get(NX_POP3_CLIENT *client_ptr, NX_PACKET **recv_packet_ptr, ULONG *bytes_retrieved, UINT *final_packet)
1527 {
1528 UINT status;
1529 UINT index;
1530 CHAR *buffer_ptr;
1531
1532 /* Initialize results to no data retrieved, or if the received packet is the last in the message. */
1533 *final_packet = NX_FALSE;
1534 *bytes_retrieved = 0;
1535
1536 /* Verify client is ready to download mail messages. */
1537 if (client_ptr -> nx_pop3_client_ready_to_download == NX_FALSE)
1538 {
1539
1540 return NX_POP3_CLIENT_INVALID_STATE;
1541 }
1542
1543 if (client_ptr -> nx_pop3_client_message_ptr)
1544 {
1545 status = NX_SUCCESS;
1546 *recv_packet_ptr = client_ptr -> nx_pop3_client_message_ptr;
1547 client_ptr -> nx_pop3_client_message_ptr = NX_NULL;
1548 }
1549 else
1550 {
1551
1552 /* Retrieve the next data packet. */
1553 status = nx_tcp_socket_receive(&client_ptr -> nx_pop3_client_tcp_socket, recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
1554 }
1555
1556 if (status == NX_SUCCESS)
1557 {
1558
1559 /* Update the bytes_retrieved with amount of data in the packet. */
1560 *bytes_retrieved = (*recv_packet_ptr) -> nx_packet_length;
1561
1562 /* Check for end of message tag in this packet. */
1563 if (*bytes_retrieved > (sizeof(NX_POP3_END_OF_MESSAGE) - 1))
1564 {
1565 buffer_ptr = (CHAR *)(*recv_packet_ptr) -> nx_packet_prepend_ptr;
1566
1567 index = *bytes_retrieved - (sizeof(NX_POP3_END_OF_MESSAGE) - 1);
1568
1569 /* Determine if the end of the data contains the terminating \r\n.\r\n marker. */
1570 if (memcmp((buffer_ptr + index), NX_POP3_END_OF_MESSAGE, (sizeof(NX_POP3_END_OF_MESSAGE) - 1)) == 0)
1571 {
1572
1573 /* It does; indicate this is the end of the mail download. */
1574 *final_packet = NX_TRUE;
1575
1576 /* Client cannot download any data for this particular mail item. */
1577 client_ptr -> nx_pop3_client_ready_to_download = NX_FALSE;
1578 }
1579 }
1580 else
1581 {
1582
1583 if (
1584 (memcmp((*recv_packet_ptr) -> nx_packet_prepend_ptr, NX_POP3_END_OF_MESSAGE, (sizeof(NX_POP3_END_OF_MESSAGE) - 1))== 0) ||
1585 (memcmp((*recv_packet_ptr) -> nx_packet_prepend_ptr, NX_POP3_END_OF_MESSAGE_TAG, (sizeof(NX_POP3_END_OF_MESSAGE_TAG) - 1))== 0)
1586 )
1587 {
1588
1589 /* Yes, but this is not considered part of the message. Indicate this with the bytes retrieved. */
1590 *bytes_retrieved = 0;
1591
1592 /* It does; indicate this is the end of the mail download. */
1593 *final_packet = NX_TRUE;
1594
1595 /* Client cannot download any data for this particular mail item. */
1596 client_ptr -> nx_pop3_client_ready_to_download = NX_FALSE;
1597 }
1598 }
1599 }
1600
1601 return status;
1602
1603 }
1604
1605 /**************************************************************************/
1606 /* */
1607 /* FUNCTION RELEASE */
1608 /* */
1609 /* _nxe_pop3_client_mail_item_delete PORTABLE C */
1610 /* 6.1 */
1611 /* AUTHOR */
1612 /* */
1613 /* Yuxin Zhou, Microsoft Corporation */
1614 /* */
1615 /* DESCRIPTION */
1616 /* */
1617 /* This function performs error checking for the delete mail item */
1618 /* service. */
1619 /* */
1620 /* INPUT */
1621 /* */
1622 /* client_ptr Pointer to client struct */
1623 /* mail_index Index of mail item to delete */
1624 /* */
1625 /* OUTPUT */
1626 /* */
1627 /* NX_PTR_ERROR Invalid pointer parameter */
1628 /* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
1629 /* status Actual completion status */
1630 /* */
1631 /* CALLS */
1632 /* */
1633 /* _nx_pop3_client_mail_item_delete Actual delete mail service */
1634 /* */
1635 /* CALLED BY */
1636 /* */
1637 /* Application Code */
1638 /* */
1639 /* RELEASE HISTORY */
1640 /* */
1641 /* DATE NAME DESCRIPTION */
1642 /* */
1643 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1644 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1645 /* resulting in version 6.1 */
1646 /* */
1647 /**************************************************************************/
_nxe_pop3_client_mail_item_delete(NX_POP3_CLIENT * client_ptr,UINT mail_index)1648 UINT _nxe_pop3_client_mail_item_delete(NX_POP3_CLIENT *client_ptr, UINT mail_index)
1649 {
1650
1651 UINT status;
1652
1653
1654 /* Check for invalid pointer input. */
1655 if (client_ptr == NX_NULL)
1656 {
1657 return NX_PTR_ERROR;
1658 }
1659
1660 /* Check for invalid mail item input. */
1661 if (mail_index == 0)
1662 {
1663
1664 return NX_POP3_CLIENT_INVALID_INDEX;
1665 }
1666
1667 status = _nx_pop3_client_mail_item_delete(client_ptr, mail_index);
1668
1669 return status;
1670 }
1671
1672
1673 /**************************************************************************/
1674 /* */
1675 /* FUNCTION RELEASE */
1676 /* */
1677 /* _nx_pop3_client_mail_item_delete PORTABLE C */
1678 /* 6.1 */
1679 /* AUTHOR */
1680 /* */
1681 /* Yuxin Zhou, Microsoft Corporation */
1682 /* */
1683 /* DESCRIPTION */
1684 /* */
1685 /* This function sends the DELE command for the specified mail item */
1686 /* and verifies the server will delete the item. Note that for some */
1687 /* servers, items marked for deletion are not deleted immediately, in */
1688 /* some cases only if they receive the QUIT command. */
1689 /* */
1690 /* INPUT */
1691 /* */
1692 /* client_ptr Pointer to client struct */
1693 /* mail_item Index into POP3 mailbox */
1694 /* */
1695 /* OUTPUT */
1696 /* */
1697 /* NX_PTR_ERROR Invalid pointer parameter */
1698 /* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
1699 /* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
1700 /* Packet too small for command */
1701 /* status Actual completion status */
1702 /* */
1703 /* CALLS */
1704 /* */
1705 /* nx_packet_allocate Allocate packet from packet pool */
1706 /* nx_packet_release Release packet back to pool */
1707 /* nx_tcp_socket_send Send packet out TCP socket */
1708 /* nx_tcp_socket_receive Retrieve packet from TCP socket */
1709 /* _nx_pop3_parse_response Extract word from server response */
1710 /* _nx_pop3_server_number_convert Convert integer to ascii */
1711 /* */
1712 /* CALLED BY */
1713 /* */
1714 /* Application Code */
1715 /* */
1716 /* RELEASE HISTORY */
1717 /* */
1718 /* DATE NAME DESCRIPTION */
1719 /* */
1720 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1721 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
1722 /* verified memcpy use cases, */
1723 /* resulting in version 6.1 */
1724 /* */
1725 /**************************************************************************/
_nx_pop3_client_mail_item_delete(NX_POP3_CLIENT * client_ptr,UINT mail_index)1726 UINT _nx_pop3_client_mail_item_delete(NX_POP3_CLIENT *client_ptr, UINT mail_index)
1727 {
1728
1729 UINT status;
1730 UINT size;
1731 NX_PACKET *packet_ptr, *recv_packet_ptr;
1732 CHAR *buffer_ptr;
1733 CHAR argument[10];
1734 UINT packet_type;
1735
1736
1737 /* Allocate a packet. */
1738 if (client_ptr -> nx_pop3_client_tcp_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
1739 packet_type = NX_IPv6_TCP_PACKET;
1740 else
1741 packet_type = NX_IPv4_TCP_PACKET;
1742
1743 /* Allocate a packet. */
1744 status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
1745 &packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
1746
1747 /* Check for error. */
1748 if (status != NX_SUCCESS)
1749 {
1750
1751 /* Return the error condition. */
1752 return(status);
1753 }
1754
1755 buffer_ptr = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
1756
1757 /* Convert the ascii word to a number. */
1758 size = _nx_pop3_server_number_convert(mail_index, &argument[0]);
1759
1760 /* Check packet payload is large enough for DEL request. */
1761 if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_DELE) - 1) + 1 + size +
1762 (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= packet_ptr -> nx_packet_data_end)
1763 {
1764
1765 /* Release the packet. */
1766 nx_packet_release(packet_ptr);
1767
1768 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
1769 }
1770
1771 /* Send the DELE command. */
1772 memcpy(buffer_ptr, NX_POP3_COMMAND_DELE, (sizeof(NX_POP3_COMMAND_DELE) - 1)); /* Use case of memcpy is verified. */
1773 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_DELE) - 1);
1774 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_DELE) - 1);
1775 buffer_ptr += (sizeof(NX_POP3_COMMAND_DELE) - 1);
1776
1777
1778 memcpy(buffer_ptr, " ", 1); /* Use case of memcpy is verified. */
1779 packet_ptr -> nx_packet_length++;
1780 packet_ptr -> nx_packet_append_ptr++;
1781 buffer_ptr++;
1782
1783 memcpy(buffer_ptr, &argument[0], size); /* Use case of memcpy is verified. */
1784 packet_ptr -> nx_packet_length += size;
1785 packet_ptr -> nx_packet_append_ptr += size;
1786 buffer_ptr += size;
1787
1788 memcpy(buffer_ptr, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
1789 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1790 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1791 buffer_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
1792
1793 /* Send the DELE command out. */
1794 status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
1795
1796 /* Check for error. */
1797 if (status != NX_SUCCESS)
1798 {
1799
1800 /* Release the packet. */
1801 nx_packet_release(packet_ptr);
1802
1803 /* Return the error condition. */
1804 return(status);
1805 }
1806
1807 /* Receive server reply to DELE command. */
1808 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
1809
1810 /* Check for error. */
1811 if (status != NX_SUCCESS)
1812 {
1813
1814 /* Return error condition. */
1815 return(status);
1816 }
1817
1818 #ifndef NX_DISABLE_PACKET_CHAIN
1819 if (recv_packet_ptr -> nx_packet_next)
1820 {
1821
1822 /* Chained packet is not supported. */
1823 nx_packet_release(recv_packet_ptr);
1824 return(NX_INVALID_PACKET);
1825 }
1826 #endif /* NX_DISABLE_PACKET_CHAIN */
1827
1828 /* Set a pointer to the packet data. */
1829 buffer_ptr = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
1830
1831 /* Parse the first argument of the server reply. */
1832 _nx_pop3_parse_response(buffer_ptr, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
1833
1834 /* Initialize status to server error status received. */
1835 status = NX_POP3_SERVER_ERROR_STATUS;
1836
1837 /* Did the server accept the Client command? */
1838 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
1839 {
1840
1841 /* Yes, set status to successful completion. */
1842 status = NX_SUCCESS;
1843 }
1844
1845 nx_packet_release(recv_packet_ptr);
1846
1847 return status;
1848 }
1849
1850 /**************************************************************************/
1851 /* */
1852 /* FUNCTION RELEASE */
1853 /* */
1854 /* _nxe_pop3_client_quit PORTABLE C */
1855 /* 6.1 */
1856 /* AUTHOR */
1857 /* */
1858 /* Yuxin Zhou, Microsoft Corporation */
1859 /* */
1860 /* DESCRIPTION */
1861 /* */
1862 /* The service performs error checking for the send QUIT service. */
1863 /* */
1864 /* INPUT */
1865 /* */
1866 /* client_ptr Pointer to POP3 Client */
1867 /* */
1868 /* OUTPUT */
1869 /* */
1870 /* NX_SUCCESS Successful completion status */
1871 /* NX_PTR_ERROR Invalid pointer input */
1872 /* status Actual completion status */
1873 /* */
1874 /* CALLED BY */
1875 /* */
1876 /* Application thread */
1877 /* */
1878 /* CALLS */
1879 /* */
1880 /* _nx_pop3_client_quit Actual send QUIT command service */
1881 /* */
1882 /* RELEASE HISTORY */
1883 /* */
1884 /* DATE NAME DESCRIPTION */
1885 /* */
1886 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1887 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1888 /* resulting in version 6.1 */
1889 /* */
1890 /**************************************************************************/
_nxe_pop3_client_quit(NX_POP3_CLIENT * client_ptr)1891 UINT _nxe_pop3_client_quit(NX_POP3_CLIENT *client_ptr)
1892 {
1893
1894 UINT status;
1895
1896 if (client_ptr == NX_NULL)
1897 {
1898 return NX_PTR_ERROR;
1899 }
1900
1901 status = _nx_pop3_client_quit(client_ptr);
1902
1903 return status;
1904 }
1905
1906
1907 /**************************************************************************/
1908 /* */
1909 /* FUNCTION RELEASE */
1910 /* */
1911 /* _nx_pop3_client_quit PORTABLE C */
1912 /* 6.1 */
1913 /* AUTHOR */
1914 /* */
1915 /* Yuxin Zhou, Microsoft Corporation */
1916 /* */
1917 /* DESCRIPTION */
1918 /* */
1919 /* The service sends a QUIT command to the Client POP3 server. The */
1920 /* QUIT command takes no arguments and can be called at any time during*/
1921 /* the Client session. */
1922 /* */
1923 /* INPUT */
1924 /* */
1925 /* client_ptr Pointer to POP3 Client */
1926 /* */
1927 /* OUTPUT */
1928 /* */
1929 /* NX_SUCCESS Successful completion status */
1930 /* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
1931 /* Packet too small for command */
1932 /* status Actual completion status */
1933 /* */
1934 /* CALLED BY */
1935 /* */
1936 /* Application thread */
1937 /* */
1938 /* CALLS */
1939 /* */
1940 /* None */
1941 /* */
1942 /* RELEASE HISTORY */
1943 /* */
1944 /* DATE NAME DESCRIPTION */
1945 /* */
1946 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1947 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
1948 /* verified memcpy use cases, */
1949 /* resulting in version 6.1 */
1950 /* */
1951 /**************************************************************************/
_nx_pop3_client_quit(NX_POP3_CLIENT * client_ptr)1952 UINT _nx_pop3_client_quit(NX_POP3_CLIENT *client_ptr)
1953 {
1954
1955 UINT status;
1956 NX_PACKET *packet_ptr, *recv_packet_ptr;
1957 CHAR *buffer_ptr;
1958 CHAR argument[10];
1959 UINT packet_type;
1960
1961
1962 /* Allocate a packet. */
1963 if (client_ptr -> nx_pop3_client_tcp_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
1964 packet_type = NX_IPv6_TCP_PACKET;
1965 else
1966 packet_type = NX_IPv4_TCP_PACKET;
1967
1968 /* Allocate a packet. */
1969 status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
1970 &packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
1971
1972 /* Check for error. */
1973 if (status != NX_SUCCESS)
1974 {
1975
1976 /* Return the error condition. */
1977 return(status);
1978 }
1979
1980 buffer_ptr = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
1981
1982 /* Check packet payload will hold the QUIT request. */
1983 if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_QUIT) - 1) + 1 +
1984 (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= packet_ptr -> nx_packet_data_end)
1985 {
1986
1987 /* Release the packet. */
1988 nx_packet_release(packet_ptr);
1989
1990 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
1991 }
1992
1993 memcpy(buffer_ptr, NX_POP3_COMMAND_QUIT, (sizeof(NX_POP3_COMMAND_QUIT) - 1)); /* Use case of memcpy is verified. */
1994 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_QUIT) - 1);
1995 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_QUIT) - 1);
1996 buffer_ptr += (sizeof(NX_POP3_COMMAND_QUIT) - 1);
1997
1998 memcpy(buffer_ptr, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
1999 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
2000 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
2001 buffer_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
2002
2003 /* Send the packet out. */
2004 status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
2005
2006 /* Check for error. */
2007 if (status != NX_SUCCESS)
2008 {
2009
2010 /* Release the packet. */
2011 nx_packet_release(packet_ptr);
2012
2013 /* Return the error condition. */
2014 return(status);
2015 }
2016
2017 /* Receive server reply over session socket. */
2018 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
2019
2020 /* Check for error. */
2021 if (status != NX_SUCCESS)
2022 {
2023
2024 /* Return error condition. */
2025 return(status);
2026 }
2027
2028 #ifndef NX_DISABLE_PACKET_CHAIN
2029 if (recv_packet_ptr -> nx_packet_next)
2030 {
2031
2032 /* Chained packet is not supported. */
2033 nx_packet_release(recv_packet_ptr);
2034 return(NX_INVALID_PACKET);
2035 }
2036 #endif /* NX_DISABLE_PACKET_CHAIN */
2037
2038 /* Set a pointer to the packet data. */
2039 buffer_ptr = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
2040
2041 /* Parse the first argument of the server reply. */
2042 _nx_pop3_parse_response(buffer_ptr, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
2043
2044 /* Initialize status to bad reply error condition. */
2045 status = NX_POP3_SERVER_ERROR_STATUS;
2046
2047 /* Did the server accept the Client command? */
2048 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
2049 {
2050
2051 /* Yes, set status to successful completion. */
2052 status = NX_SUCCESS;
2053 }
2054
2055 nx_packet_release(recv_packet_ptr);
2056
2057 return status;
2058 }
2059
2060
2061 /**************************************************************************/
2062 /* */
2063 /* FUNCTION RELEASE */
2064 /* */
2065 /* _nx_pop3_digest_authenticate PORTABLE C */
2066 /* 6.1 */
2067 /* AUTHOR */
2068 /* */
2069 /* Yuxin Zhou, Microsoft Corporation */
2070 /* */
2071 /* DESCRIPTION */
2072 /* */
2073 /* This function creates an MD5 digest based on input string which per */
2074 /* POP3 protocol is the process ID and secret (e.g. Client password). */
2075 /* This digest is used in APOP commands for the Client to authenticate */
2076 /* itself without clear texting it's password. */
2077 /* */
2078 /* INPUT */
2079 /* */
2080 /* client_ptr POP3 Client pointer */
2081 /* process_ID_ptr Pointer to process_ID string */
2082 /* process_ID_length Process ID string length */
2083 /* result Pointer to MD5 digest */
2084 /* */
2085 /* OUTPUT */
2086 /* */
2087 /* NX_SUCCESS Successful completion status */
2088 /* */
2089 /* CALLS */
2090 /* */
2091 /* _nx_md5_initialize Initialize MD5 algorithm */
2092 /* _nx_md5_update Update MD5 digest */
2093 /* _nx_md5_digest_calculate Complete the MD5 algorithm */
2094 /* _nx_pop3_hex_ascii_convert Convert digest to ascii */
2095 /* */
2096 /* CALLED BY */
2097 /* */
2098 /* _nx_pop3_client_apop Send APOP cmd to Server */
2099 /* */
2100 /* RELEASE HISTORY */
2101 /* */
2102 /* DATE NAME DESCRIPTION */
2103 /* */
2104 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2105 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2106 /* resulting in version 6.1 */
2107 /* */
2108 /**************************************************************************/
_nx_pop3_digest_authenticate(NX_POP3_CLIENT * client_ptr,CHAR * process_ID_ptr,UINT process_ID_length,CHAR * result)2109 UINT _nx_pop3_digest_authenticate(NX_POP3_CLIENT *client_ptr, CHAR *process_ID_ptr, UINT process_ID_length, CHAR *result)
2110 {
2111
2112 CHAR md5_binary[NX_POP3_MAX_BINARY_MD5];
2113
2114 /* Initialize the Client session MD5 data. */
2115 _nx_md5_initialize(&client_ptr -> nx_pop3_client_md5data);
2116
2117
2118 _nx_md5_update(&client_ptr -> nx_pop3_client_md5data, (unsigned char *)process_ID_ptr, process_ID_length);
2119
2120 /* Finish calculation of the MD5 digest. */
2121 _nx_md5_digest_calculate(&client_ptr -> nx_pop3_client_md5data, (unsigned char *)&md5_binary[0]);
2122
2123 /* Convert digest to ASCII Hex representation. */
2124 _nx_pop3_hex_ascii_convert(&md5_binary[0], NX_POP3_MAX_BINARY_MD5, result);
2125
2126 /* Return successful completion */
2127 return NX_SUCCESS;
2128 }
2129
2130 /**************************************************************************/
2131 /* */
2132 /* FUNCTION RELEASE */
2133 /* */
2134 /* _nx_pop3_parse_process_id PORTABLE C */
2135 /* 6.1 */
2136 /* AUTHOR */
2137 /* */
2138 /* Yuxin Zhou, Microsoft Corporation */
2139 /* */
2140 /* DESCRIPTION */
2141 /* */
2142 /* This function extracts the process ID in the greeting from server. */
2143 /* If found the Server is indicating we may use APOP to secure (open) */
2144 /* the mailbox. The process ID is saved to the POP3 Client instance. If*/
2145 /* no process ID is found, this field is set to NULL. */
2146 /* */
2147 /* INPUT */
2148 /* */
2149 /* client_ptr Pointer to Client */
2150 /* buffer Pointer to server reply buffer */
2151 /* buffer_length Size of server reply buffer */
2152 /* */
2153 /* OUTPUT */
2154 /* */
2155 /* status Actual completion status */
2156 /* */
2157 /* CALLED BY */
2158 /* */
2159 /* _nxd_pop3_client_connect Connect and authenticate with server*/
2160 /* */
2161 /* CALLS */
2162 /* */
2163 /* None */
2164 /* */
2165 /* RELEASE HISTORY */
2166 /* */
2167 /* DATE NAME DESCRIPTION */
2168 /* */
2169 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2170 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2171 /* resulting in version 6.1 */
2172 /* */
2173 /**************************************************************************/
_nx_pop3_parse_process_id(NX_POP3_CLIENT * client_ptr,CHAR * buffer,UINT buffer_length)2174 VOID _nx_pop3_parse_process_id(NX_POP3_CLIENT *client_ptr, CHAR *buffer, UINT buffer_length)
2175 {
2176
2177 CHAR c;
2178 UINT index;
2179 UINT pid_index;
2180
2181
2182 /* Set a pointer to the start of the buffer to search. */
2183 index = 0;
2184
2185 /* Clear memory for parsing the server process ID. */
2186 memset(&client_ptr -> nx_pop3_server_process_id[0], 0, NX_POP3_SERVER_PROCESS_ID_SIZE);
2187
2188 while(index < buffer_length)
2189 {
2190 c = *buffer;
2191 if (c == '<')
2192 {
2193
2194 /* Found the start of the process ID. Now save it to the session instance including the angle brackets. */
2195 pid_index = 0;
2196
2197 /* Check that we don't go over the size of the process ID buffer or off the end of the packet data. */
2198 while ((pid_index < NX_POP3_SERVER_PROCESS_ID_SIZE) && (index < buffer_length))
2199 {
2200
2201 /* Copy the next character and advance the counters and buffer pointer. */
2202 client_ptr -> nx_pop3_server_process_id[pid_index] = *buffer;
2203
2204 /* Check if this is the end of the time stamp which is included in the process id string. . */
2205 if (*buffer == '>')
2206 {
2207
2208 /* This is the enclosing bracket. We're done. */
2209 return;
2210 }
2211
2212 index++;
2213 pid_index++;
2214 buffer++;
2215 }
2216
2217 }
2218 index++;
2219 buffer++;
2220 }
2221
2222 /* If we got here, we did not find any process IDs. */
2223 return;
2224 }
2225
2226 /**************************************************************************/
2227 /* */
2228 /* FUNCTION RELEASE */
2229 /* */
2230 /* _nx_pop3_parse_response PORTABLE C */
2231 /* 6.1.4 */
2232 /* AUTHOR */
2233 /* */
2234 /* Yuxin Zhou, Microsoft Corporation */
2235 /* */
2236 /* DESCRIPTION */
2237 /* */
2238 /* This service parses the specified argument from the input buffer */
2239 /* and returns a pointer to the argument if found, else the a NULL */
2240 /* pointer. Dashes are handled as word separators. */
2241 /* */
2242 /* crlf_are_word_breaks indicates if CR LF's should be handled as word */
2243 /* separators. convert_to_uppercase indicates if the argument should be*/
2244 /* converted to uppercase. */
2245 /* */
2246 /* This service removes CR LF's at the end of the message. It does not*/
2247 /* allocate or clear argument memory, but does. */
2248 /* */
2249 /* INPUT */
2250 /* */
2251 /* buffer Pointer to buffer to parse */
2252 /* argument_index Index of argument to parse */
2253 /* buffer_length Buffer size */
2254 /* argument Pointer to argument parsed */
2255 /* argument_length Argument buffer size */
2256 /* convert_to_uppercase Convert argument to uppercase */
2257 /* crlf_are_word_breaks Handle CR LF's as word breaks */
2258 /* */
2259 /* OUTPUT */
2260 /* */
2261 /* None */
2262 /* */
2263 /* CALLS */
2264 /* */
2265 /* None */
2266 /* */
2267 /* CALLED BY */
2268 /* */
2269 /* */
2270 /* RELEASE HISTORY */
2271 /* */
2272 /* DATE NAME DESCRIPTION */
2273 /* */
2274 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2275 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2276 /* resulting in version 6.1 */
2277 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
2278 /* buffer length verification, */
2279 /* resulting in version 6.1.4 */
2280 /* */
2281 /**************************************************************************/
_nx_pop3_parse_response(CHAR * buffer,UINT argument_index,UINT buffer_length,CHAR * argument,UINT argument_length,UINT convert_to_uppercase,UINT crlf_are_word_breaks)2282 void _nx_pop3_parse_response(CHAR *buffer, UINT argument_index, UINT buffer_length, CHAR *argument, UINT argument_length,
2283 UINT convert_to_uppercase, UINT crlf_are_word_breaks)
2284 {
2285
2286 UINT i = 0;
2287 UINT j = 0;
2288 UINT argument_char_count;
2289
2290
2291 /* Check for invalid input. */
2292 if ((buffer == NX_NULL)|| (buffer[0] == 0x0) || (argument == NX_NULL) || (buffer_length == 0) ||
2293 (argument_length == 0) || (argument_index == 0))
2294 {
2295
2296 /* Return with argument not found status. */
2297 return;
2298 }
2299
2300 /* Initialize the argument to not found with NULL character. */
2301 *argument = (CHAR)0x0;
2302 argument_char_count = 0;
2303
2304 /* Is this the first argument? */
2305 if (argument_index == 1)
2306 {
2307
2308 /* Yes, search each character up to the end of the buffer for the first separator. */
2309 while (i < buffer_length)
2310 {
2311
2312 /* Did we find it? */
2313 if (*buffer == ' ')
2314 {
2315
2316 /* Yes, we're done with this loop! */
2317 break;
2318 }
2319
2320 /* Treat a hyphen as word breaks if it is between words, not if it is the first char. */
2321 if (*buffer == '-' && i > 0)
2322 {
2323
2324 /* Yes, we're done with this loop! */
2325 break;
2326 }
2327
2328 /* Did we go past the argument size limit? */
2329 if (argument_char_count >= argument_length)
2330 {
2331
2332 /* Yes, no argument found. */
2333 break;
2334 }
2335
2336 /* Copy the next character into the argument, converting
2337 to uppercase if the caller requested this. */
2338 *argument++ = convert_to_uppercase ? (CHAR)toupper((INT)(*buffer)) : *buffer;
2339
2340 argument_char_count++;
2341
2342 /* Move to the next character. */
2343 i++;
2344 buffer++;
2345 }
2346
2347 /* Are we at the end of the buffer? */
2348 if ((i == buffer_length) && (buffer_length >= 2))
2349 {
2350
2351 /* Yes, is there a line terminator? */
2352 if (*(argument - 2) == 0x0D && *(argument - 1) == 0x0A)
2353 {
2354
2355 /* Yes, remove it with a null character */
2356 *(argument - 2) = (CHAR) 0x0;
2357 }
2358 }
2359 }
2360 else
2361 {
2362 /* No, we're not parsing the first argument. */
2363
2364 /* Mark the start of the argument at the separator after the end of the previous argument. */
2365 while (j < argument_index && i < buffer_length)
2366 {
2367
2368 /* Keep track of the number of separators in the buffer */
2369
2370 /* Did we hit a line terminator? */
2371 if ((*buffer == 0x0D) && (*(buffer + 1) == 0x0A))
2372 {
2373
2374 /* Yes, Update the count of separators. */
2375 j++;
2376
2377 /* Are line terminators as word breaks? */
2378 if (!crlf_are_word_breaks)
2379 {
2380
2381 /* No, treat as the end of the search string buffer. */
2382 break;
2383 }
2384
2385 buffer++;
2386 }
2387
2388 /* Did we hit a space or a dash in the first argument? */
2389 else if (*buffer == ' ' ||
2390 (*buffer == '-' && j == 0))
2391 {
2392
2393 /* These are counted as separators (note that
2394 dashes found in arguments after the first arg
2395 are NOT considered separators */
2396 j++;
2397 }
2398 else
2399 {
2400
2401 if (j == argument_index - 1)
2402 {
2403
2404 /* Have we exceeded the limit on the argument size? */
2405 if (argument_char_count < argument_length)
2406 {
2407
2408 /* No, copy the next character into the argument. */
2409 argument_char_count++;
2410
2411 /* Convert to uppercase if the caller requests. */
2412 *argument++ = convert_to_uppercase ? (CHAR)toupper((INT)*buffer) : *buffer;
2413 }
2414 }
2415 }
2416
2417 /* Get the next character */
2418 i++;
2419 buffer++;
2420 }
2421 }
2422
2423 return;
2424 }
2425
2426 /**************************************************************************/
2427 /* */
2428 /* FUNCTION RELEASE */
2429 /* */
2430 /* _nx_pop3_hex_ascii_convert PORTABLE C */
2431 /* 6.1 */
2432 /* AUTHOR */
2433 /* */
2434 /* Yuxin Zhou, Microsoft Corporation */
2435 /* */
2436 /* DESCRIPTION */
2437 /* */
2438 /* This function converts hexadecimal characters into an ASCII string. */
2439 /* */
2440 /* INPUT */
2441 /* */
2442 /* source Source hex string */
2443 /* source_length Length of source string */
2444 /* destination Pointer to destination string */
2445 /* */
2446 /* OUTPUT */
2447 /* */
2448 /* None */
2449 /* */
2450 /* CALLS */
2451 /* */
2452 /* None */
2453 /* */
2454 /* CALLED BY */
2455 /* */
2456 /* _nx_pop3_utility_digest_authenticate Create digest for */
2457 /* authentication */
2458 /* */
2459 /* RELEASE HISTORY */
2460 /* */
2461 /* DATE NAME DESCRIPTION */
2462 /* */
2463 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2464 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2465 /* resulting in version 6.1 */
2466 /* */
2467 /**************************************************************************/
_nx_pop3_hex_ascii_convert(CHAR * source,UINT source_length,CHAR * destination)2468 VOID _nx_pop3_hex_ascii_convert(CHAR *source, UINT source_length, CHAR *destination)
2469 {
2470
2471 UINT i,j;
2472 CHAR digit;
2473
2474
2475 /* Setup destination index. */
2476 j = 0;
2477
2478 /* Loop to process the entire source string. */
2479 for (i = 0; i < source_length; i++)
2480 {
2481
2482 /* Pickup the first nibble. */
2483 digit = (source[i] >> 4) & 0xF;
2484
2485 /* Convert to ASCII and store. */
2486 if (digit <= 9)
2487 destination[j++] = (CHAR)(digit + '0');
2488 else
2489 destination[j++] = (CHAR)(digit + 'a' - 10);
2490
2491 /* Pickup the second nibble. */
2492 digit = source[i] & 0xF;
2493
2494 /* Convert to ASCII and store. */
2495 if (digit <= 9)
2496 destination[j++] = (CHAR)(digit + '0');
2497 else
2498 destination[j++] = (CHAR)(digit + 'a' - 10);
2499 }
2500
2501 /* Place a NULL in the destination string. */
2502 destination[j] = (CHAR) NX_NULL;
2503
2504 return;
2505 }
2506
2507
2508 /**************************************************************************/
2509 /* */
2510 /* FUNCTION RELEASE */
2511 /* */
2512 /* _nx_pop3_server_number_convert PORTABLE C */
2513 /* 6.1 */
2514 /* AUTHOR */
2515 /* */
2516 /* Yuxin Zhou, Microsoft Corporation */
2517 /* */
2518 /* DESCRIPTION */
2519 /* */
2520 /* This function converts a number into an ASCII string and returns the*/
2521 /* size of the string holding the number. */
2522 /* */
2523 /* INPUT */
2524 /* */
2525 /* number Unsigned integer number */
2526 /* string_to_convert Destination string */
2527 /* */
2528 /* OUTPUT */
2529 /* */
2530 /* Size Number of bytes in string */
2531 /* (0 implies an error) */
2532 /* */
2533 /* CALLS */
2534 /* */
2535 /* _nx_pop3_client_mail_item_get Get mail item size */
2536 /* _nx_pop3_client_mail_item_delete Delete mail item */
2537 /* */
2538 /* CALLED BY */
2539 /* */
2540 /* */
2541 /* RELEASE HISTORY */
2542 /* */
2543 /* DATE NAME DESCRIPTION */
2544 /* */
2545 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2546 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2547 /* resulting in version 6.1 */
2548 /* */
2549 /**************************************************************************/
_nx_pop3_server_number_convert(UINT number,CHAR * string_to_convert)2550 UINT _nx_pop3_server_number_convert(UINT number, CHAR *string_to_convert)
2551 {
2552
2553 UINT j;
2554 UINT digit;
2555 UINT size;
2556
2557
2558 /* Initialize counters. */
2559 size = 0;
2560
2561 /* Loop to convert the number to ASCII. */
2562 while (size < 9)
2563 {
2564
2565 /* Shift the current digits over one. */
2566 for (j = size; j != 0; j--)
2567 {
2568
2569 /* Move each digit over one place. */
2570 string_to_convert[j] = string_to_convert[j - 1];
2571 }
2572
2573 /* Compute the next decimal digit. */
2574 digit = number % 10;
2575
2576 /* Update the input number. */
2577 number = number / 10;
2578
2579 /* Store the new digit in ASCII form. */
2580 string_to_convert[0] = (CHAR) (digit + 0x30);
2581
2582 /* Increment the size. */
2583 size++;
2584
2585 /* Determine if the number is now zero. */
2586 if (number == 0)
2587 break;
2588 }
2589
2590 /* Make the string NULL terminated. */
2591 string_to_convert[size] = (CHAR) NX_NULL;
2592
2593 /* Determine if there is an overflow error. */
2594 if (number)
2595 {
2596
2597 /* Error, return bad values to user. */
2598 size = 0;
2599 string_to_convert[0] = '0';
2600 }
2601
2602 /* Return size to caller. */
2603 return(size);
2604 }
2605
2606
2607 /**************************************************************************/
2608 /* */
2609 /* FUNCTION RELEASE */
2610 /* */
2611 /* _nxd_pop3_client_connect PORTABLE C */
2612 /* 6.1.6 */
2613 /* AUTHOR */
2614 /* */
2615 /* Yuxin Zhou, Microsoft Corporation */
2616 /* */
2617 /* DESCRIPTION */
2618 /* */
2619 /* This function binds the Client socket to the POP3 port and connects */
2620 /* to the POP3 server. If the connection is made, this function */
2621 /* processes the server greeting, and initiates the APOP/USER */
2622 /* authentication with the sever. */
2623 /* */
2624 /* This supports both IPv6 and IPv4 POP3 server connections. */
2625 /* */
2626 /* INPUT */
2627 /* */
2628 /* client_ptr Pointer to client struct */
2629 /* server_ip_address Pointer to POP3 server IP address */
2630 /* server_port POP3 server port */
2631 /* */
2632 /* OUTPUT */
2633 /* */
2634 /* NX_SUCCESS Successful completion status */
2635 /* NX_POP3_PARAM_ERROR Invalid Client user or password */
2636 /* NX_POP3_CANNOT_PARSE_REPLY Unable to parse server reply */
2637 /* status TCP service completion status */
2638 /* */
2639 /* CALLED BY */
2640 /* */
2641 /* _nxd_pop3_client_create Create POP3 Client and socket */
2642 /* */
2643 /* CALLS */
2644 /* */
2645 /* nx_tcp_client_socket_bind NetX TCP socket bind service */
2646 /* nxd_tcp_client_socket_connect NetX TCP socket connect service */
2647 /* nx_tcp_socket_receive NetX TCP socket receive service */
2648 /* _nx_pop3_parse_response Parse Server reply code */
2649 /* _nx_pop3_parse_process_id Parse server ID for APOP digest */
2650 /* _nx_pop3_client_apop Send Authenticated user/pass */
2651 /* _nx_pop3_client_user_pass Send User Pass in clear text */
2652 /* */
2653 /* RELEASE HISTORY */
2654 /* */
2655 /* DATE NAME DESCRIPTION */
2656 /* */
2657 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2658 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2659 /* resulting in version 6.1 */
2660 /* 04-02-2021 Yuxin Zhou Modified comment(s), and */
2661 /* corrected the client port, */
2662 /* resulting in version 6.1.6 */
2663 /* */
2664 /**************************************************************************/
_nxd_pop3_client_connect(NX_POP3_CLIENT * client_ptr,NXD_ADDRESS * server_ip_address,ULONG server_port)2665 UINT _nxd_pop3_client_connect(NX_POP3_CLIENT *client_ptr, NXD_ADDRESS *server_ip_address, ULONG server_port)
2666 {
2667
2668 UINT status;
2669 NX_PACKET *recv_packet_ptr;
2670 CHAR *buffer_ptr;
2671 CHAR argument[10];
2672
2673
2674 /* Check for client name/password/shared secret too long for allotted buffer. */
2675 if ((_nx_utility_string_length_check(&client_ptr -> nx_pop3_client_name[0], NX_NULL, NX_POP3_MAX_USERNAME)) ||
2676 (_nx_utility_string_length_check(&client_ptr -> nx_pop3_client_password[0], NX_NULL, NX_POP3_MAX_PASSWORD)))
2677 {
2678
2679 return NX_POP3_PARAM_ERROR;
2680 }
2681
2682 status = nx_tcp_client_socket_bind(&client_ptr -> nx_pop3_client_tcp_socket, NX_ANY_PORT, NX_IP_PERIODIC_RATE);
2683
2684 /* Check for error. */
2685 if (status != NX_SUCCESS)
2686 {
2687 return status;
2688 }
2689
2690 status = nxd_tcp_client_socket_connect(&client_ptr -> nx_pop3_client_tcp_socket,
2691 server_ip_address,
2692 server_port,
2693 NX_POP3_CLIENT_CONNECTION_TIMEOUT);
2694
2695 if (status != NX_SUCCESS)
2696 {
2697 return status;
2698 }
2699
2700 /* Receive server reply over session socket. */
2701 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
2702
2703 /* Check for error. */
2704 if (status != NX_SUCCESS)
2705 {
2706
2707 /* Return error condition. */
2708 return(status);
2709 }
2710
2711 #ifndef NX_DISABLE_PACKET_CHAIN
2712 if (recv_packet_ptr -> nx_packet_next)
2713 {
2714
2715 /* Chained packet is not supported. */
2716 nx_packet_release(recv_packet_ptr);
2717 return(NX_INVALID_PACKET);
2718 }
2719 #endif /* NX_DISABLE_PACKET_CHAIN */
2720
2721 /* Set a pointer to the packet data. */
2722 buffer_ptr = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
2723
2724 /* Parse the first argument of the server reply. */
2725 _nx_pop3_parse_response(buffer_ptr, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
2726
2727 /* Initialize status to bad reply error condition. */
2728 status = NX_POP3_SERVER_ERROR_STATUS;
2729
2730 /* Did the server accept the Client command? */
2731 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
2732 {
2733
2734 if (client_ptr -> nx_pop3_client_enable_APOP_authentication)
2735 {
2736
2737 /* Attempt to extract the server process ID in the greeting. */
2738 _nx_pop3_parse_process_id(client_ptr, buffer_ptr, recv_packet_ptr -> nx_packet_length);
2739
2740 /* Did we find a process ID? */
2741 if (client_ptr -> nx_pop3_server_process_id[0] != 0)
2742 {
2743
2744 /* Do APOP authentication. */
2745 status = _nx_pop3_client_apop(client_ptr);
2746
2747 if (status == NX_SUCCESS)
2748 {
2749 return status;
2750 }
2751 else if (status != NX_POP3_SERVER_ERROR_STATUS)
2752 {
2753
2754 /* Another error encountered (packet pool depletion, broken connection, etc*/
2755 return status;
2756 }
2757 }
2758 else
2759 {
2760 /* Possibly the server doesn't like APOP. Try User Pass */
2761 client_ptr -> nx_pop3_client_enable_APOP_authentication = NX_FALSE;
2762 }
2763 }
2764
2765 /* Try USER PASS authentication. */
2766 status = _nx_pop3_client_user_pass(client_ptr);
2767 }
2768
2769 nx_packet_release(recv_packet_ptr);
2770
2771 return status;
2772 }
2773
2774 /**************************************************************************/
2775 /* */
2776 /* FUNCTION RELEASE */
2777 /* */
2778 /* _nx_pop3_client_apop PORTABLE C */
2779 /* 6.1 */
2780 /* AUTHOR */
2781 /* */
2782 /* Yuxin Zhou, Microsoft Corporation */
2783 /* */
2784 /* DESCRIPTION */
2785 /* */
2786 /* This function attempts to authenticate the POP3 client with the POP3*/
2787 /* server. If successful returns NX_SUCCESS. */
2788 /* */
2789 /* INPUT */
2790 /* */
2791 /* client_ptr Pointer to client struct */
2792 /* */
2793 /* OUTPUT */
2794 /* */
2795 /* NX_SUCCESS Authentication accepted by server */
2796 /* NX_POP3_APOP_FAILED_MD5_DIGEST Error creating digest */
2797 /* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
2798 /* Packet too small for command */
2799 /* status Actual completion status */
2800 /* */
2801 /* CALLS */
2802 /* */
2803 /* nx_packet_allocate Allocate packet from packet pool */
2804 /* nx_packet_release Release packet back to pool */
2805 /* nx_tcp_socket_send Send packet out TCP socket */
2806 /* nx_tcp_socket_receive Retrieve packet from TCP socket */
2807 /* _nx_pop3_parse_response Extract word from server response */
2808 /* _nx_pop3_digest_authenticate Create authentication string */
2809 /* */
2810 /* CALLED BY */
2811 /* */
2812 /* nxd_pop3_client_connect Connect with POP3 server */
2813 /* */
2814 /* RELEASE HISTORY */
2815 /* */
2816 /* DATE NAME DESCRIPTION */
2817 /* */
2818 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2819 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2820 /* verified memcpy use cases, */
2821 /* resulting in version 6.1 */
2822 /* */
2823 /**************************************************************************/
_nx_pop3_client_apop(NX_POP3_CLIENT * client_ptr)2824 UINT _nx_pop3_client_apop(NX_POP3_CLIENT *client_ptr)
2825 {
2826
2827 UINT status;
2828 NX_PACKET *packet_ptr, *recv_packet_ptr;
2829 CHAR *buffer;
2830 CHAR argument[10];
2831 CHAR md5_digest_buffer[NX_POP3_MAX_ASCII_MD5 + 1];
2832 UINT packet_type;
2833 UINT index;
2834 CHAR userid_buffer[100];
2835 UINT server_process_id_length;
2836 UINT client_password_length;
2837 UINT client_name_length;
2838 UINT md5_digest_buffer_length;
2839
2840
2841 if (client_ptr -> nx_pop3_client_tcp_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
2842 packet_type = NX_IPv6_TCP_PACKET;
2843 else
2844 packet_type = NX_IPv4_TCP_PACKET;
2845
2846 /* Allocate a packet. */
2847 status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
2848 &packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
2849
2850 /* Check for error. */
2851 if (status != NX_SUCCESS)
2852 {
2853
2854 /* Return the error condition. */
2855 return(status);
2856 }
2857
2858 /* Create the APOP digest. */
2859 memset(&userid_buffer[0],0,sizeof(userid_buffer));
2860
2861 /* Validate copy size. */
2862 if (_nx_utility_string_length_check(client_ptr -> nx_pop3_server_process_id, &server_process_id_length, NX_POP3_SERVER_PROCESS_ID_SIZE) ||
2863 _nx_utility_string_length_check(client_ptr -> nx_pop3_client_password, &client_password_length, NX_POP3_MAX_PASSWORD))
2864 {
2865 nx_packet_release(packet_ptr);
2866 return(NX_POP3_INSUFFICIENT_PACKET_PAYLOAD);
2867 }
2868 if((server_process_id_length + client_password_length) > sizeof(userid_buffer))
2869 {
2870 nx_packet_release(packet_ptr);
2871 return(NX_POP3_INSUFFICIENT_PACKET_PAYLOAD);
2872 }
2873
2874 memcpy(&userid_buffer[0], &client_ptr -> nx_pop3_server_process_id[0], server_process_id_length); /* Use case of memcpy is verified. */
2875 index = server_process_id_length;
2876 memcpy(&userid_buffer[index], &client_ptr -> nx_pop3_client_password[0], client_password_length); /* Use case of memcpy is verified. */
2877 status = _nx_pop3_digest_authenticate(client_ptr, &userid_buffer[0], (server_process_id_length + client_password_length), &md5_digest_buffer[0]);
2878
2879 /* Check for error. */
2880 if (status != NX_SUCCESS)
2881 {
2882
2883 nx_packet_release(packet_ptr);
2884
2885 /* Return failed APOP attempt error condition. */
2886 return NX_POP3_APOP_FAILED_MD5_DIGEST;
2887 }
2888
2889 /* Verify the packet payload will hold the APOP command. */
2890 if (_nx_utility_string_length_check(client_ptr -> nx_pop3_client_name, &client_name_length, NX_POP3_MAX_USERNAME) ||
2891 _nx_utility_string_length_check(md5_digest_buffer, &md5_digest_buffer_length, NX_POP3_MAX_ASCII_MD5))
2892 {
2893
2894 /* Release the packet. */
2895 nx_packet_release(packet_ptr);
2896
2897 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
2898 }
2899
2900 if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_APOP) - 1)
2901 + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1) + 2
2902 + client_name_length
2903 + md5_digest_buffer_length) >= packet_ptr -> nx_packet_data_end)
2904 {
2905
2906 /* Release the packet. */
2907 nx_packet_release(packet_ptr);
2908
2909 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
2910 }
2911
2912 buffer = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
2913
2914 /* Create the APOP command. */
2915 memcpy(buffer, NX_POP3_COMMAND_APOP, (sizeof(NX_POP3_COMMAND_APOP) - 1)); /* Use case of memcpy is verified. */
2916 buffer += (sizeof(NX_POP3_COMMAND_APOP) - 1);
2917 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_APOP) - 1);
2918 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_APOP) - 1);
2919
2920 memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
2921 buffer++;
2922 packet_ptr -> nx_packet_append_ptr++;
2923 packet_ptr -> nx_packet_length++;
2924
2925 memcpy(buffer, client_ptr -> nx_pop3_client_name, client_name_length); /* Use case of memcpy is verified. */
2926 buffer += client_name_length;
2927 packet_ptr -> nx_packet_length += client_name_length;
2928 packet_ptr -> nx_packet_append_ptr += client_name_length;
2929
2930 memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
2931 buffer++;
2932 packet_ptr -> nx_packet_append_ptr++;
2933 packet_ptr -> nx_packet_length++;
2934
2935 memcpy(buffer, &md5_digest_buffer[0], md5_digest_buffer_length); /* Use case of memcpy is verified. */
2936 buffer += md5_digest_buffer_length;
2937 packet_ptr -> nx_packet_length += md5_digest_buffer_length;
2938 packet_ptr -> nx_packet_append_ptr += md5_digest_buffer_length;
2939
2940 memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
2941 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
2942 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
2943
2944 /* Send the packet out. */
2945 status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
2946
2947 /* Check for error. */
2948 if (status != NX_SUCCESS)
2949 {
2950
2951 /* Release the packet. */
2952 nx_packet_release(packet_ptr);
2953
2954 /* Return the error condition. */
2955 return(status);
2956 }
2957
2958 /* Receive server reply over session socket. */
2959 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
2960
2961 /* Check for error. */
2962 if (status != NX_SUCCESS)
2963 {
2964
2965 /* Return error condition. */
2966 return(status);
2967 }
2968
2969 #ifndef NX_DISABLE_PACKET_CHAIN
2970 if (recv_packet_ptr -> nx_packet_next)
2971 {
2972
2973 /* Chained packet is not supported. */
2974 nx_packet_release(recv_packet_ptr);
2975 return(NX_INVALID_PACKET);
2976 }
2977 #endif /* NX_DISABLE_PACKET_CHAIN */
2978
2979 /* Set a pointer to the packet data. */
2980 buffer = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
2981
2982 /* Parse the first argument of the server reply. */
2983 _nx_pop3_parse_response(buffer, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
2984
2985 /* Initialize status to bad reply error condition. */
2986 status = NX_POP3_SERVER_ERROR_STATUS;
2987
2988 /* Did the server accept the Client command? */
2989 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
2990 {
2991
2992 /* APOP command accepted. */
2993 status = NX_SUCCESS;
2994 }
2995
2996 nx_packet_release(recv_packet_ptr);
2997
2998 return status;
2999 }
3000
3001
3002 /**************************************************************************/
3003 /* */
3004 /* FUNCTION RELEASE */
3005 /* */
3006 /* _nx_pop3_client_user_pass PORTABLE C */
3007 /* 6.1 */
3008 /* AUTHOR */
3009 /* */
3010 /* Yuxin Zhou, Microsoft Corporation */
3011 /* */
3012 /* DESCRIPTION */
3013 /* */
3014 /* This function attempts to login using client sername and password */
3015 /* with the POP3 server. If successful returns NX_SUCCESS. */
3016 /* */
3017 /* INPUT */
3018 /* */
3019 /* client_ptr Pointer to client struct */
3020 /* */
3021 /* OUTPUT */
3022 /* */
3023 /* NX_SUCCESS Login accepted by server */
3024 /* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
3025 /* Packet too small for command */
3026 /* status Actual completion status */
3027 /* */
3028 /* CALLS */
3029 /* */
3030 /* nx_packet_allocate Allocate packet from packet pool */
3031 /* nx_packet_release Release packet back to pool */
3032 /* nx_tcp_socket_send Send packet out TCP socket */
3033 /* nx_tcp_socket_receive Retrieve packet from TCP socket */
3034 /* _nx_pop3_parse_response Extract word from server response */
3035 /* _nx_pop3_digest_authenticate Create authentication string */
3036 /* */
3037 /* CALLED BY */
3038 /* */
3039 /* nxd_pop3_client_connect Connect with POP3 server */
3040 /* */
3041 /* RELEASE HISTORY */
3042 /* */
3043 /* DATE NAME DESCRIPTION */
3044 /* */
3045 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3046 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
3047 /* verified memcpy use cases, */
3048 /* resulting in version 6.1 */
3049 /* */
3050 /**************************************************************************/
_nx_pop3_client_user_pass(NX_POP3_CLIENT * client_ptr)3051 UINT _nx_pop3_client_user_pass(NX_POP3_CLIENT *client_ptr)
3052 {
3053
3054 UINT status;
3055 NX_PACKET *packet_ptr, *recv_packet_ptr, *next_recv_packet_ptr;
3056 CHAR *buffer;
3057 CHAR argument[10];
3058 UINT packet_type;
3059 UINT client_name_length;
3060 UINT client_password_length;
3061
3062
3063 if (client_ptr -> nx_pop3_client_tcp_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
3064 packet_type = NX_IPv6_TCP_PACKET;
3065 else
3066 packet_type = NX_IPv4_TCP_PACKET;
3067
3068 /* Allocate a packet. */
3069 status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
3070 &packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
3071
3072 /* Check for error. */
3073 if (status != NX_SUCCESS)
3074 {
3075
3076 /* Return the error condition. */
3077 return(status);
3078 }
3079
3080 /* Verify the packet payload will hold the user command message. */
3081 if (_nx_utility_string_length_check(client_ptr -> nx_pop3_client_name, &client_name_length, NX_POP3_MAX_USERNAME))
3082 {
3083
3084 /* Release the packet. */
3085 nx_packet_release(packet_ptr);
3086
3087 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
3088 }
3089
3090 if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_USER) - 1) +
3091 1 + client_name_length + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1))
3092 >= packet_ptr -> nx_packet_data_end)
3093 {
3094
3095 /* Release the packet. */
3096 nx_packet_release(packet_ptr);
3097
3098 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
3099 }
3100
3101 buffer = (CHAR *)(packet_ptr -> nx_packet_prepend_ptr);
3102
3103
3104 memcpy(buffer, NX_POP3_COMMAND_USER, (sizeof(NX_POP3_COMMAND_USER) - 1)); /* Use case of memcpy is verified. */
3105 packet_ptr -> nx_packet_length = (sizeof(NX_POP3_COMMAND_USER) - 1);
3106 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_USER) - 1);
3107 buffer += (sizeof(NX_POP3_COMMAND_USER) - 1);
3108
3109 memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
3110 packet_ptr -> nx_packet_length++;
3111 packet_ptr -> nx_packet_append_ptr++;
3112 buffer++;
3113
3114 memcpy(buffer, client_ptr -> nx_pop3_client_name, client_name_length); /* Use case of memcpy is verified. */
3115 packet_ptr -> nx_packet_length += client_name_length;
3116 packet_ptr -> nx_packet_append_ptr += client_name_length;
3117 buffer += client_name_length;
3118
3119 memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
3120 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
3121 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
3122 buffer += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
3123
3124 /* Send the packet out. */
3125 status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
3126
3127 /* Check for error. */
3128 if (status != NX_SUCCESS)
3129 {
3130
3131 /* Release the packet. */
3132 nx_packet_release(packet_ptr);
3133
3134 /* Return the error condition. */
3135 return(status);
3136 }
3137
3138 /* Receive server reply to Client username over session socket. */
3139 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
3140
3141 /* Check for error. */
3142 if (status != NX_SUCCESS)
3143 {
3144
3145 /* Return error condition. */
3146 return(status);
3147 }
3148
3149 #ifndef NX_DISABLE_PACKET_CHAIN
3150 if (recv_packet_ptr -> nx_packet_next)
3151 {
3152
3153 /* Chained packet is not supported. */
3154 nx_packet_release(recv_packet_ptr);
3155 return(NX_INVALID_PACKET);
3156 }
3157 #endif /* NX_DISABLE_PACKET_CHAIN */
3158
3159 /* Set a pointer to the packet data. */
3160 buffer = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
3161
3162 /* Parse the first argument of the server reply. */
3163 _nx_pop3_parse_response(buffer, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
3164
3165 /* Initialize status to bad reply error condition. */
3166 status = NX_POP3_SERVER_ERROR_STATUS;
3167
3168 /* Did the server accept the Client command? */
3169 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
3170 {
3171
3172 /* We are done with this packet. */
3173 nx_packet_release(recv_packet_ptr);
3174
3175 if (client_ptr -> nx_pop3_client_tcp_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6)
3176 packet_type = NX_IPv6_TCP_PACKET;
3177 else
3178 packet_type = NX_IPv4_TCP_PACKET;
3179
3180 /* Allocate another packet. */
3181 status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
3182 &packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
3183
3184 /* Check for error. */
3185 if (status != NX_SUCCESS)
3186 {
3187
3188 /* Return the error condition. */
3189 return(status);
3190 }
3191
3192 /* Verify the packet payload will hold the password request. */
3193 if (_nx_utility_string_length_check(client_ptr -> nx_pop3_client_password, &client_password_length, NX_POP3_MAX_PASSWORD))
3194 {
3195
3196 /* Release the packet. */
3197 nx_packet_release(packet_ptr);
3198
3199 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
3200 }
3201
3202 if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_PASS) - 1) +
3203 1 + client_password_length + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1))
3204 >= packet_ptr -> nx_packet_data_end)
3205 {
3206
3207 /* Release the packet. */
3208 nx_packet_release(packet_ptr);
3209
3210 return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
3211 }
3212
3213 buffer = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
3214 memcpy(buffer, NX_POP3_COMMAND_PASS, (sizeof(NX_POP3_COMMAND_PASS) - 1)); /* Use case of memcpy is verified. */
3215 buffer += (sizeof(NX_POP3_COMMAND_PASS) - 1);
3216 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_PASS) - 1);
3217 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_PASS) - 1);
3218
3219 memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
3220 buffer++;
3221 packet_ptr -> nx_packet_length++;
3222 packet_ptr -> nx_packet_append_ptr++;
3223
3224 memcpy(buffer, client_ptr -> nx_pop3_client_password, client_password_length); /* Use case of memcpy is verified. */
3225 buffer += client_password_length;
3226 packet_ptr -> nx_packet_length += client_password_length;
3227 packet_ptr -> nx_packet_append_ptr += client_password_length;
3228
3229 memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
3230 buffer += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
3231 packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
3232 packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
3233
3234 /* Send the next Client message out. */
3235 status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
3236
3237 /* Check for error. */
3238 if (status != NX_SUCCESS)
3239 {
3240
3241 /* Release the packet. */
3242 nx_packet_release(packet_ptr);
3243
3244 /* Return the error condition. */
3245 return(status);
3246 }
3247
3248 /* Receive server reply to Client password over session socket. */
3249 status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &next_recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
3250
3251 /* Check for error. */
3252 if (status != NX_SUCCESS)
3253 {
3254
3255 /* Return error condition. */
3256 return(status);
3257 }
3258
3259 #ifndef NX_DISABLE_PACKET_CHAIN
3260 if (next_recv_packet_ptr -> nx_packet_next)
3261 {
3262
3263 /* Chained packet is not supported. */
3264 nx_packet_release(next_recv_packet_ptr);
3265 return(NX_INVALID_PACKET);
3266 }
3267 #endif /* NX_DISABLE_PACKET_CHAIN */
3268
3269 /* Set a pointer to the packet data. */
3270 buffer = (CHAR *)(next_recv_packet_ptr -> nx_packet_prepend_ptr);
3271
3272 /* Parse the first argument of the server reply. */
3273 _nx_pop3_parse_response(buffer, 1, next_recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
3274
3275 /* Did the server accept the Client command? */
3276 if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
3277 {
3278
3279 status = NX_SUCCESS;
3280 }
3281
3282 /* We are done with this packet. */
3283 nx_packet_release(next_recv_packet_ptr);
3284 }
3285 else
3286 {
3287
3288 /* Server rejected the Client message. */
3289 nx_packet_release(recv_packet_ptr);
3290 }
3291
3292 return status;
3293 }
3294
3295