Split create_ssl_connection()
[openssl.git] / test / ssltestlib.c
1 /*
2  * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <string.h>
11
12 #include "ssltestlib.h"
13
14 static int tls_dump_new(BIO *bi);
15 static int tls_dump_free(BIO *a);
16 static int tls_dump_read(BIO *b, char *out, int outl);
17 static int tls_dump_write(BIO *b, const char *in, int inl);
18 static long tls_dump_ctrl(BIO *b, int cmd, long num, void *ptr);
19 static int tls_dump_gets(BIO *bp, char *buf, int size);
20 static int tls_dump_puts(BIO *bp, const char *str);
21
22 /* Choose a sufficiently large type likely to be unused for this custom BIO */
23 # define BIO_TYPE_TLS_DUMP_FILTER  (0x80 | BIO_TYPE_FILTER)
24
25 # define BIO_TYPE_MEMPACKET_TEST      0x81
26
27 static BIO_METHOD *method_tls_dump = NULL;
28 static BIO_METHOD *method_mempacket_test = NULL;
29
30 /* Note: Not thread safe! */
31 const BIO_METHOD *bio_f_tls_dump_filter(void)
32 {
33     if (method_tls_dump == NULL) {
34         method_tls_dump = BIO_meth_new(BIO_TYPE_TLS_DUMP_FILTER,
35                                         "TLS dump filter");
36         if (   method_tls_dump == NULL
37             || !BIO_meth_set_write(method_tls_dump, tls_dump_write)
38             || !BIO_meth_set_read(method_tls_dump, tls_dump_read)
39             || !BIO_meth_set_puts(method_tls_dump, tls_dump_puts)
40             || !BIO_meth_set_gets(method_tls_dump, tls_dump_gets)
41             || !BIO_meth_set_ctrl(method_tls_dump, tls_dump_ctrl)
42             || !BIO_meth_set_create(method_tls_dump, tls_dump_new)
43             || !BIO_meth_set_destroy(method_tls_dump, tls_dump_free))
44             return NULL;
45     }
46     return method_tls_dump;
47 }
48
49 void bio_f_tls_dump_filter_free(void)
50 {
51     BIO_meth_free(method_tls_dump);
52 }
53
54 static int tls_dump_new(BIO *bio)
55 {
56     BIO_set_init(bio, 1);
57     return 1;
58 }
59
60 static int tls_dump_free(BIO *bio)
61 {
62     BIO_set_init(bio, 0);
63
64     return 1;
65 }
66
67 static void copy_flags(BIO *bio)
68 {
69     int flags;
70     BIO *next = BIO_next(bio);
71
72     flags = BIO_test_flags(next, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_RWS);
73     BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_RWS);
74     BIO_set_flags(bio, flags);
75 }
76
77 #define RECORD_CONTENT_TYPE     0
78 #define RECORD_VERSION_HI       1
79 #define RECORD_VERSION_LO       2
80 #define RECORD_EPOCH_HI         3
81 #define RECORD_EPOCH_LO         4
82 #define RECORD_SEQUENCE_START   5
83 #define RECORD_SEQUENCE_END     10
84 #define RECORD_LEN_HI           11
85 #define RECORD_LEN_LO           12
86
87 #define MSG_TYPE                0
88 #define MSG_LEN_HI              1
89 #define MSG_LEN_MID             2
90 #define MSG_LEN_LO              3
91 #define MSG_SEQ_HI              4
92 #define MSG_SEQ_LO              5
93 #define MSG_FRAG_OFF_HI         6
94 #define MSG_FRAG_OFF_MID        7
95 #define MSG_FRAG_OFF_LO         8
96 #define MSG_FRAG_LEN_HI         9
97 #define MSG_FRAG_LEN_MID        10
98 #define MSG_FRAG_LEN_LO         11
99
100
101 static void dump_data(const char *data, int len)
102 {
103     int rem, i, content, reclen, msglen, fragoff, fraglen, epoch;
104     unsigned char *rec;
105
106     printf("---- START OF PACKET ----\n");
107
108     rem = len;
109     rec = (unsigned char *)data;
110
111     while (rem > 0) {
112         if (rem != len)
113             printf("*\n");
114         printf("*---- START OF RECORD ----\n");
115         if (rem < DTLS1_RT_HEADER_LENGTH) {
116             printf("*---- RECORD TRUNCATED ----\n");
117             break;
118         }
119         content = rec[RECORD_CONTENT_TYPE];
120         printf("** Record Content-type: %d\n", content);
121         printf("** Record Version: %02x%02x\n",
122                rec[RECORD_VERSION_HI], rec[RECORD_VERSION_LO]);
123         epoch = (rec[RECORD_EPOCH_HI] << 8) | rec[RECORD_EPOCH_LO];
124         printf("** Record Epoch: %d\n", epoch);
125         printf("** Record Sequence: ");
126         for (i = RECORD_SEQUENCE_START; i <= RECORD_SEQUENCE_END; i++)
127             printf("%02x", rec[i]);
128         reclen = (rec[RECORD_LEN_HI] << 8) | rec[RECORD_LEN_LO];
129         printf("\n** Record Length: %d\n", reclen);
130
131         /* Now look at message */
132         rec += DTLS1_RT_HEADER_LENGTH;
133         rem -= DTLS1_RT_HEADER_LENGTH;
134         if (content == SSL3_RT_HANDSHAKE) {
135             printf("**---- START OF HANDSHAKE MESSAGE FRAGMENT ----\n");
136             if (epoch > 0) {
137                 printf("**---- HANDSHAKE MESSAGE FRAGMENT ENCRYPTED ----\n");
138             } else if (rem < DTLS1_HM_HEADER_LENGTH
139                     || reclen < DTLS1_HM_HEADER_LENGTH) {
140                 printf("**---- HANDSHAKE MESSAGE FRAGMENT TRUNCATED ----\n");
141             } else {
142                 printf("*** Message Type: %d\n", rec[MSG_TYPE]);
143                 msglen = (rec[MSG_LEN_HI] << 16) | (rec[MSG_LEN_MID] << 8)
144                          | rec[MSG_LEN_LO];
145                 printf("*** Message Length: %d\n", msglen);
146                 printf("*** Message sequence: %d\n",
147                        (rec[MSG_SEQ_HI] << 8) | rec[MSG_SEQ_LO]);
148                 fragoff = (rec[MSG_FRAG_OFF_HI] << 16)
149                           | (rec[MSG_FRAG_OFF_MID] << 8)
150                           | rec[MSG_FRAG_OFF_LO];
151                 printf("*** Message Fragment offset: %d\n", fragoff);
152                 fraglen = (rec[MSG_FRAG_LEN_HI] << 16)
153                           | (rec[MSG_FRAG_LEN_MID] << 8)
154                           | rec[MSG_FRAG_LEN_LO];
155                 printf("*** Message Fragment len: %d\n", fraglen);
156                 if (fragoff + fraglen > msglen)
157                     printf("***---- HANDSHAKE MESSAGE FRAGMENT INVALID ----\n");
158                 else if(reclen < fraglen)
159                     printf("**---- HANDSHAKE MESSAGE FRAGMENT TRUNCATED ----\n");
160                 else
161                     printf("**---- END OF HANDSHAKE MESSAGE FRAGMENT ----\n");
162             }
163         }
164         if (rem < reclen) {
165             printf("*---- RECORD TRUNCATED ----\n");
166             rem = 0;
167         } else {
168             rec += reclen;
169             rem -= reclen;
170             printf("*---- END OF RECORD ----\n");
171         }
172     }
173     printf("---- END OF PACKET ----\n\n");
174     fflush(stdout);
175 }
176
177 static int tls_dump_read(BIO *bio, char *out, int outl)
178 {
179     int ret;
180     BIO *next = BIO_next(bio);
181
182     ret = BIO_read(next, out, outl);
183     copy_flags(bio);
184
185     if (ret > 0) {
186         dump_data(out, ret);
187     }
188
189     return ret;
190 }
191
192 static int tls_dump_write(BIO *bio, const char *in, int inl)
193 {
194     int ret;
195     BIO *next = BIO_next(bio);
196
197     ret = BIO_write(next, in, inl);
198     copy_flags(bio);
199
200     return ret;
201 }
202
203 static long tls_dump_ctrl(BIO *bio, int cmd, long num, void *ptr)
204 {
205     long ret;
206     BIO *next = BIO_next(bio);
207
208     if (next == NULL)
209         return 0;
210
211     switch (cmd) {
212     case BIO_CTRL_DUP:
213         ret = 0L;
214         break;
215     default:
216         ret = BIO_ctrl(next, cmd, num, ptr);
217         break;
218     }
219     return ret;
220 }
221
222 static int tls_dump_gets(BIO *bio, char *buf, int size)
223 {
224     /* We don't support this - not needed anyway */
225     return -1;
226 }
227
228 static int tls_dump_puts(BIO *bio, const char *str)
229 {
230     return tls_dump_write(bio, str, strlen(str));
231 }
232
233
234 typedef struct mempacket_st {
235     unsigned char *data;
236     int len;
237     unsigned int num;
238     unsigned int type;
239 } MEMPACKET;
240
241 DEFINE_STACK_OF(MEMPACKET)
242
243 static void mempacket_free(MEMPACKET *pkt)
244 {
245     if (pkt->data != NULL)
246         OPENSSL_free(pkt->data);
247     OPENSSL_free(pkt);
248 }
249
250 typedef struct mempacket_test_ctx_st {
251     STACK_OF(MEMPACKET) *pkts;
252     unsigned int epoch;
253     unsigned int currrec;
254     unsigned int currpkt;
255     unsigned int lastpkt;
256     unsigned int noinject;
257 } MEMPACKET_TEST_CTX;
258
259 static int mempacket_test_new(BIO *bi);
260 static int mempacket_test_free(BIO *a);
261 static int mempacket_test_read(BIO *b, char *out, int outl);
262 static int mempacket_test_write(BIO *b, const char *in, int inl);
263 static long mempacket_test_ctrl(BIO *b, int cmd, long num, void *ptr);
264 static int mempacket_test_gets(BIO *bp, char *buf, int size);
265 static int mempacket_test_puts(BIO *bp, const char *str);
266
267 const BIO_METHOD *bio_s_mempacket_test(void)
268 {
269     if (method_mempacket_test == NULL) {
270         method_mempacket_test = BIO_meth_new(BIO_TYPE_MEMPACKET_TEST,
271                                              "Mem Packet Test");
272         if (   method_mempacket_test == NULL
273             || !BIO_meth_set_write(method_mempacket_test, mempacket_test_write)
274             || !BIO_meth_set_read(method_mempacket_test, mempacket_test_read)
275             || !BIO_meth_set_puts(method_mempacket_test, mempacket_test_puts)
276             || !BIO_meth_set_gets(method_mempacket_test, mempacket_test_gets)
277             || !BIO_meth_set_ctrl(method_mempacket_test, mempacket_test_ctrl)
278             || !BIO_meth_set_create(method_mempacket_test, mempacket_test_new)
279             || !BIO_meth_set_destroy(method_mempacket_test, mempacket_test_free))
280             return NULL;
281     }
282     return method_mempacket_test;
283 }
284
285 void bio_s_mempacket_test_free(void)
286 {
287     BIO_meth_free(method_mempacket_test);
288 }
289
290 static int mempacket_test_new(BIO *bio)
291 {
292     MEMPACKET_TEST_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
293     if (ctx == NULL)
294         return 0;
295     ctx->pkts = sk_MEMPACKET_new_null();
296     if (ctx->pkts == NULL) {
297         OPENSSL_free(ctx);
298         return 0;
299     }
300     BIO_set_init(bio, 1);
301     BIO_set_data(bio, ctx);
302     return 1;
303 }
304
305 static int mempacket_test_free(BIO *bio)
306 {
307     MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
308
309     sk_MEMPACKET_pop_free(ctx->pkts, mempacket_free);
310     OPENSSL_free(ctx);
311     BIO_set_data(bio, NULL);
312     BIO_set_init(bio, 0);
313
314     return 1;
315 }
316
317 /* Record Header values */
318 #define EPOCH_HI        4
319 #define EPOCH_LO        5
320 #define RECORD_SEQUENCE 10
321 #define RECORD_LEN_HI   11
322 #define RECORD_LEN_LO   12
323
324 #define STANDARD_PACKET                 0
325
326 static int mempacket_test_read(BIO *bio, char *out, int outl)
327 {
328     MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
329     MEMPACKET *thispkt;
330     unsigned char *rec;
331     int rem;
332     unsigned int seq, offset, len, epoch;
333
334     BIO_clear_retry_flags(bio);
335
336     thispkt = sk_MEMPACKET_value(ctx->pkts, 0);
337     if (thispkt == NULL || thispkt->num != ctx->currpkt) {
338         /* Probably run out of data */
339         BIO_set_retry_read(bio);
340         return -1;
341     }
342     sk_MEMPACKET_shift(ctx->pkts);
343     ctx->currpkt++;
344
345     if (outl > thispkt->len)
346         outl = thispkt->len;
347
348     if (thispkt->type != INJECT_PACKET_IGNORE_REC_SEQ) {
349         /*
350          * Overwrite the record sequence number. We strictly number them in
351          * the order received. Since we are actually a reliable transport
352          * we know that there won't be any re-ordering. We overwrite to deal
353          * with any packets that have been injected
354          */
355         rem = thispkt->len;
356         rec = thispkt->data;
357         while (rem > 0) {
358             if (rem < DTLS1_RT_HEADER_LENGTH) {
359                 return -1;
360             }
361             epoch = (rec[EPOCH_HI] << 8) | rec[EPOCH_LO];
362             if (epoch != ctx->epoch) {
363                 ctx->epoch = epoch;
364                 ctx->currrec = 0;
365             }
366             seq = ctx->currrec;
367             offset = 0;
368             do {
369                 rec[RECORD_SEQUENCE - offset] = seq & 0xFF;
370                 seq >>= 8;
371                 offset++;
372             } while (seq > 0);
373             ctx->currrec++;
374
375             len = ((rec[RECORD_LEN_HI] << 8) | rec[RECORD_LEN_LO])
376                   + DTLS1_RT_HEADER_LENGTH;
377
378             rec += len;
379             rem -= len;
380         }
381     }
382
383     memcpy(out, thispkt->data, outl);
384
385     mempacket_free(thispkt);
386
387     return outl;
388 }
389
390 int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
391                           int type)
392 {
393     MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
394     MEMPACKET *thispkt, *looppkt, *nextpkt;
395     int i;
396
397     if (ctx == NULL)
398         return -1;
399
400     /* We only allow injection before we've started writing any data */
401     if (pktnum >= 0) {
402         if (ctx->noinject)
403             return -1;
404     } else {
405         ctx->noinject = 1;
406     }
407
408     thispkt = OPENSSL_malloc(sizeof(MEMPACKET));
409     if (thispkt == NULL)
410         return -1;
411
412     thispkt->data = OPENSSL_malloc(inl);
413     if (thispkt->data == NULL) {
414         mempacket_free(thispkt);
415         return -1;
416     }
417
418     memcpy(thispkt->data, in, inl);
419     thispkt->len = inl;
420     thispkt->num = (pktnum >= 0) ? (unsigned int)pktnum : ctx->lastpkt;
421     thispkt->type = type;
422
423     for(i = 0; (looppkt = sk_MEMPACKET_value(ctx->pkts, i)) != NULL; i++) {
424         /* Check if we found the right place to insert this packet */
425         if (looppkt->num > thispkt->num) {
426             if (sk_MEMPACKET_insert(ctx->pkts, thispkt, i) == 0) {
427                 mempacket_free(thispkt);
428                 return -1;
429             }
430             /* If we're doing up front injection then we're done */
431             if (pktnum >= 0)
432                 return inl;
433             /*
434              * We need to do some accounting on lastpkt. We increment it first,
435              * but it might now equal the value of injected packets, so we need
436              * to skip over those
437              */
438             ctx->lastpkt++;
439             do {
440                 i++;
441                 nextpkt = sk_MEMPACKET_value(ctx->pkts, i);
442                 if (nextpkt != NULL && nextpkt->num == ctx->lastpkt)
443                     ctx->lastpkt++;
444                 else
445                     return inl;
446             } while(1);
447         } else if(looppkt->num == thispkt->num) {
448             if (!ctx->noinject) {
449                 /* We injected two packets with the same packet number! */
450                 return -1;
451             }
452             ctx->lastpkt++;
453             thispkt->num++;
454         }
455     }
456     /*
457      * We didn't find any packets with a packet number equal to or greater than
458      * this one, so we just add it onto the end
459      */
460     if (!sk_MEMPACKET_push(ctx->pkts, thispkt)) {
461         mempacket_free(thispkt);
462         return -1;
463     }
464
465     if (pktnum < 0)
466         ctx->lastpkt++;
467
468     return inl;
469 }
470
471 static int mempacket_test_write(BIO *bio, const char *in, int inl)
472 {
473     return mempacket_test_inject(bio, in, inl, -1, STANDARD_PACKET);
474 }
475
476 static long mempacket_test_ctrl(BIO *bio, int cmd, long num, void *ptr)
477 {
478     long ret = 1;
479     MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
480     MEMPACKET *thispkt;
481
482     switch (cmd) {
483     case BIO_CTRL_EOF:
484         ret = (long)(sk_MEMPACKET_num(ctx->pkts) == 0);
485         break;
486     case BIO_CTRL_GET_CLOSE:
487         ret = BIO_get_shutdown(bio);
488         break;
489     case BIO_CTRL_SET_CLOSE:
490         BIO_set_shutdown(bio, (int)num);
491         break;
492     case BIO_CTRL_WPENDING:
493         ret = 0L;
494         break;
495     case BIO_CTRL_PENDING:
496         thispkt = sk_MEMPACKET_value(ctx->pkts, 0);
497         if (thispkt == NULL)
498             ret = 0;
499         else
500             ret = thispkt->len;
501         break;
502     case BIO_CTRL_FLUSH:
503         ret = 1;
504         break;
505     case BIO_CTRL_RESET:
506     case BIO_CTRL_DUP:
507     case BIO_CTRL_PUSH:
508     case BIO_CTRL_POP:
509     default:
510         ret = 0;
511         break;
512     }
513     return ret;
514 }
515
516 static int mempacket_test_gets(BIO *bio, char *buf, int size)
517 {
518     /* We don't support this - not needed anyway */
519     return -1;
520 }
521
522 static int mempacket_test_puts(BIO *bio, const char *str)
523 {
524     return mempacket_test_write(bio, str, strlen(str));
525 }
526
527 int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm,
528                         SSL_CTX **sctx, SSL_CTX **cctx, char *certfile,
529                         char *privkeyfile)
530 {
531     SSL_CTX *serverctx = NULL;
532     SSL_CTX *clientctx = NULL;
533
534     serverctx = SSL_CTX_new(sm);
535     clientctx = SSL_CTX_new(cm);
536     if (serverctx == NULL || clientctx == NULL) {
537         printf("Failed to create SSL_CTX\n");
538         goto err;
539     }
540
541     if (SSL_CTX_use_certificate_file(serverctx, certfile,
542                                      SSL_FILETYPE_PEM) <= 0) {
543         printf("Failed to load server certificate\n");
544         goto err;
545     }
546     if (SSL_CTX_use_PrivateKey_file(serverctx, privkeyfile,
547                                     SSL_FILETYPE_PEM) <= 0) {
548         printf("Failed to load server private key\n");
549     }
550     if (SSL_CTX_check_private_key(serverctx) <= 0) {
551         printf("Failed to check private key\n");
552         goto err;
553     }
554
555     *sctx = serverctx;
556     *cctx = clientctx;
557
558     return 1;
559  err:
560     SSL_CTX_free(serverctx);
561     SSL_CTX_free(clientctx);
562     return 0;
563 }
564
565 #define MAXLOOPS    100000
566
567 /*
568  * NOTE: Transfers control of the BIOs - this function will free them on error
569  */
570 int create_ssl_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
571                           SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio)
572 {
573     SSL *serverssl, *clientssl;
574     BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL;
575
576     if (*sssl == NULL)
577         serverssl = SSL_new(serverctx);
578     else
579         serverssl = *sssl;
580     if (*cssl == NULL)
581         clientssl = SSL_new(clientctx);
582     else
583         clientssl = *cssl;
584
585     if (serverssl == NULL || clientssl == NULL) {
586         printf("Failed to create SSL object\n");
587         goto error;
588     }
589
590     if (SSL_is_dtls(clientssl)) {
591         s_to_c_bio = BIO_new(bio_s_mempacket_test());
592         c_to_s_bio = BIO_new(bio_s_mempacket_test());;
593     } else {
594         s_to_c_bio = BIO_new(BIO_s_mem());
595         c_to_s_bio = BIO_new(BIO_s_mem());
596     }
597     if (s_to_c_bio == NULL || c_to_s_bio == NULL) {
598         printf("Failed to create mem BIOs\n");
599         goto error;
600     }
601
602     if (s_to_c_fbio != NULL)
603         s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio);
604     if (c_to_s_fbio != NULL)
605         c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio);
606     if (s_to_c_bio == NULL || c_to_s_bio == NULL) {
607         printf("Failed to create chained BIOs\n");
608         goto error;
609     }
610
611     /* Set Non-blocking IO behaviour */
612     BIO_set_mem_eof_return(s_to_c_bio, -1);
613     BIO_set_mem_eof_return(c_to_s_bio, -1);
614
615     /* Up ref these as we are passing them to two SSL objects */
616     BIO_up_ref(s_to_c_bio);
617     BIO_up_ref(c_to_s_bio);
618
619     SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio);
620     SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio);
621
622     /* BIOs will now be freed when SSL objects are freed */
623     s_to_c_bio = c_to_s_bio = NULL;
624     s_to_c_fbio = c_to_s_fbio = NULL;
625
626     *sssl = serverssl;
627     *cssl = clientssl;
628
629     return 1;
630
631  error:
632     SSL_free(serverssl);
633     SSL_free(clientssl);
634     BIO_free(s_to_c_bio);
635     BIO_free(c_to_s_bio);
636     BIO_free(s_to_c_fbio);
637     BIO_free(c_to_s_fbio);
638
639     return 0;
640 }
641
642 int create_ssl_connection(SSL *serverssl, SSL *clientssl)
643 {
644     int retc = -1, rets = -1, err, abortctr = 0;
645     int clienterr = 0, servererr = 0;
646
647     do {
648         err = SSL_ERROR_WANT_WRITE;
649         while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
650             retc = SSL_connect(clientssl);
651             if (retc <= 0)
652                 err = SSL_get_error(clientssl, retc);
653         }
654
655         if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
656             printf("SSL_connect() failed %d, %d\n", retc, err);
657             clienterr = 1;
658         }
659
660         err = SSL_ERROR_WANT_WRITE;
661         while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
662             rets = SSL_accept(serverssl);
663             if (rets <= 0)
664                 err = SSL_get_error(serverssl, rets);
665         }
666
667         if (!servererr && rets <= 0 && err != SSL_ERROR_WANT_READ) {
668             printf("SSL_accept() failed %d, %d\n", retc, err);
669             servererr = 1;
670         }
671         if (clienterr && servererr)
672             return 0;
673         if (++abortctr == MAXLOOPS) {
674             printf("No progress made\n");
675             return 0;
676         }
677     } while (retc <=0 || rets <= 0);
678
679     return 1;
680 }