gnutls-cli: added --starttls-proto option
[gnutls:gnutls.git] / src / cli.c
1 /*
2  * Copyright (C) 2000-2014 Free Software Foundation, Inc.
3  * Copyright (C) 2013-2014 Nikos Mavrogiannopoulos
4  *
5  * This file is part of GnuTLS.
6  *
7  * GnuTLS is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuTLS is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <string.h>
28 #include <sys/time.h>
29 #include <sys/stat.h>
30 #if HAVE_SYS_SOCKET_H
31 #include <sys/socket.h>
32 #elif HAVE_WS2TCPIP_H
33 #include <ws2tcpip.h>
34 #endif
35 #include <sys/select.h>
36 #include <unistd.h>
37 #include <stdint.h>
38 #include <stdbool.h>
39 #include <fcntl.h>
40 #include <netdb.h>
41 #include <ctype.h>
42
43 #include <gnutls/gnutls.h>
44 #include <gnutls/abstract.h>
45 #include <gnutls/dtls.h>
46 #include <gnutls/x509.h>
47 #include <gnutls/openpgp.h>
48 #include <gnutls/pkcs11.h>
49 #include <gnutls/crypto.h>
50
51 /* Gnulib portability files. */
52 #include <read-file.h>
53 #include <getpass.h>
54 #include <minmax.h>
55
56 #include "sockets.h"
57 #include "benchmark.h"
58 #include "inline_cmds.h"
59
60 #ifdef HAVE_DANE
61 #include <gnutls/dane.h>
62 #endif
63
64 #include <common.h>
65 #include <socket.h>
66
67 #include <cli-args.h>
68 #include <ocsptool-common.h>
69
70 #define MAX_BUF 4096
71
72 /* global stuff here */
73 int resume, starttls, insecure, ranges, rehandshake, udp, mtu,
74     inline_commands;
75 const char *hostname = NULL;
76 const char *service = NULL;
77 int record_max_size;
78 int fingerprint;
79 int crlf;
80 unsigned int verbose = 0;
81 int print_cert;
82
83 const char *srp_passwd = NULL;
84 const char *srp_username = NULL;
85 const char *pgp_keyfile = NULL;
86 const char *pgp_certfile = NULL;
87 const char *pgp_keyring = NULL;
88 const char *x509_keyfile = NULL;
89 const char *x509_certfile = NULL;
90 const char *x509_cafile = NULL;
91 const char *x509_crlfile = NULL;
92 static int x509ctype;
93 static int disable_extensions;
94 static int disable_sni;
95 static unsigned int init_flags = GNUTLS_CLIENT;
96 static const char *priorities = NULL;
97 static const char *inline_commands_prefix;
98
99 const char *psk_username = NULL;
100 gnutls_datum_t psk_key = { NULL, 0 };
101
102 static gnutls_srp_client_credentials_t srp_cred;
103 static gnutls_psk_client_credentials_t psk_cred;
104 static gnutls_anon_client_credentials_t anon_cred;
105 static gnutls_certificate_credentials_t xcred;
106
107 /* end of global stuff */
108
109 /* prototypes */
110
111 static void check_rehandshake(socket_st * socket, int ret);
112 static int do_handshake(socket_st * socket);
113 static void init_global_tls_stuff(void);
114 static int cert_verify_ocsp(gnutls_session_t session);
115
116 #define MAX_CRT 6
117 static unsigned int x509_crt_size;
118 static gnutls_pcert_st x509_crt[MAX_CRT];
119 static gnutls_privkey_t x509_key = NULL;
120
121 static gnutls_pcert_st pgp_crt;
122 static gnutls_privkey_t pgp_key = NULL;
123
124 static void get_keyid(gnutls_openpgp_keyid_t keyid, const char *str)
125 {
126         size_t keyid_size = GNUTLS_OPENPGP_KEYID_SIZE;
127
128         if (strlen(str) != 16) {
129                 fprintf(stderr,
130                         "The OpenPGP subkey ID has to be 16 hexadecimal characters.\n");
131                 exit(1);
132         }
133
134         if (gnutls_hex2bin(str, strlen(str), keyid, &keyid_size) < 0) {
135                 fprintf(stderr, "Error converting hex string: %s.\n", str);
136                 exit(1);
137         }
138
139         return;
140 }
141
142 /* Load the certificate and the private key.
143  */
144 static void load_keys(void)
145 {
146         unsigned int crt_num;
147         int ret;
148         unsigned int i;
149         gnutls_datum_t data = { NULL, 0 };
150         gnutls_x509_crt_t crt_list[MAX_CRT];
151         unsigned char keyid[GNUTLS_OPENPGP_KEYID_SIZE];
152
153         if (x509_certfile != NULL && x509_keyfile != NULL) {
154 #ifdef ENABLE_PKCS11
155                 if (strncmp(x509_certfile, "pkcs11:", 7) == 0) {
156                         crt_num = 1;
157                         gnutls_x509_crt_init(&crt_list[0]);
158                         gnutls_x509_crt_set_pin_function(crt_list[0],
159                                                          pin_callback,
160                                                          NULL);
161
162                         ret =
163                             gnutls_x509_crt_import_pkcs11_url(crt_list[0],
164                                                               x509_certfile,
165                                                               0);
166
167                         if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
168                                 ret =
169                                     gnutls_x509_crt_import_pkcs11_url
170                                     (crt_list[0], x509_certfile,
171                                      GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
172
173                         if (ret < 0) {
174                                 fprintf(stderr,
175                                         "*** Error loading cert file.\n");
176                                 exit(1);
177                         }
178                         x509_crt_size = 1;
179                 } else
180 #endif                          /* ENABLE_PKCS11 */
181                 {
182
183                         ret = gnutls_load_file(x509_certfile, &data);
184                         if (ret < 0) {
185                                 fprintf(stderr,
186                                         "*** Error loading cert file.\n");
187                                 exit(1);
188                         }
189
190                         crt_num = MAX_CRT;
191                         ret =
192                             gnutls_x509_crt_list_import(crt_list, &crt_num,
193                                                         &data, x509ctype,
194                                                         GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
195                         if (ret < 0) {
196                                 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
197                                         fprintf(stderr,
198                                                 "*** Error loading cert file: Too many certs %d\n",
199                                                 crt_num);
200
201                                 } else {
202                                         fprintf(stderr,
203                                                 "*** Error loading cert file: %s\n",
204                                                 gnutls_strerror(ret));
205                                 }
206                                 exit(1);
207                         }
208                         x509_crt_size = ret;
209                 }
210
211                 for (i = 0; i < x509_crt_size; i++) {
212                         ret =
213                             gnutls_pcert_import_x509(&x509_crt[i],
214                                                      crt_list[i], 0);
215                         if (ret < 0) {
216                                 fprintf(stderr,
217                                         "*** Error importing crt to pcert: %s\n",
218                                         gnutls_strerror(ret));
219                                 exit(1);
220                         }
221                         gnutls_x509_crt_deinit(crt_list[i]);
222                 }
223
224                 gnutls_free(data.data);
225
226                 ret = gnutls_privkey_init(&x509_key);
227                 if (ret < 0) {
228                         fprintf(stderr, "*** Error initializing key: %s\n",
229                                 gnutls_strerror(ret));
230                         exit(1);
231                 }
232
233                 gnutls_privkey_set_pin_function(x509_key, pin_callback,
234                                                 NULL);
235
236                 if (gnutls_url_is_supported(x509_keyfile) != 0) {
237                         ret =
238                             gnutls_privkey_import_url(x509_key,
239                                                       x509_keyfile, 0);
240                         if (ret < 0) {
241                                 fprintf(stderr,
242                                         "*** Error loading url: %s\n",
243                                         gnutls_strerror(ret));
244                                 exit(1);
245                         }
246                 } else {
247                         ret = gnutls_load_file(x509_keyfile, &data);
248                         if (ret < 0) {
249                                 fprintf(stderr,
250                                         "*** Error loading key file.\n");
251                                 exit(1);
252                         }
253
254                         ret =
255                             gnutls_privkey_import_x509_raw(x509_key, &data,
256                                                            x509ctype, NULL,
257                                                            0);
258                         if (ret < 0) {
259                                 fprintf(stderr,
260                                         "*** Error loading url: %s\n",
261                                         gnutls_strerror(ret));
262                                 exit(1);
263                         }
264
265                         gnutls_free(data.data);
266                 }
267
268                 fprintf(stdout,
269                         "Processed %d client X.509 certificates...\n",
270                         x509_crt_size);
271         }
272
273 #ifdef ENABLE_OPENPGP
274         if (HAVE_OPT(PGPSUBKEY)) {
275                 get_keyid(keyid, OPT_ARG(PGPSUBKEY));
276         }
277
278         if (pgp_certfile != NULL && pgp_keyfile != NULL) {
279                 gnutls_openpgp_crt_t tmp_pgp_crt;
280
281                 ret = gnutls_load_file(pgp_certfile, &data);
282                 if (ret < 0) {
283                         fprintf(stderr,
284                                 "*** Error loading PGP cert file.\n");
285                         exit(1);
286                 }
287
288                 gnutls_openpgp_crt_init(&tmp_pgp_crt);
289
290                 ret =
291                     gnutls_pcert_import_openpgp_raw(&pgp_crt, &data,
292                                                     GNUTLS_OPENPGP_FMT_BASE64,
293                                                     HAVE_OPT(PGPSUBKEY) ?
294                                                     keyid : NULL, 0);
295                 if (ret < 0) {
296                         fprintf(stderr,
297                                 "*** Error loading PGP cert file: %s\n",
298                                 gnutls_strerror(ret));
299                         exit(1);
300                 }
301
302                 gnutls_free(data.data);
303
304                 ret = gnutls_privkey_init(&pgp_key);
305                 if (ret < 0) {
306                         fprintf(stderr, "*** Error initializing key: %s\n",
307                                 gnutls_strerror(ret));
308                         exit(1);
309                 }
310
311                 gnutls_privkey_set_pin_function(pgp_key, pin_callback,
312                                                 NULL);
313
314                 if (gnutls_url_is_supported(pgp_keyfile)) {
315                         ret =
316                             gnutls_privkey_import_url(pgp_key, pgp_keyfile,
317                                                       0);
318                         if (ret < 0) {
319                                 fprintf(stderr,
320                                         "*** Error loading url: %s\n",
321                                         gnutls_strerror(ret));
322                                 exit(1);
323                         }
324                 } else {
325                         ret = gnutls_load_file(pgp_keyfile, &data);
326                         if (ret < 0) {
327                                 fprintf(stderr,
328                                         "*** Error loading key file.\n");
329                                 exit(1);
330                         }
331
332                         if (HAVE_OPT(PGPSUBKEY))
333                                 ret =
334                                     gnutls_privkey_import_openpgp_raw
335                                     (pgp_key, &data, x509ctype, keyid,
336                                      NULL);
337                         else
338                                 ret =
339                                     gnutls_privkey_import_openpgp_raw
340                                     (pgp_key, &data, x509ctype, NULL,
341                                      NULL);
342                         if (ret < 0) {
343                                 fprintf(stderr,
344                                         "*** Error loading url: %s\n",
345                                         gnutls_strerror(ret));
346                                 exit(1);
347                         }
348
349                         gnutls_free(data.data);
350                 }
351
352
353                 fprintf(stdout, "Processed 1 client PGP certificate...\n");
354         }
355 #endif
356
357 }
358
359 #define IS_NEWLINE(x) ((x[0] == '\n') || (x[0] == '\r'))
360 static int read_yesno(const char *input_str)
361 {
362         char input[128];
363
364         fputs(input_str, stderr);
365         if (fgets(input, sizeof(input), stdin) == NULL)
366                 return 0;
367
368         if (IS_NEWLINE(input))
369                 return 0;
370
371         if (input[0] == 'y' || input[0] == 'Y')
372                 return 1;
373
374         return 0;
375 }
376
377 static int cert_verify_callback(gnutls_session_t session)
378 {
379         int rc;
380         unsigned int status = 0;
381         int ssh = ENABLED_OPT(TOFU);
382         int strictssh = ENABLED_OPT(STRICT_TOFU);
383 #ifdef HAVE_DANE
384         int dane = ENABLED_OPT(DANE);
385 #endif
386         int ca_verify = ENABLED_OPT(CA_VERIFICATION);
387         const char *txt_service;
388
389         /* On an session with TOFU the PKI/DANE verification
390          * become advisory.
391          */
392
393         if (strictssh) {
394                 ssh = strictssh;
395         }
396
397         print_cert_info(session, verbose, print_cert);
398
399         if (ca_verify) {
400                 rc = cert_verify(session, hostname, GNUTLS_KP_TLS_WWW_SERVER);
401                 if (rc == 0) {
402                         printf
403                             ("*** PKI verification of server certificate failed...\n");
404                         if (!insecure && !ssh)
405                                 return -1;
406                 } else if (ENABLED_OPT(OCSP) && gnutls_ocsp_status_request_is_checked(session, 0) == 0) {       /* off-line verification succeeded. Try OCSP */
407                         rc = cert_verify_ocsp(session);
408                         if (rc == 0) {
409                                 printf
410                                     ("*** Verifying (with OCSP) server certificate failed...\n");
411                                 if (!insecure && !ssh)
412                                         return -1;
413                         } else if (rc == -1)
414                                 printf("*** OCSP response ignored...\n");
415                 }
416         }
417
418 #ifdef HAVE_DANE
419         if (dane) {             /* try DANE auth */
420                 int port;
421                 unsigned vflags = 0;
422                 unsigned int sflags =
423                     ENABLED_OPT(LOCAL_DNS) ? 0 :
424                     DANE_F_IGNORE_LOCAL_RESOLVER;
425
426                 /* if we didn't verify the chain it only makes sense
427                  * to check the end certificate using dane. */
428                 if (ca_verify == 0)
429                         vflags |= DANE_VFLAG_ONLY_CHECK_EE_USAGE;
430
431                 port = service_to_port(service, udp?"udp":"tcp");
432                 rc = dane_verify_session_crt(NULL, session, hostname,
433                                              udp ? "udp" : "tcp", port,
434                                              sflags, vflags, &status);
435                 if (rc < 0) {
436                         fprintf(stderr,
437                                 "*** DANE verification error: %s\n",
438                                 dane_strerror(rc));
439                         if (!insecure && !ssh)
440                                 return -1;
441                 } else {
442                         gnutls_datum_t out;
443
444                         rc = dane_verification_status_print(status, &out,
445                                                             0);
446                         if (rc < 0) {
447                                 fprintf(stderr, "*** DANE error: %s\n",
448                                         dane_strerror(rc));
449                         } else {
450                                 fprintf(stderr, "- DANE: %s\n", out.data);
451                                 gnutls_free(out.data);
452                         }
453
454                         if (status != 0 && !insecure && !ssh)
455                                 return -1;
456                 }
457
458         }
459 #endif
460
461         if (ssh) {              /* try ssh auth */
462                 unsigned int list_size;
463                 const gnutls_datum_t *cert;
464
465                 cert = gnutls_certificate_get_peers(session, &list_size);
466                 if (cert == NULL) {
467                         fprintf(stderr,
468                                 "Cannot obtain peer's certificate!\n");
469                         return -1;
470                 }
471
472                 txt_service = port_to_service(service, udp?"udp":"tcp");
473
474                 rc = gnutls_verify_stored_pubkey(NULL, NULL, hostname,
475                                                  txt_service,
476                                                  GNUTLS_CRT_X509, cert, 0);
477                 if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) {
478                         fprintf(stderr,
479                                 "Host %s (%s) has never been contacted before.\n",
480                                 hostname, txt_service);
481                         if (status == 0)
482                                 fprintf(stderr,
483                                         "Its certificate is valid for %s.\n",
484                                         hostname);
485
486                         rc = read_yesno
487                             ("Are you sure you want to trust it? (y/N): ");
488                         if (rc == 0)
489                                 return -1;
490                 } else if (rc == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
491                         fprintf(stderr,
492                                 "Warning: host %s is known and it is associated with a different key.\n",
493                                 hostname);
494                         fprintf(stderr,
495                                 "It might be that the server has multiple keys, or an attacker replaced the key to eavesdrop this connection .\n");
496                         if (status == 0)
497                                 fprintf(stderr,
498                                         "Its certificate is valid for %s.\n",
499                                         hostname);
500
501                         if (strictssh == 0) {
502                                 rc = read_yesno
503                                         ("Do you trust the received key? (y/N): ");
504                                 if (rc == 0)
505                                         return -1;
506                         } else return -1;
507
508                 } else if (rc < 0) {
509                         fprintf(stderr,
510                                 "gnutls_verify_stored_pubkey: %s\n",
511                                 gnutls_strerror(rc));
512                         return -1;
513                 }
514
515                 if (rc != 0) {
516                         rc = gnutls_store_pubkey(NULL, NULL, hostname,
517                                                  txt_service,
518                                                  GNUTLS_CRT_X509, cert, 0,
519                                                  0);
520                         if (rc < 0)
521                                 fprintf(stderr,
522                                         "Could not store key: %s\n",
523                                         gnutls_strerror(rc));
524                 }
525         }
526         return 0;
527 }
528
529 /* This callback should be associated with a session by calling
530  * gnutls_certificate_client_set_retrieve_function( session, cert_callback),
531  * before a handshake.
532  */
533
534 static int
535 cert_callback(gnutls_session_t session,
536               const gnutls_datum_t * req_ca_rdn, int nreqs,
537               const gnutls_pk_algorithm_t * sign_algos,
538               int sign_algos_length, gnutls_pcert_st ** pcert,
539               unsigned int *pcert_length, gnutls_privkey_t * pkey)
540 {
541         char issuer_dn[256];
542         int i, ret, cert_type;
543         size_t len;
544
545         if (verbose) {
546                 /* Print the server's trusted CAs
547                  */
548                 if (nreqs > 0)
549                         printf("- Server's trusted authorities:\n");
550                 else
551                         printf
552                             ("- Server did not send us any trusted authorities names.\n");
553
554                 /* print the names (if any) */
555                 for (i = 0; i < nreqs; i++) {
556                         len = sizeof(issuer_dn);
557                         ret =
558                             gnutls_x509_rdn_get(&req_ca_rdn[i], issuer_dn,
559                                                 &len);
560                         if (ret >= 0) {
561                                 printf("   [%d]: ", i);
562                                 printf("%s\n", issuer_dn);
563                         }
564                 }
565         }
566
567         /* Select a certificate and return it.
568          * The certificate must be of any of the "sign algorithms"
569          * supported by the server.
570          */
571
572         cert_type = gnutls_certificate_type_get(session);
573
574         *pcert_length = 0;
575
576         if (cert_type == GNUTLS_CRT_X509) {
577                 if (x509_crt_size > 0) {
578                         if (x509_key != NULL) {
579                                 *pkey = x509_key;
580                         } else {
581                                 printf
582                                     ("- Could not find a suitable key to send to server\n");
583                                 return -1;
584                         }
585
586                         *pcert_length = x509_crt_size;
587                         *pcert = x509_crt;
588                 }
589
590         } else if (cert_type == GNUTLS_CRT_OPENPGP) {
591                 if (pgp_key != NULL) {
592                         *pkey = pgp_key;
593
594                         *pcert_length = 1;
595                         *pcert = &pgp_crt;
596                 }
597         }
598
599         printf("- Successfully sent %u certificate(s) to server.\n",
600                *pcert_length);
601         return 0;
602
603 }
604
605 /* initializes a gnutls_session_t with some defaults.
606  */
607 static gnutls_session_t init_tls_session(const char *host)
608 {
609         const char *err;
610         int ret;
611         unsigned i;
612         gnutls_session_t session;
613
614         if (udp) {
615                 gnutls_init(&session, GNUTLS_DATAGRAM | init_flags);
616                 if (mtu)
617                         gnutls_dtls_set_mtu(session, mtu);
618         } else
619                 gnutls_init(&session, init_flags);
620
621         if ((ret =
622              gnutls_priority_set_direct(session, priorities, &err)) < 0) {
623                 if (ret == GNUTLS_E_INVALID_REQUEST)
624                         fprintf(stderr, "Syntax error at: %s\n", err);
625                 else
626                         fprintf(stderr, "Error in priorities: %s\n",
627                                 gnutls_strerror(ret));
628                 exit(1);
629         }
630
631         /* allow the use of private ciphersuites.
632          */
633         if (disable_extensions == 0 && disable_sni == 0) {
634                 if (host != NULL && is_ip(host) == 0)
635                         gnutls_server_name_set(session, GNUTLS_NAME_DNS,
636                                                host, strlen(host));
637         }
638
639         if (HAVE_OPT(DH_BITS))
640                 gnutls_dh_set_prime_bits(session, OPT_VALUE_DH_BITS);
641
642         if (HAVE_OPT(ALPN)) {
643                 unsigned proto_n = STACKCT_OPT(ALPN);
644                 char **protos = (void *) STACKLST_OPT(ALPN);
645                 gnutls_datum_t p[proto_n];
646
647                 for (i = 0; i < proto_n; i++) {
648                         p[i].data = (void *) protos[i];
649                         p[i].size = strlen(protos[i]);
650                 }
651                 gnutls_alpn_set_protocols(session, p, proto_n, 0);
652         }
653
654         gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred);
655         if (srp_cred)
656                 gnutls_credentials_set(session, GNUTLS_CRD_SRP, srp_cred);
657         if (psk_cred)
658                 gnutls_credentials_set(session, GNUTLS_CRD_PSK, psk_cred);
659         gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
660
661         gnutls_certificate_set_retrieve_function2(xcred, cert_callback);
662         gnutls_certificate_set_verify_function(xcred,
663                                                cert_verify_callback);
664
665         /* send the fingerprint */
666 #ifdef ENABLE_OPENPGP
667         if (fingerprint != 0)
668                 gnutls_openpgp_send_cert(session,
669                                          GNUTLS_OPENPGP_CERT_FINGERPRINT);
670 #endif
671
672         /* use the max record size extension */
673         if (record_max_size > 0 && disable_extensions == 0) {
674                 if (gnutls_record_set_max_size(session, record_max_size) <
675                     0) {
676                         fprintf(stderr,
677                                 "Cannot set the maximum record size to %d.\n",
678                                 record_max_size);
679                         fprintf(stderr,
680                                 "Possible values: 512, 1024, 2048, 4096.\n");
681                         exit(1);
682                 }
683         }
684
685         if (HAVE_OPT(HEARTBEAT))
686                 gnutls_heartbeat_enable(session,
687                                         GNUTLS_HB_PEER_ALLOWED_TO_SEND);
688
689 #ifdef ENABLE_DTLS_SRTP
690         if (HAVE_OPT(SRTP_PROFILES)) {
691                 ret =
692                     gnutls_srtp_set_profile_direct(session,
693                                                    OPT_ARG(SRTP_PROFILES),
694                                                    &err);
695                 if (ret == GNUTLS_E_INVALID_REQUEST)
696                         fprintf(stderr, "Syntax error at: %s\n", err);
697                 else if (ret != 0)
698                         fprintf(stderr, "Error in profiles: %s\n",
699                                 gnutls_strerror(ret));
700                 else fprintf(stderr,"DTLS profile set to %s\n",
701                              OPT_ARG(SRTP_PROFILES));
702
703                 if (ret != 0) exit(1);
704         }
705 #endif
706
707
708         return session;
709 }
710
711 static void cmd_parser(int argc, char **argv);
712
713 /* Returns zero if the error code was successfully handled.
714  */
715 static int handle_error(socket_st * hd, int err)
716 {
717         int alert, ret;
718         const char *err_type, *str;
719
720         if (err >= 0 || err == GNUTLS_E_AGAIN
721             || err == GNUTLS_E_INTERRUPTED)
722                 return 0;
723
724         if (gnutls_error_is_fatal(err) == 0) {
725                 ret = 0;
726                 err_type = "Non fatal";
727         } else {
728                 ret = err;
729                 err_type = "Fatal";
730         }
731
732         str = gnutls_strerror(err);
733         if (str == NULL)
734                 str = str_unknown;
735         fprintf(stderr, "*** %s error: %s\n", err_type, str);
736
737         if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
738             || err == GNUTLS_E_FATAL_ALERT_RECEIVED) {
739                 alert = gnutls_alert_get(hd->session);
740                 str = gnutls_alert_get_name(alert);
741                 if (str == NULL)
742                         str = str_unknown;
743                 printf("*** Received alert [%d]: %s\n", alert, str);
744         }
745
746         check_rehandshake(hd, err);
747
748         return ret;
749 }
750
751 int starttls_alarmed = 0;
752
753 #ifndef _WIN32
754 static void starttls_alarm(int signum)
755 {
756         starttls_alarmed = 1;
757 }
758 #endif
759
760 static void tls_log_func(int level, const char *str)
761 {
762         fprintf(stderr, "|<%d>| %s", level, str);
763 }
764
765 #define IN_KEYBOARD 1
766 #define IN_NET 2
767 #define IN_NONE 0
768 /* returns IN_KEYBOARD for keyboard input and IN_NET for network input
769  */
770 static int check_net_or_keyboard_input(socket_st * hd)
771 {
772         int maxfd;
773         fd_set rset;
774         int err;
775         struct timeval tv;
776
777         do {
778                 FD_ZERO(&rset);
779                 FD_SET(hd->fd, &rset);
780
781 #ifndef _WIN32
782                 FD_SET(fileno(stdin), &rset);
783                 maxfd = MAX(fileno(stdin), hd->fd);
784 #else
785                 maxfd = hd->fd;
786 #endif
787
788                 tv.tv_sec = 0;
789                 tv.tv_usec = 50 * 1000;
790
791                 if (hd->secure == 1)
792                         if (gnutls_record_check_pending(hd->session))
793                                 return IN_NET;
794
795                 err = select(maxfd + 1, &rset, NULL, NULL, &tv);
796                 if (err < 0)
797                         continue;
798
799                 if (FD_ISSET(hd->fd, &rset))
800                         return IN_NET;
801
802 #ifdef _WIN32
803                 {
804                         int state;
805                         state =
806                             WaitForSingleObject(GetStdHandle
807                                                 (STD_INPUT_HANDLE), 200);
808
809                         if (state == WAIT_OBJECT_0)
810                                 return IN_KEYBOARD;
811                 }
812 #else
813                 if (FD_ISSET(fileno(stdin), &rset))
814                         return IN_KEYBOARD;
815 #endif
816         }
817         while (err == 0);
818
819         return IN_NONE;
820 }
821
822 static int try_rehandshake(socket_st * hd)
823 {
824         int ret;
825
826         ret = do_handshake(hd);
827         if (ret < 0) {
828                 fprintf(stderr, "*** ReHandshake has failed\n");
829                 gnutls_perror(ret);
830                 return ret;
831         } else {
832                 printf("- ReHandshake was completed\n");
833                 return 0;
834         }
835 }
836
837 static int try_resume(socket_st * hd)
838 {
839         int ret;
840
841         char *session_data;
842         size_t session_data_size = 0;
843
844         gnutls_session_get_data(hd->session, NULL, &session_data_size);
845         session_data = (char *) malloc(session_data_size);
846         if (session_data == NULL)
847                 return GNUTLS_E_MEMORY_ERROR;
848
849         gnutls_session_get_data(hd->session, session_data,
850                                 &session_data_size);
851
852         printf("- Disconnecting\n");
853         socket_bye(hd);
854
855         printf
856             ("\n\n- Connecting again- trying to resume previous session\n");
857         socket_open(hd, hostname, service, udp, CONNECT_MSG);
858
859         if (HAVE_OPT(STARTTLS_PROTO))
860                 socket_starttls(hd, OPT_ARG(STARTTLS_PROTO));
861
862         hd->session = init_tls_session(hostname);
863         gnutls_session_set_data(hd->session, session_data,
864                                 session_data_size);
865         free(session_data);
866
867         ret = do_handshake(hd);
868         if (ret < 0) {
869                 fprintf(stderr, "*** Resume handshake has failed\n");
870                 gnutls_perror(ret);
871                 return ret;
872         }
873
874         printf("- Resume Handshake was completed\n");
875         if (gnutls_session_is_resumed(hd->session) != 0)
876                 printf("*** This is a resumed session\n");
877
878         return 0;
879 }
880
881 static
882 bool parse_for_inline_commands_in_buffer(char *buffer, size_t bytes,
883                                          inline_cmds_st * inline_cmds)
884 {
885         ssize_t local_bytes, match_bytes, prev_bytes_copied, ii, jj;
886         char *local_buffer_ptr, *ptr;
887         char inline_command_string[MAX_INLINE_COMMAND_BYTES];
888         ssize_t l;
889
890         inline_cmds->bytes_to_flush = 0;
891         inline_cmds->cmd_found = INLINE_COMMAND_NONE;
892
893         if (inline_cmds->bytes_copied) {
894                 local_buffer_ptr =
895                     &inline_cmds->inline_cmd_buffer[inline_cmds->
896                                                     bytes_copied];
897
898                 local_bytes =
899                     ((inline_cmds->bytes_copied + bytes) <=
900                      MAX_INLINE_COMMAND_BYTES) ? (ssize_t) bytes
901                     : (MAX_INLINE_COMMAND_BYTES -
902                        inline_cmds->bytes_copied);
903
904                 memcpy(local_buffer_ptr, buffer, local_bytes);
905                 prev_bytes_copied = inline_cmds->bytes_copied;
906                 inline_cmds->new_buffer_ptr = buffer + local_bytes;
907                 inline_cmds->bytes_copied += local_bytes;
908                 local_buffer_ptr = inline_cmds->inline_cmd_buffer;
909                 local_bytes = inline_cmds->bytes_copied;
910         } else {
911                 prev_bytes_copied = 0;
912                 local_buffer_ptr = buffer;
913                 local_bytes = bytes;
914                 inline_cmds->new_buffer_ptr = buffer + bytes;
915         }
916
917         inline_cmds->current_ptr = local_buffer_ptr;
918
919         if (local_buffer_ptr[0] == inline_commands_prefix[0]
920             && inline_cmds->lf_found) {
921                 for (jj = 0; jj < NUM_INLINE_COMMANDS; jj++) {
922                         if (inline_commands_prefix[0] != '^') { /* refer inline_cmds.h for usage of ^ */
923                                 strcpy(inline_command_string,
924                                        inline_commands_def[jj].string);
925                                 inline_command_string[strlen
926                                                       (inline_commands_def
927                                                        [jj].string)] =
928                                     '\0';
929                                 inline_command_string[0] =
930                                     inline_commands_prefix[0];
931                                 /* Inline commands are delimited by the inline_commands_prefix[0] (default is ^).
932                                    The inline_commands_def[].string includes a trailing LF */
933                                 inline_command_string[strlen
934                                                       (inline_commands_def
935                                                        [jj].string) - 2] =
936                                     inline_commands_prefix[0];
937                                 ptr = inline_command_string;
938                         } else
939                                 ptr = inline_commands_def[jj].string;
940
941                         l = strlen(ptr);
942                         match_bytes = (local_bytes <= l) ? local_bytes : l;
943                         if (strncmp(ptr, local_buffer_ptr, match_bytes) ==
944                             0) {
945                                 if (match_bytes == (ssize_t) strlen(ptr)) {
946                                         inline_cmds->new_buffer_ptr =
947                                             buffer + match_bytes -
948                                             prev_bytes_copied;
949                                         inline_cmds->cmd_found =
950                                             inline_commands_def[jj].
951                                             command;
952                                         inline_cmds->bytes_copied = 0;  /* reset it */
953                                 } else {
954                                         /* partial command */
955                                         memcpy(&inline_cmds->
956                                                inline_cmd_buffer
957                                                [inline_cmds->bytes_copied],
958                                                buffer, bytes);
959                                         inline_cmds->bytes_copied += bytes;
960                                 }
961                                 return true;
962                         }
963                         /* else - if not a match, do nothing here */
964                 }               /* for */
965         }
966
967         for (ii = prev_bytes_copied; ii < local_bytes; ii++) {
968                 if (ii && local_buffer_ptr[ii] == inline_commands_prefix[0]
969                     && inline_cmds->lf_found) {
970                         /* possible inline command. First, let's flush bytes up to ^ */
971                         inline_cmds->new_buffer_ptr =
972                             buffer + ii - prev_bytes_copied;
973                         inline_cmds->bytes_to_flush = ii;
974                         inline_cmds->lf_found = true;
975
976                         /* bytes to flush starts at inline_cmds->current_ptr */
977                         return true;
978                 } else if (local_buffer_ptr[ii] == '\n') {
979                         inline_cmds->lf_found = true;
980                 } else {
981                         inline_cmds->lf_found = false;
982                 }
983         }                       /* for */
984
985         inline_cmds->bytes_copied = 0;  /* reset it */
986         return false;           /* not an inline command */
987 }
988
989 static
990 int run_inline_command(inline_cmds_st * cmd, socket_st * hd)
991 {
992         switch (cmd->cmd_found) {
993         case INLINE_COMMAND_RESUME:
994                 return try_resume(hd);
995         case INLINE_COMMAND_RENEGOTIATE:
996                 return try_rehandshake(hd);
997         default:
998                 return -1;
999         }
1000 }
1001
1002 static
1003 int do_inline_command_processing(char *buffer_ptr, size_t curr_bytes,
1004                                  socket_st * hd,
1005                                  inline_cmds_st * inline_cmds)
1006 {
1007         int skip_bytes, bytes;
1008         bool inline_cmd_start_found;
1009
1010         bytes = curr_bytes;
1011
1012       continue_inline_processing:
1013         /* parse_for_inline_commands_in_buffer hunts for start of an inline command
1014          * sequence. The function maintains state information in inline_cmds. 
1015          */
1016         inline_cmd_start_found =
1017             parse_for_inline_commands_in_buffer(buffer_ptr, bytes,
1018                                                 inline_cmds);
1019         if (!inline_cmd_start_found)
1020                 return bytes;
1021
1022         /* inline_cmd_start_found is set */
1023
1024         if (inline_cmds->bytes_to_flush) {
1025                 /* start of an inline command sequence found, but is not
1026                  * at the beginning of buffer. So, we flush all preceding bytes.
1027                  */
1028                 return inline_cmds->bytes_to_flush;
1029         } else if (inline_cmds->cmd_found == INLINE_COMMAND_NONE) {
1030                 /* partial command found */
1031                 return 0;
1032         } else {
1033                 /* complete inline command found and is at the start */
1034                 if (run_inline_command(inline_cmds, hd))
1035                         return -1;
1036
1037                 inline_cmds->cmd_found = INLINE_COMMAND_NONE;
1038                 skip_bytes = inline_cmds->new_buffer_ptr - buffer_ptr;
1039
1040                 if (skip_bytes >= bytes)
1041                         return 0;
1042                 else {
1043                         buffer_ptr = inline_cmds->new_buffer_ptr;
1044                         bytes -= skip_bytes;
1045                         goto continue_inline_processing;
1046                 }
1047         }
1048 }
1049
1050 static void
1051 print_other_info(gnutls_session_t session)
1052 {
1053         int ret;
1054         gnutls_datum_t oresp;
1055
1056         ret = gnutls_ocsp_status_request_get(session, &oresp);
1057         if (ret < 0) {
1058                 oresp.data = NULL;
1059                 oresp.size = 0;
1060         }
1061
1062         if (ENABLED_OPT(VERBOSE) && oresp.data) {
1063                 gnutls_ocsp_resp_t r;
1064                 gnutls_datum_t p;
1065                 unsigned flag;
1066
1067                 ret = gnutls_ocsp_resp_init(&r);
1068                 if (ret < 0) {
1069                         fprintf(stderr, "ocsp_resp_init: %s\n",
1070                                 gnutls_strerror(ret));
1071                         return;
1072                 }
1073
1074                 ret = gnutls_ocsp_resp_import(r, &oresp);
1075                 if (ret < 0) {
1076                         fprintf(stderr, "importing response: %s\n",
1077                                 gnutls_strerror(ret));
1078                         return;
1079                 }
1080
1081                 if (print_cert != 0)
1082                         flag = GNUTLS_OCSP_PRINT_FULL;
1083                 else
1084                         flag = GNUTLS_OCSP_PRINT_COMPACT;
1085                 ret =
1086                     gnutls_ocsp_resp_print(r, flag, &p);
1087                 gnutls_ocsp_resp_deinit(r);
1088                 fputs((char*)p.data, stdout);
1089         }
1090
1091         if (HAVE_OPT(SAVE_OCSP) && oresp.data) {
1092                 FILE *fp = fopen(OPT_ARG(SAVE_OCSP), "w");
1093
1094                 if (fp != NULL) {
1095                         fwrite(oresp.data, 1, oresp.size, fp);
1096                         fclose(fp);
1097                 }
1098         }
1099 }
1100
1101 int main(int argc, char **argv)
1102 {
1103         int ret;
1104         int ii, inp;
1105         char buffer[MAX_BUF + 1];
1106         int user_term = 0, retval = 0;
1107         socket_st hd;
1108         ssize_t bytes, keyboard_bytes;
1109         char *keyboard_buffer_ptr;
1110         inline_cmds_st inline_cmds;
1111 #ifndef _WIN32
1112         struct sigaction new_action;
1113 #endif
1114
1115         cmd_parser(argc, argv);
1116
1117         gnutls_global_set_log_function(tls_log_func);
1118         gnutls_global_set_log_level(OPT_VALUE_DEBUG);
1119
1120         if ((ret = gnutls_global_init()) < 0) {
1121                 fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret));
1122                 exit(1);
1123         }
1124
1125         if (hostname == NULL) {
1126                 fprintf(stderr, "No hostname given\n");
1127                 exit(1);
1128         }
1129
1130         sockets_init();
1131
1132         init_global_tls_stuff();
1133
1134         socket_open(&hd, hostname, service, udp, CONNECT_MSG);
1135         hd.verbose = verbose;
1136
1137         if (HAVE_OPT(STARTTLS_PROTO))
1138                 socket_starttls(&hd, OPT_ARG(STARTTLS_PROTO));
1139
1140         hd.session = init_tls_session(hostname);
1141         if (starttls)
1142                 goto after_handshake;
1143
1144         ret = do_handshake(&hd);
1145
1146         if (ret < 0) {
1147                 fprintf(stderr, "*** Handshake has failed\n");
1148                 gnutls_perror(ret);
1149                 gnutls_deinit(hd.session);
1150                 return 1;
1151         } else
1152                 printf("- Handshake was completed\n");
1153
1154         if (resume != 0)
1155                 if (try_resume(&hd))
1156                         return 1;
1157
1158         print_other_info(hd.session);
1159
1160       after_handshake:
1161
1162         /* Warning!  Do not touch this text string, it is used by external
1163            programs to search for when gnutls-cli has reached this point. */
1164         printf("\n- Simple Client Mode:\n\n");
1165
1166         if (rehandshake)
1167                 if (try_rehandshake(&hd))
1168                         return 1;
1169
1170 #ifndef _WIN32
1171         new_action.sa_handler = starttls_alarm;
1172         sigemptyset(&new_action.sa_mask);
1173         new_action.sa_flags = 0;
1174
1175         sigaction(SIGALRM, &new_action, NULL);
1176 #endif
1177
1178         fflush(stdout);
1179         fflush(stderr);
1180
1181         /* do not buffer */
1182 #ifndef _WIN32
1183         setbuf(stdin, NULL);
1184 #endif
1185         setbuf(stdout, NULL);
1186         setbuf(stderr, NULL);
1187
1188         if (inline_commands) {
1189                 memset(&inline_cmds, 0, sizeof(inline_cmds_st));
1190                 inline_cmds.lf_found = true;    /* initially, at start of line */
1191         }
1192
1193         for (;;) {
1194                 if (starttls_alarmed && !hd.secure) {
1195                         /* Warning!  Do not touch this text string, it is used by
1196                            external programs to search for when gnutls-cli has
1197                            reached this point. */
1198                         fprintf(stderr, "*** Starting TLS handshake\n");
1199                         ret = do_handshake(&hd);
1200                         if (ret < 0) {
1201                                 fprintf(stderr,
1202                                         "*** Handshake has failed\n");
1203                                 user_term = 1;
1204                                 retval = 1;
1205                                 break;
1206                         }
1207                 }
1208
1209                 inp = check_net_or_keyboard_input(&hd);
1210
1211                 if (inp == IN_NET) {
1212                         memset(buffer, 0, MAX_BUF + 1);
1213                         ret = socket_recv(&hd, buffer, MAX_BUF);
1214
1215                         if (ret == 0) {
1216                                 printf
1217                                     ("- Peer has closed the GnuTLS connection\n");
1218                                 break;
1219                         } else if (handle_error(&hd, ret) < 0
1220                                    && user_term == 0) {
1221                                 fprintf(stderr,
1222                                         "*** Server has terminated the connection abnormally.\n");
1223                                 retval = 1;
1224                                 break;
1225                         } else if (ret > 0) {
1226                                 if (verbose != 0)
1227                                         printf("- Received[%d]: ", ret);
1228                                 for (ii = 0; ii < ret; ii++) {
1229                                         fputc(buffer[ii], stdout);
1230                                 }
1231                                 fflush(stdout);
1232                         }
1233
1234                         if (user_term != 0)
1235                                 break;
1236                 }
1237
1238                 if (inp == IN_KEYBOARD) {
1239                         if ((bytes =
1240                              read(fileno(stdin), buffer,
1241                                   MAX_BUF - 1)) <= 0) {
1242                                 if (hd.secure == 0) {
1243                                         /* Warning!  Do not touch this text string, it is
1244                                            used by external programs to search for when
1245                                            gnutls-cli has reached this point. */
1246                                         fprintf(stderr,
1247                                                 "*** Starting TLS handshake\n");
1248                                         ret = do_handshake(&hd);
1249                                         clearerr(stdin);
1250                                         if (ret < 0) {
1251                                                 fprintf(stderr,
1252                                                         "*** Handshake has failed\n");
1253                                                 user_term = 1;
1254                                                 retval = 1;
1255                                                 break;
1256                                         }
1257                                 } else {
1258                                         user_term = 1;
1259                                         break;
1260                                 }
1261                                 continue;
1262                         }
1263
1264                         buffer[bytes] = 0;
1265                         if (crlf != 0) {
1266                                 char *b = strchr(buffer, '\n');
1267                                 if (b != NULL) {
1268                                         strcpy(b, "\r\n");
1269                                         bytes++;
1270                                 }
1271                         }
1272
1273                         keyboard_bytes = bytes;
1274                         keyboard_buffer_ptr = buffer;
1275
1276                       inline_command_processing:
1277
1278                         if (inline_commands) {
1279                                 keyboard_bytes =
1280                                     do_inline_command_processing
1281                                     (keyboard_buffer_ptr, keyboard_bytes,
1282                                      &hd, &inline_cmds);
1283                                 if (keyboard_bytes == 0)
1284                                         continue;
1285                                 else if (keyboard_bytes < 0) {  /* error processing an inline command */
1286                                         retval = 1;
1287                                         break;
1288                                 } else {
1289                                         /* current_ptr could point to either an inline_cmd_buffer
1290                                          * or may point to start or an offset into buffer.
1291                                          */
1292                                         keyboard_buffer_ptr =
1293                                             inline_cmds.current_ptr;
1294                                 }
1295                         }
1296
1297                         if (ranges
1298                             && gnutls_record_can_use_length_hiding(hd.
1299                                                                    session))
1300                         {
1301                                 gnutls_range_st range;
1302                                 range.low = 0;
1303                                 range.high = MAX_BUF;
1304                                 ret =
1305                                     socket_send_range(&hd,
1306                                                       keyboard_buffer_ptr,
1307                                                       keyboard_bytes,
1308                                                       &range);
1309                         } else {
1310                                 ret =
1311                                     socket_send(&hd, keyboard_buffer_ptr,
1312                                                 keyboard_bytes);
1313                         }
1314
1315                         if (ret > 0) {
1316                                 if (verbose != 0)
1317                                         printf("- Sent: %d bytes\n", ret);
1318                         } else
1319                                 handle_error(&hd, ret);
1320
1321                         if (inline_commands &&
1322                             inline_cmds.new_buffer_ptr < (buffer + bytes))
1323                         {
1324                                 keyboard_buffer_ptr =
1325                                     inline_cmds.new_buffer_ptr;
1326                                 keyboard_bytes =
1327                                     (buffer + bytes) - keyboard_buffer_ptr;
1328                                 goto inline_command_processing;
1329                         }
1330                 }
1331         }
1332
1333         if (user_term != 0)
1334                 socket_bye(&hd);
1335         else
1336                 gnutls_deinit(hd.session);
1337
1338 #ifdef ENABLE_SRP
1339         if (srp_cred)
1340                 gnutls_srp_free_client_credentials(srp_cred);
1341 #endif
1342 #ifdef ENABLE_PSK
1343         if (psk_cred)
1344                 gnutls_psk_free_client_credentials(psk_cred);
1345 #endif
1346
1347         gnutls_certificate_free_credentials(xcred);
1348
1349 #ifdef ENABLE_ANON
1350         gnutls_anon_free_client_credentials(anon_cred);
1351 #endif
1352
1353         gnutls_global_deinit();
1354
1355         return retval;
1356 }
1357
1358 static
1359 void print_priority_list(void)
1360 {
1361         unsigned int idx;
1362         const char *str;
1363         unsigned int lineb = 0;
1364
1365         printf("Priority strings in GnuTLS %s:\n", gnutls_check_version(NULL));
1366
1367         fputs("\t", stdout);
1368         for (idx=0;;idx++) {
1369                 str = gnutls_priority_string_list(idx, GNUTLS_PRIORITY_LIST_INIT_KEYWORDS);
1370                 if (str == NULL)
1371                         break;
1372                 lineb += printf("%s ", str);
1373                 if (lineb > 64) {
1374                         lineb = 0;
1375                         printf("\n\t");
1376                 }
1377         }
1378
1379         printf("\n\nSpecial strings:\n");
1380         lineb = 0;
1381         fputs("\t", stdout);
1382         for (idx=0;;idx++) {
1383                 str = gnutls_priority_string_list(idx, GNUTLS_PRIORITY_LIST_SPECIAL);
1384                 if (str == NULL)
1385                         break;
1386                 if (str[0] == 0)
1387                         continue;
1388                 lineb += printf("%%%s ", str);
1389                 if (lineb > 64) {
1390                         lineb = 0;
1391                         printf("\n\t");
1392                 }
1393         }
1394         printf("\n");
1395
1396         return;
1397 }
1398
1399 static void cmd_parser(int argc, char **argv)
1400 {
1401         const char *rest = NULL;
1402
1403         int optct = optionProcess(&gnutls_cliOptions, argc, argv);
1404         argc -= optct;
1405         argv += optct;
1406
1407         if (rest == NULL && argc > 0)
1408                 rest = argv[0];
1409
1410
1411         if (HAVE_OPT(FIPS140_MODE)) {
1412                 if (gnutls_fips140_mode_enabled() != 0) {
1413                         fprintf(stderr, "library is in FIPS140-2 mode\n");
1414                         exit(0);
1415                 }
1416                 fprintf(stderr, "library is NOT in FIPS140-2 mode\n");
1417                 exit(1);
1418         }
1419
1420         if (HAVE_OPT(BENCHMARK_CIPHERS)) {
1421                 benchmark_cipher(OPT_VALUE_DEBUG);
1422                 exit(0);
1423         }
1424
1425         if (HAVE_OPT(BENCHMARK_TLS_CIPHERS)) {
1426                 benchmark_tls(OPT_VALUE_DEBUG, 1);
1427                 exit(0);
1428         }
1429
1430         if (HAVE_OPT(BENCHMARK_TLS_KX)) {
1431                 benchmark_tls(OPT_VALUE_DEBUG, 0);
1432                 exit(0);
1433         }
1434
1435         if (HAVE_OPT(PRIORITY)) {
1436                 priorities = OPT_ARG(PRIORITY);
1437         }
1438         verbose = HAVE_OPT(VERBOSE);
1439         if (verbose)
1440                 print_cert = 1;
1441         else
1442                 print_cert = HAVE_OPT(PRINT_CERT);
1443
1444         if (HAVE_OPT(LIST)) {
1445                 print_list(priorities, verbose);
1446                 exit(0);
1447         }
1448
1449         if (HAVE_OPT(PRIORITY_LIST)) {
1450                 print_priority_list();
1451                 exit(0);
1452         }
1453
1454         disable_sni = HAVE_OPT(DISABLE_SNI);
1455         disable_extensions = HAVE_OPT(DISABLE_EXTENSIONS);
1456         if (disable_extensions)
1457                 init_flags |= GNUTLS_NO_EXTENSIONS;
1458
1459         inline_commands = HAVE_OPT(INLINE_COMMANDS);
1460         if (HAVE_OPT(INLINE_COMMANDS_PREFIX)) {
1461                 if (strlen(OPT_ARG(INLINE_COMMANDS_PREFIX)) > 1) {
1462                         fprintf(stderr,
1463                                 "inline-commands-prefix value is a single US-ASCII character (octets 0 - 127)\n");
1464                         exit(1);
1465                 }
1466                 inline_commands_prefix =
1467                     (char *) OPT_ARG(INLINE_COMMANDS_PREFIX);
1468                 if (!isascii(inline_commands_prefix[0])) {
1469                         fprintf(stderr,
1470                                 "inline-commands-prefix value is a single US-ASCII character (octets 0 - 127)\n");
1471                         exit(1);
1472                 }
1473         } else
1474                 inline_commands_prefix = "^";
1475
1476         starttls = HAVE_OPT(STARTTLS);
1477         resume = HAVE_OPT(RESUME);
1478         rehandshake = HAVE_OPT(REHANDSHAKE);
1479         insecure = HAVE_OPT(INSECURE);
1480         ranges = HAVE_OPT(RANGES);
1481
1482         udp = HAVE_OPT(UDP);
1483         mtu = OPT_VALUE_MTU;
1484
1485         if (HAVE_OPT(PORT)) {
1486                 service = OPT_ARG(PORT);
1487         } else {
1488                 service = "443";
1489         }
1490
1491         record_max_size = OPT_VALUE_RECORDSIZE;
1492
1493         fingerprint = HAVE_OPT(FINGERPRINT);
1494
1495         if (HAVE_OPT(X509FMTDER))
1496                 x509ctype = GNUTLS_X509_FMT_DER;
1497         else
1498                 x509ctype = GNUTLS_X509_FMT_PEM;
1499
1500         if (HAVE_OPT(SRPUSERNAME))
1501                 srp_username = OPT_ARG(SRPUSERNAME);
1502
1503         if (HAVE_OPT(SRPPASSWD))
1504                 srp_passwd = OPT_ARG(SRPPASSWD);
1505
1506         if (HAVE_OPT(X509CAFILE))
1507                 x509_cafile = OPT_ARG(X509CAFILE);
1508
1509         if (HAVE_OPT(X509CRLFILE))
1510                 x509_crlfile = OPT_ARG(X509CRLFILE);
1511
1512         if (HAVE_OPT(X509KEYFILE))
1513                 x509_keyfile = OPT_ARG(X509KEYFILE);
1514
1515         if (HAVE_OPT(X509CERTFILE))
1516                 x509_certfile = OPT_ARG(X509CERTFILE);
1517
1518         if (HAVE_OPT(PGPKEYFILE))
1519                 pgp_keyfile = OPT_ARG(PGPKEYFILE);
1520
1521         if (HAVE_OPT(PGPCERTFILE))
1522                 pgp_certfile = OPT_ARG(PGPCERTFILE);
1523
1524         if (HAVE_OPT(PSKUSERNAME))
1525                 psk_username = OPT_ARG(PSKUSERNAME);
1526
1527         if (HAVE_OPT(PSKKEY)) {
1528                 psk_key.data = (unsigned char *) OPT_ARG(PSKKEY);
1529                 psk_key.size = strlen(OPT_ARG(PSKKEY));
1530         } else
1531                 psk_key.size = 0;
1532
1533         if (HAVE_OPT(PGPKEYRING))
1534                 pgp_keyring = OPT_ARG(PGPKEYRING);
1535
1536         crlf = HAVE_OPT(CRLF);
1537
1538         if (rest != NULL)
1539                 hostname = rest;
1540
1541         if (hostname == NULL) {
1542                 fprintf(stderr, "No hostname specified\n");
1543                 exit(1);
1544         }
1545 }
1546
1547 static void check_rehandshake(socket_st * socket, int ret)
1548 {
1549         if (socket->secure && ret == GNUTLS_E_REHANDSHAKE) {
1550                 /* There is a race condition here. If application
1551                  * data is sent after the rehandshake request,
1552                  * the server thinks we ignored his request.
1553                  * This is a bad design of this client.
1554                  */
1555                 printf("*** Received rehandshake request\n");
1556                 /* gnutls_alert_send( session, GNUTLS_AL_WARNING, GNUTLS_A_NO_RENEGOTIATION); */
1557
1558                 ret = do_handshake(socket);
1559
1560                 if (ret == 0) {
1561                         printf("*** Rehandshake was performed.\n");
1562                 } else {
1563                         printf("*** Rehandshake Failed.\n");
1564                 }
1565         }
1566 }
1567
1568
1569 static int do_handshake(socket_st * socket)
1570 {
1571         int ret;
1572
1573         gnutls_transport_set_int(socket->session, socket->fd);
1574         set_read_funcs(socket->session);
1575
1576         do {
1577                 gnutls_handshake_set_timeout(socket->session,
1578                                              GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
1579                 ret = gnutls_handshake(socket->session);
1580
1581                 if (ret < 0) {
1582                         handle_error(socket, ret);
1583                 }
1584         }
1585         while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
1586
1587         if (ret == 0) {
1588                 /* print some information */
1589                 print_info(socket->session, verbose, 0);
1590                 socket->secure = 1;
1591         } else {
1592                 gnutls_alert_send_appropriate(socket->session, ret);
1593                 shutdown(socket->fd, SHUT_RDWR);
1594         }
1595         return ret;
1596 }
1597
1598 static int
1599 srp_username_callback(gnutls_session_t session,
1600                       char **username, char **password)
1601 {
1602         if (srp_username == NULL || srp_passwd == NULL) {
1603                 return -1;
1604         }
1605
1606         *username = gnutls_strdup(srp_username);
1607         *password = gnutls_strdup(srp_passwd);
1608
1609         return 0;
1610 }
1611
1612 static int
1613 psk_callback(gnutls_session_t session, char **username,
1614              gnutls_datum_t * key)
1615 {
1616         const char *hint = gnutls_psk_client_get_hint(session);
1617         char *rawkey;
1618         char *passwd;
1619         int ret;
1620         size_t res_size;
1621         gnutls_datum_t tmp;
1622
1623         printf("- PSK client callback. ");
1624         if (hint)
1625                 printf("PSK hint '%s'\n", hint);
1626         else
1627                 printf("No PSK hint\n");
1628
1629         if (HAVE_OPT(PSKUSERNAME))
1630                 *username = gnutls_strdup(OPT_ARG(PSKUSERNAME));
1631         else {
1632                 char *p = NULL;
1633                 size_t n;
1634
1635                 printf("Enter PSK identity: ");
1636                 fflush(stdout);
1637                 getline(&p, &n, stdin);
1638
1639                 if (p == NULL) {
1640                         fprintf(stderr,
1641                                 "No username given, aborting...\n");
1642                         return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1643                 }
1644
1645                 if (p[strlen(p) - 1] == '\n')
1646                         p[strlen(p) - 1] = '\0';
1647                 if (p[strlen(p) - 1] == '\r')
1648                         p[strlen(p) - 1] = '\0';
1649
1650                 *username = gnutls_strdup(p);
1651                 free(p);
1652         }
1653         if (!*username)
1654                 return GNUTLS_E_MEMORY_ERROR;
1655
1656         passwd = getpass("Enter key: ");
1657         if (passwd == NULL) {
1658                 fprintf(stderr, "No key given, aborting...\n");
1659                 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1660         }
1661
1662         tmp.data = (void *) passwd;
1663         tmp.size = strlen(passwd);
1664
1665         res_size = tmp.size / 2 + 1;
1666         rawkey = gnutls_malloc(res_size);
1667         if (rawkey == NULL)
1668                 return GNUTLS_E_MEMORY_ERROR;
1669
1670         ret = gnutls_hex_decode(&tmp, rawkey, &res_size);
1671         if (ret < 0) {
1672                 fprintf(stderr, "Error deriving password: %s\n",
1673                         gnutls_strerror(ret));
1674                 gnutls_free(*username);
1675                 return ret;
1676         }
1677
1678         key->data = (void *) rawkey;
1679         key->size = res_size;
1680
1681         if (HAVE_OPT(DEBUG)) {
1682                 char hexkey[41];
1683                 res_size = sizeof(hexkey);
1684                 gnutls_hex_encode(key, hexkey, &res_size);
1685                 fprintf(stderr, "PSK username: %s\n", *username);
1686                 fprintf(stderr, "PSK hint: %s\n", hint);
1687                 fprintf(stderr, "PSK key: %s\n", hexkey);
1688         }
1689
1690         return 0;
1691 }
1692
1693 static void init_global_tls_stuff(void)
1694 {
1695         int ret;
1696
1697 #ifdef ENABLE_PKCS11
1698         if (HAVE_OPT(PROVIDER)) {
1699                 ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
1700                 if (ret < 0)
1701                         fprintf(stderr, "pkcs11_init: %s",
1702                                 gnutls_strerror(ret));
1703                 else {
1704                         ret =
1705                             gnutls_pkcs11_add_provider(OPT_ARG(PROVIDER),
1706                                                        NULL);
1707                         if (ret < 0) {
1708                                 fprintf(stderr, "pkcs11_add_provider: %s",
1709                                         gnutls_strerror(ret));
1710                                 exit(1);
1711                         }
1712                 }
1713         }
1714 #endif
1715
1716         /* X509 stuff */
1717         if (gnutls_certificate_allocate_credentials(&xcred) < 0) {
1718                 fprintf(stderr, "Certificate allocation memory error\n");
1719                 exit(1);
1720         }
1721         gnutls_certificate_set_pin_function(xcred, pin_callback, NULL);
1722
1723         if (x509_cafile != NULL) {
1724                 ret = gnutls_certificate_set_x509_trust_file(xcred,
1725                                                              x509_cafile,
1726                                                              x509ctype);
1727         } else {
1728                 if (insecure == 0) {
1729                         ret = gnutls_certificate_set_x509_system_trust(xcred);
1730                 } else {
1731                         ret = 0;
1732                 }
1733         }
1734         if (ret < 0) {
1735                 fprintf(stderr, "Error setting the x509 trust file\n");
1736         } else {
1737                 printf("Processed %d CA certificate(s).\n", ret);
1738         }
1739
1740         if (x509_crlfile != NULL) {
1741                 ret =
1742                     gnutls_certificate_set_x509_crl_file(xcred,
1743                                                          x509_crlfile,
1744                                                          x509ctype);
1745                 if (ret < 0) {
1746                         fprintf(stderr,
1747                                 "Error setting the x509 CRL file\n");
1748                 } else {
1749                         printf("Processed %d CRL(s).\n", ret);
1750                 }
1751         }
1752
1753         load_keys();
1754
1755 #ifdef ENABLE_OPENPGP
1756         if (pgp_keyring != NULL) {
1757                 ret =
1758                     gnutls_certificate_set_openpgp_keyring_file(xcred,
1759                                                                 pgp_keyring,
1760                                                                 GNUTLS_OPENPGP_FMT_BASE64);
1761                 if (ret < 0) {
1762                         fprintf(stderr,
1763                                 "Error setting the OpenPGP keyring file\n");
1764                 }
1765         }
1766 #endif
1767
1768 #ifdef ENABLE_SRP
1769         if (srp_username && srp_passwd) {
1770                 /* SRP stuff */
1771                 if (gnutls_srp_allocate_client_credentials(&srp_cred) < 0) {
1772                         fprintf(stderr, "SRP authentication error\n");
1773                 }
1774
1775                 gnutls_srp_set_client_credentials_function(srp_cred,
1776                                                            srp_username_callback);
1777         }
1778 #endif
1779
1780 #ifdef ENABLE_PSK
1781         /* PSK stuff */
1782         if (gnutls_psk_allocate_client_credentials(&psk_cred) < 0) {
1783                 fprintf(stderr, "PSK authentication error\n");
1784         }
1785
1786         if (psk_username && psk_key.data) {
1787                 ret = gnutls_psk_set_client_credentials(psk_cred,
1788                                                         psk_username,
1789                                                         &psk_key,
1790                                                         GNUTLS_PSK_KEY_HEX);
1791                 if (ret < 0) {
1792                         fprintf(stderr,
1793                                 "Error setting the PSK credentials: %s\n",
1794                                 gnutls_strerror(ret));
1795                 }
1796         } else
1797                 gnutls_psk_set_client_credentials_function(psk_cred,
1798                                                            psk_callback);
1799 #endif
1800
1801 #ifdef ENABLE_ANON
1802         /* ANON stuff */
1803         if (gnutls_anon_allocate_client_credentials(&anon_cred) < 0) {
1804                 fprintf(stderr, "Anonymous authentication error\n");
1805         }
1806 #endif
1807
1808 }
1809
1810 /* OCSP check for the peer's certificate. Should be called 
1811  * only after the certificate list verication is complete.
1812  * Returns:
1813  * 0: certificate is revoked
1814  * 1: certificate is ok
1815  * -1: dunno
1816  */
1817 static int cert_verify_ocsp(gnutls_session_t session)
1818 {
1819         gnutls_x509_crt_t crt, issuer;
1820         const gnutls_datum_t *cert_list;
1821         unsigned int cert_list_size = 0;
1822         int deinit_issuer = 0;
1823         gnutls_datum_t resp;
1824         unsigned char noncebuf[23];
1825         gnutls_datum_t nonce = { noncebuf, sizeof(noncebuf) };
1826         int ret;
1827
1828         cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
1829         if (cert_list_size == 0) {
1830                 fprintf(stderr, "No certificates found!\n");
1831                 return -1;
1832         }
1833
1834         gnutls_x509_crt_init(&crt);
1835         ret =
1836             gnutls_x509_crt_import(crt, &cert_list[0],
1837                                    GNUTLS_X509_FMT_DER);
1838         if (ret < 0) {
1839                 fprintf(stderr, "Decoding error: %s\n",
1840                         gnutls_strerror(ret));
1841                 return -1;
1842         }
1843
1844         ret = gnutls_certificate_get_issuer(xcred, crt, &issuer, 0);
1845         if (ret < 0 && cert_list_size > 1) {
1846                 gnutls_x509_crt_init(&issuer);
1847                 ret =
1848                     gnutls_x509_crt_import(issuer, &cert_list[1],
1849                                            GNUTLS_X509_FMT_DER);
1850                 if (ret < 0) {
1851                         fprintf(stderr, "Decoding error: %s\n",
1852                                 gnutls_strerror(ret));
1853                         return -1;
1854                 }
1855                 deinit_issuer = 1;
1856         } else if (ret < 0) {
1857                 fprintf(stderr, "Cannot find issuer\n");
1858                 ret = -1;
1859                 goto cleanup;
1860         }
1861
1862         ret =
1863             gnutls_rnd(GNUTLS_RND_NONCE, nonce.data, nonce.size);
1864         if (ret < 0) {
1865                 fprintf(stderr, "gnutls_rnd: %s",
1866                         gnutls_strerror(ret));
1867                 ret = -1;
1868                 goto cleanup;
1869         }
1870
1871         ret = send_ocsp_request(NULL, crt, issuer, &resp, &nonce);
1872         if (ret < 0) {
1873                 fprintf(stderr, "Cannot contact OCSP server\n");
1874                 ret = -1;
1875                 goto cleanup;
1876         }
1877
1878         /* verify and check the response for revoked cert */
1879         ret = check_ocsp_response(crt, issuer, &resp, &nonce);
1880
1881       cleanup:
1882         if (deinit_issuer)
1883                 gnutls_x509_crt_deinit(issuer);
1884         gnutls_x509_crt_deinit(crt);
1885
1886         return ret;
1887 }