Missed one case of "retry time not reached" when adding additional
[users/jgh/exim.git] / test / src / client.c
1 /* $Cambridge: exim/test/src/client.c,v 1.1 2006/02/06 16:24:05 ph10 Exp $ */
2
3 /* A little hacked up program that makes a TCP/IP call and reads a script to
4 drive it, for testing Exim server code running as a daemon. It's got a bit
5 messy with the addition of support for either OpenSSL or GnuTLS. The code for
6 those was hacked out of Exim itself. */
7
8 /* ANSI C standard includes */
9
10 #include <ctype.h>
11 #include <signal.h>
12 #include <stdarg.h>
13 #include <stddef.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <time.h>
18
19 /* Unix includes */
20
21 #include <errno.h>
22 #include <dirent.h>
23 #include <sys/types.h>
24
25 #include <netinet/in_systm.h>
26 #include <netinet/in.h>
27 #include <netinet/ip.h>
28
29 #include <netdb.h>
30 #include <arpa/inet.h>
31 #include <sys/time.h>
32 #include <sys/resource.h>
33 #include <sys/socket.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <utime.h>
38
39 #ifdef AF_INET6
40 #define HAVE_IPV6 1
41 #endif
42
43 #ifndef S_ADDR_TYPE
44 #define S_ADDR_TYPE u_long
45 #endif
46
47 typedef unsigned char uschar;
48
49 #define CS   (char *)
50 #define US   (unsigned char *)
51
52 #define FALSE         0
53 #define TRUE          1
54
55
56
57 static int sigalrm_seen = 0;
58
59
60 /* TLS support can be optionally included, either for OpenSSL or GnuTLS. The
61 latter needs a whole pile of tables. */
62
63 #ifdef HAVE_OPENSSL
64 #define HAVE_TLS
65 #include <openssl/crypto.h>
66 #include <openssl/x509.h>
67 #include <openssl/pem.h>
68 #include <openssl/ssl.h>
69 #include <openssl/err.h>
70 #include <openssl/rand.h>
71 #endif
72
73
74 #ifdef HAVE_GNUTLS
75 #define HAVE_TLS
76 #include <gnutls/gnutls.h>
77 #include <gnutls/x509.h>
78
79 #define DH_BITS      768
80 #define RSA_BITS     512
81
82 /* Local static variables for GNUTLS */
83
84 static gnutls_rsa_params rsa_params = NULL;
85 static gnutls_dh_params dh_params = NULL;
86
87 static gnutls_certificate_credentials_t x509_cred = NULL;
88 static gnutls_session tls_session = NULL;
89
90 static int  ssl_session_timeout = 200;
91
92 /* Priorities for TLS algorithms to use. */
93
94 static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
95
96 static const int kx_priority[16] = {
97   GNUTLS_KX_RSA,
98   GNUTLS_KX_DHE_DSS,
99   GNUTLS_KX_DHE_RSA,
100   GNUTLS_KX_RSA_EXPORT,
101   0 };
102
103 static int default_cipher_priority[16] = {
104   GNUTLS_CIPHER_AES_256_CBC,
105   GNUTLS_CIPHER_AES_128_CBC,
106   GNUTLS_CIPHER_3DES_CBC,
107   GNUTLS_CIPHER_ARCFOUR_128,
108   0 };
109
110 static const int mac_priority[16] = {
111   GNUTLS_MAC_SHA,
112   GNUTLS_MAC_MD5,
113   0 };
114
115 static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
116 static const int cert_type_priority[16] = { GNUTLS_CRT_X509, 0 };
117
118 #endif
119
120
121
122
123 /*************************************************
124 *            SIGALRM handler - crash out         *
125 *************************************************/
126
127 static void
128 sigalrm_handler_crash(int sig)
129 {
130 sig = sig;    /* Keep picky compilers happy */
131 printf("\nClient timed out\n");
132 exit(99);
133 }
134
135
136 /*************************************************
137 *            SIGALRM handler - set flag          *
138 *************************************************/
139
140 static void
141 sigalrm_handler_flag(int sig)
142 {
143 sig = sig;    /* Keep picky compilers happy */
144 sigalrm_seen = 1;
145 }
146
147
148
149 /****************************************************************************/
150 /****************************************************************************/
151
152 #ifdef HAVE_OPENSSL
153 /*************************************************
154 *         Start an OpenSSL TLS session           *
155 *************************************************/
156
157 int tls_start(int sock, SSL **ssl, SSL_CTX *ctx)
158 {
159 int rc;
160 static const char *sid_ctx = "exim";
161
162 RAND_load_file("client.c", -1);   /* Not *very* random! */
163
164 *ssl = SSL_new (ctx);
165 SSL_set_session_id_context(*ssl, sid_ctx, strlen(sid_ctx));
166 SSL_set_fd (*ssl, sock);
167 SSL_set_connect_state(*ssl);
168
169 signal(SIGALRM, sigalrm_handler_flag);
170 sigalrm_seen = 0;
171 alarm(5);
172 rc = SSL_connect (*ssl);
173 alarm(0);
174
175 if (sigalrm_seen)
176   {
177   printf("SSL_connect timed out\n");
178   return 0;
179   }
180
181 if (rc <= 0)
182   {
183   ERR_print_errors_fp(stdout);
184   return 0;
185   }
186
187 printf("SSL connection using %s\n", SSL_get_cipher (*ssl));
188 return 1;
189 }
190
191
192 /*************************************************
193 *           SSL Information callback             *
194 *************************************************/
195
196 static void
197 info_callback(SSL *s, int where, int ret)
198 {
199 where = where;
200 ret = ret;
201 printf("SSL info: %s\n", SSL_state_string_long(s));
202 }
203 #endif
204
205
206 /****************************************************************************/
207 /****************************************************************************/
208
209
210 #ifdef HAVE_GNUTLS
211 /*************************************************
212 *            Handle GnuTLS error                 *
213 *************************************************/
214
215 /* Called from lots of places when errors occur before actually starting to do
216 the TLS handshake, that is, while the session is still in clear.
217
218 Argument:
219   prefix    prefix text
220   err       a GnuTLS error number, or 0 if local error
221
222 Returns:    doesn't - it dies
223 */
224
225 static void
226 gnutls_error(uschar *prefix, int err)
227 {
228 fprintf(stderr, "GnuTLS connection error:%s", prefix);
229 if (err != 0) fprintf(stderr, " %s", gnutls_strerror(err));
230 fprintf(stderr, "\n");
231 exit(1);
232 }
233
234
235
236 /*************************************************
237 *          Setup up RSA and DH parameters        *
238 *************************************************/
239
240 /* For the test suite, the parameters should always be available in the spool
241 directory. */
242
243 static void
244 init_rsa_dh(void)
245 {
246 int fd;
247 int ret;
248 gnutls_datum m;
249 uschar filename[200];
250 struct stat statbuf;
251
252 /* Initialize the data structures for holding the parameters */
253
254 ret = gnutls_rsa_params_init(&rsa_params);
255 if (ret < 0) gnutls_error(US"init rsa_params", ret);
256
257 ret = gnutls_dh_params_init(&dh_params);
258 if (ret < 0) gnutls_error(US"init dh_params", ret);
259
260 /* Open the cache file for reading and if successful, read it and set up the
261 parameters. If we can't set up the RSA parameters, assume that we are dealing
262 with an old-style cache file that is in another format, and fall through to
263 compute new values. However, if we correctly get RSA parameters, a failure to
264 set up D-H parameters is treated as an error. */
265
266 fd = open("aux-fixed/gnutls-params", O_RDONLY, 0);
267 if (fd < 0)
268   {
269   fprintf(stderr, "Failed to open spool/gnutls-params: %s\n", strerror(errno));
270   exit(1);
271   }
272
273 if (fstat(fd, &statbuf) < 0)
274   {
275   (void)close(fd);
276   return gnutls_error(US"TLS cache stat failed", 0);
277   }
278
279 m.size = statbuf.st_size;
280 m.data = malloc(m.size);
281 if (m.data == NULL)
282   return gnutls_error(US"memory allocation failed", 0);
283 if (read(fd, m.data, m.size) != m.size)
284   return gnutls_error(US"TLS cache read failed", 0);
285 (void)close(fd);
286
287 ret = gnutls_rsa_params_import_pkcs1(rsa_params, &m, GNUTLS_X509_FMT_PEM);
288 if (ret < 0) return gnutls_error(US"RSA params import", ret);
289 ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM);
290 if (ret < 0) return gnutls_error(US"DH params import", ret);
291 free(m.data);
292 }
293
294
295
296
297 /*************************************************
298 *            Initialize for GnuTLS               *
299 *************************************************/
300
301 /*
302 Arguments:
303   certificate     certificate file
304   privatekey      private key file
305 */
306
307 static void
308 tls_init(uschar *certificate, uschar *privatekey)
309 {
310 int rc;
311
312 rc = gnutls_global_init();
313 if (rc < 0) gnutls_error(US"gnutls_global_init", rc);
314
315 /* Read RSA and D-H parameters from the cache file. */
316
317 init_rsa_dh();
318
319 /* Create the credentials structure */
320
321 rc = gnutls_certificate_allocate_credentials(&x509_cred);
322 if (rc < 0) gnutls_error(US"certificate_allocate_credentials", rc);
323
324 /* Set the certificate and private keys */
325
326 if (certificate != NULL)
327   {
328   rc = gnutls_certificate_set_x509_key_file(x509_cred, CS certificate,
329     CS privatekey, GNUTLS_X509_FMT_PEM);
330   if (rc < 0) gnutls_error("gnutls_certificate", rc);
331   }
332
333 /* Associate the parameters with the x509 credentials structure. */
334
335 gnutls_certificate_set_dh_params(x509_cred, dh_params);
336 gnutls_certificate_set_rsa_export_params(x509_cred, rsa_params);
337 }
338
339
340
341 /*************************************************
342 *        Initialize a single GNUTLS session      *
343 *************************************************/
344
345 static gnutls_session
346 tls_session_init(void)
347 {
348 gnutls_session session;
349
350 gnutls_init(&session, GNUTLS_CLIENT);
351
352 gnutls_cipher_set_priority(session, default_cipher_priority);
353 gnutls_compression_set_priority(session, comp_priority);
354 gnutls_kx_set_priority(session, kx_priority);
355 gnutls_protocol_set_priority(session, protocol_priority);
356 gnutls_mac_set_priority(session, mac_priority);
357
358 gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
359
360 gnutls_dh_set_prime_bits(session, DH_BITS);
361 gnutls_db_set_cache_expiration(session, ssl_session_timeout);
362
363 return session;
364 }
365 #endif
366
367
368 /****************************************************************************/
369 /****************************************************************************/
370
371
372
373
374 /*************************************************
375 *                 Main Program                   *
376 *************************************************/
377
378 /* Usage: client
379           <IP address>
380           <port>
381           [<outgoing interface>]
382           [<cert file>]
383           [<key file>]
384 */
385
386 int main(int argc, char **argv)
387 {
388 struct sockaddr *s_ptr;
389 struct sockaddr_in s_in4;
390 char *interface = NULL;
391 char *address = NULL;
392 char *certfile = NULL;
393 char *keyfile = NULL;
394 int argi = 1;
395 int host_af, port, s_len, rc, sock, save_errno;
396 int timeout = 1;
397 int tls_active = 0;
398 int sent_starttls = 0;
399 int tls_on_connect = 0;
400
401 #if HAVE_IPV6
402 struct sockaddr_in6 s_in6;
403 #endif
404
405 #ifdef HAVE_OPENSSL
406 SSL_CTX* ctx;
407 SSL*     ssl;
408 #endif
409
410 unsigned char outbuffer[10240];
411 unsigned char inbuffer[10240];
412 unsigned char *inptr = inbuffer;
413
414 *inptr = 0;   /* Buffer empty */
415
416 /* Options */
417
418 while (argc >= argi + 1 && argv[argi][0] == '-')
419   {
420   if (strcmp(argv[argi], "-tls-on-connect") == 0)
421     {
422     tls_on_connect = 1;
423     argi++;
424     }
425   else if (argv[argi][1] == 't' && isdigit(argv[argi][2]))
426     {
427     timeout = atoi(argv[argi]+1);
428     argi++;
429     }
430   else
431     {
432     printf("Unrecognized option %s\n", argv[argi]);
433     exit(1);
434     }
435   }
436
437 /* Mandatory 1st arg is IP address */
438
439 if (argc < argi+1)
440   {
441   printf("No IP address given\n");
442   exit(1);
443   }
444
445 address = argv[argi++];
446 host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET;
447
448 /* Mandatory 2nd arg is port */
449
450 if (argc < argi+1)
451   {
452   printf("No port number given\n");
453   exit(1);
454   }
455
456 port = atoi(argv[argi++]);
457
458 /* Optional next arg is interface */
459
460 if (argc > argi &&
461   (isdigit((unsigned char)argv[argi][0]) || argv[argi][0] == ':'))
462     interface = argv[argi++];
463
464 /* Any more arguments are the name of a certificate file and key file */
465
466 if (argc > argi) certfile = argv[argi++];
467 if (argc > argi) keyfile = argv[argi++];
468
469
470 #if HAVE_IPV6
471 /* For an IPv6 address, use an IPv6 sockaddr structure. */
472
473 if (host_af == AF_INET6)
474   {
475   s_ptr = (struct sockaddr *)&s_in6;
476   s_len = sizeof(s_in6);
477   }
478 else
479 #endif
480
481 /* For an IPv4 address, use an IPv4 sockaddr structure,
482 even on an IPv6 system. */
483
484   {
485   s_ptr = (struct sockaddr *)&s_in4;
486   s_len = sizeof(s_in4);
487   }
488
489 printf("Connecting to %s port %d ... ", address, port);
490
491 sock = socket(host_af, SOCK_STREAM, 0);
492 if (sock < 0)
493   {
494   printf("socket creation failed: %s\n", strerror(errno));
495   exit(1);
496   }
497
498 /* Bind to a specific interface if requested. On an IPv6 system, this has
499 to be of the same family as the address we are calling. On an IPv4 system the
500 test is redundant, but it keeps the code tidier. */
501
502 if (interface != NULL)
503   {
504   int interface_af = (strchr(interface, ':') != NULL)? AF_INET6 : AF_INET;
505
506   if (interface_af == host_af)
507     {
508     #if HAVE_IPV6
509
510     /* Set up for IPv6 binding */
511
512     if (host_af == AF_INET6)
513       {
514       memset(&s_in6, 0, sizeof(s_in6));
515       s_in6.sin6_family = AF_INET6;
516       s_in6.sin6_port = 0;
517       if (inet_pton(AF_INET6, interface, &s_in6.sin6_addr) != 1)
518         {
519         printf("Unable to parse \"%s\"", interface);
520         exit(1);
521         }
522       }
523     else
524     #endif
525
526     /* Set up for IPv4 binding */
527
528       {
529       memset(&s_in4, 0, sizeof(s_in4));
530       s_in4.sin_family = AF_INET;
531       s_in4.sin_port = 0;
532       s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(interface);
533       }
534
535     /* Bind */
536
537     if (bind(sock, s_ptr, s_len) < 0)
538       {
539       printf("Unable to bind outgoing SMTP call to %s: %s",
540         interface, strerror(errno));
541       exit(1);
542       }
543     }
544   }
545
546 /* Set up a remote IPv6 address */
547
548 #if HAVE_IPV6
549 if (host_af == AF_INET6)
550   {
551   memset(&s_in6, 0, sizeof(s_in6));
552   s_in6.sin6_family = AF_INET6;
553   s_in6.sin6_port = htons(port);
554   if (inet_pton(host_af, address, &s_in6.sin6_addr) != 1)
555     {
556     printf("Unable to parse \"%s\"", address);
557     exit(1);
558     }
559   }
560 else
561 #endif
562
563 /* Set up a remote IPv4 address */
564
565   {
566   memset(&s_in4, 0, sizeof(s_in4));
567   s_in4.sin_family = AF_INET;
568   s_in4.sin_port = htons(port);
569   s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(address);
570   }
571
572 /* SIGALRM handler crashes out */
573
574 signal(SIGALRM, sigalrm_handler_crash);
575 alarm(timeout);
576 rc = connect(sock, s_ptr, s_len);
577 save_errno = errno;
578 alarm(0);
579
580 /* A failure whose error code is "Interrupted system call" is in fact
581 an externally applied timeout if the signal handler has been run. */
582
583 if (rc < 0)
584   {
585   close(sock);
586   printf("failed: %s\n", strerror(save_errno));
587   exit(1);
588   }
589
590 printf("connected\n");
591
592
593 /* --------------- Set up for OpenSSL --------------- */
594
595 #ifdef HAVE_OPENSSL
596 SSL_library_init();
597 SSL_load_error_strings();
598
599 ctx = SSL_CTX_new(SSLv23_method());
600 if (ctx == NULL)
601   {
602   printf ("SSL_CTX_new failed\n");
603   exit(1);
604   }
605
606 if (certfile != NULL)
607   {
608   if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
609     {
610     printf("SSL_CTX_use_certificate_file failed\n");
611     exit(1);
612     }
613   printf("Certificate file = %s\n", certfile);
614   }
615
616 if (keyfile != NULL)
617   {
618   if (!SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))
619     {
620     printf("SSL_CTX_use_PrivateKey_file failed\n");
621     exit(1);
622     }
623   printf("Key file = %s\n", keyfile);
624   }
625
626 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
627 SSL_CTX_set_timeout(ctx, 200);
628 SSL_CTX_set_info_callback(ctx, (void (*)())info_callback);
629 #endif
630
631
632 /* --------------- Set up for GnuTLS --------------- */
633
634 #ifdef HAVE_GNUTLS
635 if (certfile != NULL) printf("Certificate file = %s\n", certfile);
636 if (keyfile != NULL) printf("Key file = %s\n", keyfile);
637 tls_init(certfile, keyfile);
638 tls_session = tls_session_init();
639 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)sock);
640
641 /* When the server asks for a certificate and the client does not have one,
642 there is a SIGPIPE error in the gnutls_handshake() function for some reason
643 that is not understood. As luck would have it, this has never hit Exim itself
644 because it ignores SIGPIPE errors. Doing the same here allows it all to work as
645 one wants. */
646
647 signal(SIGPIPE, SIG_IGN);
648 #endif
649
650 /* ---------------------------------------------- */
651
652
653 /* Start TLS session if configured to do so without STARTTLS */
654
655 #ifdef HAVE_TLS
656 if (tls_on_connect)
657   {
658   printf("Attempting to start TLS\n");
659
660   #ifdef HAVE_OPENSSL
661   tls_active = tls_start(sock, &ssl, ctx);
662   #endif
663
664   #ifdef HAVE_GNUTLS
665   sigalrm_seen = FALSE;
666   alarm(timeout);
667   tls_active = gnutls_handshake(tls_session) >= 0;
668   alarm(0);
669   #endif
670
671   if (!tls_active)
672     printf("Failed to start TLS\n");
673   else
674     printf("Succeeded in starting TLS\n");
675   }
676 #endif
677
678 while (fgets(outbuffer, sizeof(outbuffer), stdin) != NULL)
679   {
680   int n = (int)strlen(outbuffer);
681   while (n > 0 && isspace(outbuffer[n-1])) n--;
682   outbuffer[n] = 0;
683
684   /* Expect incoming */
685
686   if (strncmp(outbuffer, "??? ", 4) == 0)
687     {
688     unsigned char *lineptr;
689     printf("%s\n", outbuffer);
690
691     if (*inptr == 0)   /* Refill input buffer */
692       {
693       if (tls_active)
694         {
695         #ifdef HAVE_OPENSSL
696         rc = SSL_read (ssl, inbuffer, sizeof(inbuffer) - 1);
697         #endif
698         #ifdef HAVE_GNUTLS
699         rc = gnutls_record_recv(tls_session, CS inbuffer, sizeof(inbuffer) - 1);
700         #endif
701         }
702       else
703         {
704         alarm(timeout);
705         rc = read(sock, inbuffer, sizeof(inbuffer));
706         alarm(0);
707         }
708
709       if (rc < 0)
710         {
711         printf("Read error %s\n", strerror(errno));
712         exit(1)  ;
713         }
714       else if (rc == 0)
715         {
716         printf("Unexpected EOF read\n");
717         close(sock);
718         exit(1);
719         }
720       else
721         {
722         inbuffer[rc] = 0;
723         inptr = inbuffer;
724         }
725       }
726
727     lineptr = inptr;
728     while (*inptr != 0 && *inptr != '\r' && *inptr != '\n') inptr++;
729     if (*inptr != 0)
730       {
731       *inptr++ = 0;
732       if (*inptr == '\n') inptr++;
733       }
734
735     printf("<<< %s\n", lineptr);
736     if (strncmp(lineptr, outbuffer + 4, (int)strlen(outbuffer) - 4) != 0)
737       {
738       printf("\n******** Input mismatch ********\n");
739       exit(1);
740       }
741
742     #ifdef HAVE_TLS
743     if (sent_starttls)
744       {
745       if (lineptr[0] == '2')
746         {
747         printf("Attempting to start TLS\n");
748         fflush(stdout);
749
750         #ifdef HAVE_OPENSSL
751         tls_active = tls_start(sock, &ssl, ctx);
752         #endif
753
754         #ifdef HAVE_GNUTLS
755         sigalrm_seen = FALSE;
756         alarm(timeout);
757         tls_active = gnutls_handshake(tls_session) >= 0;
758         alarm(0);
759         #endif
760
761         if (!tls_active)
762           {
763           printf("Failed to start TLS\n");
764           fflush(stdout);
765           }
766         else
767           printf("Succeeded in starting TLS\n");
768         }
769       else printf("Abandoning TLS start attempt\n");
770       }
771     sent_starttls = 0;
772     #endif
773     }
774
775   /* Wait for a bit before proceeding */
776
777   else if (strncmp(outbuffer, "+++ ", 4) == 0)
778     {
779     printf("%s\n", outbuffer);
780     sleep(atoi(outbuffer + 4));
781     }
782
783   /* Send outgoing, but barf if unconsumed incoming */
784
785   else
786     {
787     unsigned char *escape;
788
789     if (*inptr != 0)
790       {
791       printf("Unconsumed input: %s", inptr);
792       printf("   About to send: %s\n", outbuffer);
793       exit(1);
794       }
795
796     #ifdef HAVE_TLS
797
798     /* Shutdown TLS */
799
800     if (strcmp(outbuffer, "stoptls") == 0 ||
801         strcmp(outbuffer, "STOPTLS") == 0)
802       {
803       if (!tls_active)
804         {
805         printf("STOPTLS read when TLS not active\n");
806         exit(1);
807         }
808       printf("Shutting down TLS encryption\n");
809
810       #ifdef HAVE_OPENSSL
811       SSL_shutdown(ssl);
812       SSL_free(ssl);
813       #endif
814
815       #ifdef HAVE_GNUTLS
816       gnutls_bye(tls_session, GNUTLS_SHUT_WR);
817       gnutls_deinit(tls_session);
818       tls_session = NULL;
819       gnutls_global_deinit();
820       #endif
821
822       tls_active = 0;
823       continue;
824       }
825
826     /* Remember that we sent STARTTLS */
827
828     sent_starttls = (strcmp(outbuffer, "starttls") == 0 ||
829                      strcmp(outbuffer, "STARTTLS") == 0);
830
831     /* Fudge: if the command is "starttls_wait", we send the starttls bit,
832     but we haven't set the flag, so that there is no negotiation. This is for
833     testing the server's timeout. */
834
835     if (strcmp(outbuffer, "starttls_wait") == 0)
836       {
837       outbuffer[8] = 0;
838       n = 8;
839       }
840     #endif
841
842     printf(">>> %s\n", outbuffer);
843     strcpy(outbuffer + n, "\r\n");
844
845     /* Turn "\n" and "\r" into the relevant characters. This is a hack. */
846
847     while ((escape = strstr(outbuffer, "\\r")) != NULL)
848       {
849       *escape = '\r';
850       memmove(escape + 1, escape + 2,  (n + 2) - (escape - outbuffer) - 2);
851       n--;
852       }
853
854     while ((escape = strstr(outbuffer, "\\n")) != NULL)
855       {
856       *escape = '\n';
857       memmove(escape + 1, escape + 2,  (n + 2) - (escape - outbuffer) - 2);
858       n--;
859       }
860
861     /* OK, do it */
862
863     alarm(timeout);
864     if (tls_active)
865       {
866       #ifdef HAVE_OPENSSL
867         rc = SSL_write (ssl, outbuffer, n + 2);
868       #endif
869       #ifdef HAVE_GNUTLS
870         rc = gnutls_record_send(tls_session, CS outbuffer, n + 2);
871         if (rc < 0)
872           {
873           printf("GnuTLS write error: %s\n", gnutls_strerror(rc));
874           exit(1);
875           }
876       #endif
877       }
878     else
879       {
880       rc = write(sock, outbuffer, n + 2);
881       }
882     alarm(0);
883
884     if (rc < 0)
885       {
886       printf("Write error: %s\n", strerror(errno));
887       exit(1);
888       }
889     }
890   }
891
892 printf("End of script\n");
893 close(sock);
894
895 exit(0);
896 }
897
898 /* End of client.c */