don't be so verbose about the OCSP nonce; it is universally unsupported
[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 == -1) {
409                                 printf
410                                     ("*** Verifying (with OCSP) server certificate chain failed...\n");
411                                 if (!insecure && !ssh)
412                                         return -1;
413                         } else if (rc == 0)
414                                 printf("*** OCSP: nothing to check.\n");
415                         else
416                                 printf("*** OCSP: verified %d certificate(s).\n", rc);
417                 }
418         }
419
420 #ifdef HAVE_DANE
421         if (dane) {             /* try DANE auth */
422                 int port;
423                 unsigned vflags = 0;
424                 unsigned int sflags =
425                     ENABLED_OPT(LOCAL_DNS) ? 0 :
426                     DANE_F_IGNORE_LOCAL_RESOLVER;
427
428                 /* if we didn't verify the chain it only makes sense
429                  * to check the end certificate using dane. */
430                 if (ca_verify == 0)
431                         vflags |= DANE_VFLAG_ONLY_CHECK_EE_USAGE;
432
433                 port = service_to_port(service, udp?"udp":"tcp");
434                 rc = dane_verify_session_crt(NULL, session, hostname,
435                                              udp ? "udp" : "tcp", port,
436                                              sflags, vflags, &status);
437                 if (rc < 0) {
438                         fprintf(stderr,
439                                 "*** DANE verification error: %s\n",
440                                 dane_strerror(rc));
441                         if (!insecure && !ssh)
442                                 return -1;
443                 } else {
444                         gnutls_datum_t out;
445
446                         rc = dane_verification_status_print(status, &out,
447                                                             0);
448                         if (rc < 0) {
449                                 fprintf(stderr, "*** DANE error: %s\n",
450                                         dane_strerror(rc));
451                         } else {
452                                 fprintf(stderr, "- DANE: %s\n", out.data);
453                                 gnutls_free(out.data);
454                         }
455
456                         if (status != 0 && !insecure && !ssh)
457                                 return -1;
458                 }
459
460         }
461 #endif
462
463         if (ssh) {              /* try ssh auth */
464                 unsigned int list_size;
465                 const gnutls_datum_t *cert;
466
467                 cert = gnutls_certificate_get_peers(session, &list_size);
468                 if (cert == NULL) {
469                         fprintf(stderr,
470                                 "Cannot obtain peer's certificate!\n");
471                         return -1;
472                 }
473
474                 txt_service = port_to_service(service, udp?"udp":"tcp");
475
476                 rc = gnutls_verify_stored_pubkey(NULL, NULL, hostname,
477                                                  txt_service,
478                                                  GNUTLS_CRT_X509, cert, 0);
479                 if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) {
480                         fprintf(stderr,
481                                 "Host %s (%s) has never been contacted before.\n",
482                                 hostname, txt_service);
483                         if (status == 0)
484                                 fprintf(stderr,
485                                         "Its certificate is valid for %s.\n",
486                                         hostname);
487
488                         rc = read_yesno
489                             ("Are you sure you want to trust it? (y/N): ");
490                         if (rc == 0)
491                                 return -1;
492                 } else if (rc == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
493                         fprintf(stderr,
494                                 "Warning: host %s is known and it is associated with a different key.\n",
495                                 hostname);
496                         fprintf(stderr,
497                                 "It might be that the server has multiple keys, or an attacker replaced the key to eavesdrop this connection .\n");
498                         if (status == 0)
499                                 fprintf(stderr,
500                                         "Its certificate is valid for %s.\n",
501                                         hostname);
502
503                         if (strictssh == 0) {
504                                 rc = read_yesno
505                                         ("Do you trust the received key? (y/N): ");
506                                 if (rc == 0)
507                                         return -1;
508                         } else return -1;
509
510                 } else if (rc < 0) {
511                         fprintf(stderr,
512                                 "gnutls_verify_stored_pubkey: %s\n",
513                                 gnutls_strerror(rc));
514                         return -1;
515                 }
516
517                 if (rc != 0) {
518                         rc = gnutls_store_pubkey(NULL, NULL, hostname,
519                                                  txt_service,
520                                                  GNUTLS_CRT_X509, cert, 0,
521                                                  0);
522                         if (rc < 0)
523                                 fprintf(stderr,
524                                         "Could not store key: %s\n",
525                                         gnutls_strerror(rc));
526                 }
527         }
528         return 0;
529 }
530
531 /* This callback should be associated with a session by calling
532  * gnutls_certificate_client_set_retrieve_function( session, cert_callback),
533  * before a handshake.
534  */
535
536 static int
537 cert_callback(gnutls_session_t session,
538               const gnutls_datum_t * req_ca_rdn, int nreqs,
539               const gnutls_pk_algorithm_t * sign_algos,
540               int sign_algos_length, gnutls_pcert_st ** pcert,
541               unsigned int *pcert_length, gnutls_privkey_t * pkey)
542 {
543         char issuer_dn[256];
544         int i, ret, cert_type;
545         size_t len;
546
547         if (verbose) {
548                 /* Print the server's trusted CAs
549                  */
550                 if (nreqs > 0)
551                         printf("- Server's trusted authorities:\n");
552                 else
553                         printf
554                             ("- Server did not send us any trusted authorities names.\n");
555
556                 /* print the names (if any) */
557                 for (i = 0; i < nreqs; i++) {
558                         len = sizeof(issuer_dn);
559                         ret =
560                             gnutls_x509_rdn_get(&req_ca_rdn[i], issuer_dn,
561                                                 &len);
562                         if (ret >= 0) {
563                                 printf("   [%d]: ", i);
564                                 printf("%s\n", issuer_dn);
565                         }
566                 }
567         }
568
569         /* Select a certificate and return it.
570          * The certificate must be of any of the "sign algorithms"
571          * supported by the server.
572          */
573
574         cert_type = gnutls_certificate_type_get(session);
575
576         *pcert_length = 0;
577
578         if (cert_type == GNUTLS_CRT_X509) {
579                 if (x509_crt_size > 0) {
580                         if (x509_key != NULL) {
581                                 *pkey = x509_key;
582                         } else {
583                                 printf
584                                     ("- Could not find a suitable key to send to server\n");
585                                 return -1;
586                         }
587
588                         *pcert_length = x509_crt_size;
589                         *pcert = x509_crt;
590                 }
591
592         } else if (cert_type == GNUTLS_CRT_OPENPGP) {
593                 if (pgp_key != NULL) {
594                         *pkey = pgp_key;
595
596                         *pcert_length = 1;
597                         *pcert = &pgp_crt;
598                 }
599         }
600
601         printf("- Successfully sent %u certificate(s) to server.\n",
602                *pcert_length);
603         return 0;
604
605 }
606
607 /* initializes a gnutls_session_t with some defaults.
608  */
609 static gnutls_session_t init_tls_session(const char *host)
610 {
611         const char *err;
612         int ret;
613         unsigned i;
614         gnutls_session_t session;
615
616         if (udp) {
617                 gnutls_init(&session, GNUTLS_DATAGRAM | init_flags);
618                 if (mtu)
619                         gnutls_dtls_set_mtu(session, mtu);
620         } else
621                 gnutls_init(&session, init_flags);
622
623         if ((ret =
624              gnutls_priority_set_direct(session, priorities, &err)) < 0) {
625                 if (ret == GNUTLS_E_INVALID_REQUEST)
626                         fprintf(stderr, "Syntax error at: %s\n", err);
627                 else
628                         fprintf(stderr, "Error in priorities: %s\n",
629                                 gnutls_strerror(ret));
630                 exit(1);
631         }
632
633         /* allow the use of private ciphersuites.
634          */
635         if (disable_extensions == 0 && disable_sni == 0) {
636                 if (host != NULL && is_ip(host) == 0)
637                         gnutls_server_name_set(session, GNUTLS_NAME_DNS,
638                                                host, strlen(host));
639         }
640
641         if (HAVE_OPT(DH_BITS))
642                 gnutls_dh_set_prime_bits(session, OPT_VALUE_DH_BITS);
643
644         if (HAVE_OPT(ALPN)) {
645                 unsigned proto_n = STACKCT_OPT(ALPN);
646                 char **protos = (void *) STACKLST_OPT(ALPN);
647                 gnutls_datum_t p[proto_n];
648
649                 for (i = 0; i < proto_n; i++) {
650                         p[i].data = (void *) protos[i];
651                         p[i].size = strlen(protos[i]);
652                 }
653                 gnutls_alpn_set_protocols(session, p, proto_n, 0);
654         }
655
656         gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred);
657         if (srp_cred)
658                 gnutls_credentials_set(session, GNUTLS_CRD_SRP, srp_cred);
659         if (psk_cred)
660                 gnutls_credentials_set(session, GNUTLS_CRD_PSK, psk_cred);
661         gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
662
663         gnutls_certificate_set_retrieve_function2(xcred, cert_callback);
664         gnutls_certificate_set_verify_function(xcred,
665                                                cert_verify_callback);
666
667         /* send the fingerprint */
668 #ifdef ENABLE_OPENPGP
669         if (fingerprint != 0)
670                 gnutls_openpgp_send_cert(session,
671                                          GNUTLS_OPENPGP_CERT_FINGERPRINT);
672 #endif
673
674         /* use the max record size extension */
675         if (record_max_size > 0 && disable_extensions == 0) {
676                 if (gnutls_record_set_max_size(session, record_max_size) <
677                     0) {
678                         fprintf(stderr,
679                                 "Cannot set the maximum record size to %d.\n",
680                                 record_max_size);
681                         fprintf(stderr,
682                                 "Possible values: 512, 1024, 2048, 4096.\n");
683                         exit(1);
684                 }
685         }
686
687         if (HAVE_OPT(HEARTBEAT))
688                 gnutls_heartbeat_enable(session,
689                                         GNUTLS_HB_PEER_ALLOWED_TO_SEND);
690
691 #ifdef ENABLE_DTLS_SRTP
692         if (HAVE_OPT(SRTP_PROFILES)) {
693                 ret =
694                     gnutls_srtp_set_profile_direct(session,
695                                                    OPT_ARG(SRTP_PROFILES),
696                                                    &err);
697                 if (ret == GNUTLS_E_INVALID_REQUEST)
698                         fprintf(stderr, "Syntax error at: %s\n", err);
699                 else if (ret != 0)
700                         fprintf(stderr, "Error in profiles: %s\n",
701                                 gnutls_strerror(ret));
702                 else fprintf(stderr,"DTLS profile set to %s\n",
703                              OPT_ARG(SRTP_PROFILES));
704
705                 if (ret != 0) exit(1);
706         }
707 #endif
708
709
710         return session;
711 }
712
713 static void cmd_parser(int argc, char **argv);
714
715 /* Returns zero if the error code was successfully handled.
716  */
717 static int handle_error(socket_st * hd, int err)
718 {
719         int alert, ret;
720         const char *err_type, *str;
721
722         if (err >= 0 || err == GNUTLS_E_AGAIN
723             || err == GNUTLS_E_INTERRUPTED)
724                 return 0;
725
726         if (gnutls_error_is_fatal(err) == 0) {
727                 ret = 0;
728                 err_type = "Non fatal";
729         } else {
730                 ret = err;
731                 err_type = "Fatal";
732         }
733
734         str = gnutls_strerror(err);
735         if (str == NULL)
736                 str = str_unknown;
737         fprintf(stderr, "*** %s error: %s\n", err_type, str);
738
739         if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
740             || err == GNUTLS_E_FATAL_ALERT_RECEIVED) {
741                 alert = gnutls_alert_get(hd->session);
742                 str = gnutls_alert_get_name(alert);
743                 if (str == NULL)
744                         str = str_unknown;
745                 printf("*** Received alert [%d]: %s\n", alert, str);
746         }
747
748         check_rehandshake(hd, err);
749
750         return ret;
751 }
752
753 int starttls_alarmed = 0;
754
755 #ifndef _WIN32
756 static void starttls_alarm(int signum)
757 {
758         starttls_alarmed = 1;
759 }
760 #endif
761
762 static void tls_log_func(int level, const char *str)
763 {
764         fprintf(stderr, "|<%d>| %s", level, str);
765 }
766
767 #define IN_KEYBOARD 1
768 #define IN_NET 2
769 #define IN_NONE 0
770 /* returns IN_KEYBOARD for keyboard input and IN_NET for network input
771  */
772 static int check_net_or_keyboard_input(socket_st * hd)
773 {
774         int maxfd;
775         fd_set rset;
776         int err;
777         struct timeval tv;
778
779         do {
780                 FD_ZERO(&rset);
781                 FD_SET(hd->fd, &rset);
782
783 #ifndef _WIN32
784                 FD_SET(fileno(stdin), &rset);
785                 maxfd = MAX(fileno(stdin), hd->fd);
786 #else
787                 maxfd = hd->fd;
788 #endif
789
790                 tv.tv_sec = 0;
791                 tv.tv_usec = 50 * 1000;
792
793                 if (hd->secure == 1)
794                         if (gnutls_record_check_pending(hd->session))
795                                 return IN_NET;
796
797                 err = select(maxfd + 1, &rset, NULL, NULL, &tv);
798                 if (err < 0)
799                         continue;
800
801                 if (FD_ISSET(hd->fd, &rset))
802                         return IN_NET;
803
804 #ifdef _WIN32
805                 {
806                         int state;
807                         state =
808                             WaitForSingleObject(GetStdHandle
809                                                 (STD_INPUT_HANDLE), 200);
810
811                         if (state == WAIT_OBJECT_0)
812                                 return IN_KEYBOARD;
813                 }
814 #else
815                 if (FD_ISSET(fileno(stdin), &rset))
816                         return IN_KEYBOARD;
817 #endif
818         }
819         while (err == 0);
820
821         return IN_NONE;
822 }
823
824 static int try_rehandshake(socket_st * hd)
825 {
826         int ret;
827
828         ret = do_handshake(hd);
829         if (ret < 0) {
830                 fprintf(stderr, "*** ReHandshake has failed\n");
831                 gnutls_perror(ret);
832                 return ret;
833         } else {
834                 printf("- ReHandshake was completed\n");
835                 return 0;
836         }
837 }
838
839 static int try_resume(socket_st * hd)
840 {
841         int ret;
842
843         char *session_data;
844         size_t session_data_size = 0;
845
846         gnutls_session_get_data(hd->session, NULL, &session_data_size);
847         session_data = (char *) malloc(session_data_size);
848         if (session_data == NULL)
849                 return GNUTLS_E_MEMORY_ERROR;
850
851         gnutls_session_get_data(hd->session, session_data,
852                                 &session_data_size);
853
854         printf("- Disconnecting\n");
855         socket_bye(hd);
856
857         printf
858             ("\n\n- Connecting again- trying to resume previous session\n");
859         socket_open(hd, hostname, service, udp, CONNECT_MSG);
860
861         if (HAVE_OPT(STARTTLS_PROTO))
862                 socket_starttls(hd, OPT_ARG(STARTTLS_PROTO));
863
864         hd->session = init_tls_session(hostname);
865         gnutls_session_set_data(hd->session, session_data,
866                                 session_data_size);
867         free(session_data);
868
869         ret = do_handshake(hd);
870         if (ret < 0) {
871                 fprintf(stderr, "*** Resume handshake has failed\n");
872                 gnutls_perror(ret);
873                 return ret;
874         }
875
876         printf("- Resume Handshake was completed\n");
877         if (gnutls_session_is_resumed(hd->session) != 0)
878                 printf("*** This is a resumed session\n");
879
880         return 0;
881 }
882
883 static
884 bool parse_for_inline_commands_in_buffer(char *buffer, size_t bytes,
885                                          inline_cmds_st * inline_cmds)
886 {
887         ssize_t local_bytes, match_bytes, prev_bytes_copied, ii, jj;
888         char *local_buffer_ptr, *ptr;
889         char inline_command_string[MAX_INLINE_COMMAND_BYTES];
890         ssize_t l;
891
892         inline_cmds->bytes_to_flush = 0;
893         inline_cmds->cmd_found = INLINE_COMMAND_NONE;
894
895         if (inline_cmds->bytes_copied) {
896                 local_buffer_ptr =
897                     &inline_cmds->inline_cmd_buffer[inline_cmds->
898                                                     bytes_copied];
899
900                 local_bytes =
901                     ((inline_cmds->bytes_copied + bytes) <=
902                      MAX_INLINE_COMMAND_BYTES) ? (ssize_t) bytes
903                     : (MAX_INLINE_COMMAND_BYTES -
904                        inline_cmds->bytes_copied);
905
906                 memcpy(local_buffer_ptr, buffer, local_bytes);
907                 prev_bytes_copied = inline_cmds->bytes_copied;
908                 inline_cmds->new_buffer_ptr = buffer + local_bytes;
909                 inline_cmds->bytes_copied += local_bytes;
910                 local_buffer_ptr = inline_cmds->inline_cmd_buffer;
911                 local_bytes = inline_cmds->bytes_copied;
912         } else {
913                 prev_bytes_copied = 0;
914                 local_buffer_ptr = buffer;
915                 local_bytes = bytes;
916                 inline_cmds->new_buffer_ptr = buffer + bytes;
917         }
918
919         inline_cmds->current_ptr = local_buffer_ptr;
920
921         if (local_buffer_ptr[0] == inline_commands_prefix[0]
922             && inline_cmds->lf_found) {
923                 for (jj = 0; jj < NUM_INLINE_COMMANDS; jj++) {
924                         if (inline_commands_prefix[0] != '^') { /* refer inline_cmds.h for usage of ^ */
925                                 strcpy(inline_command_string,
926                                        inline_commands_def[jj].string);
927                                 inline_command_string[strlen
928                                                       (inline_commands_def
929                                                        [jj].string)] =
930                                     '\0';
931                                 inline_command_string[0] =
932                                     inline_commands_prefix[0];
933                                 /* Inline commands are delimited by the inline_commands_prefix[0] (default is ^).
934                                    The inline_commands_def[].string includes a trailing LF */
935                                 inline_command_string[strlen
936                                                       (inline_commands_def
937                                                        [jj].string) - 2] =
938                                     inline_commands_prefix[0];
939                                 ptr = inline_command_string;
940                         } else
941                                 ptr = inline_commands_def[jj].string;
942
943                         l = strlen(ptr);
944                         match_bytes = (local_bytes <= l) ? local_bytes : l;
945                         if (strncmp(ptr, local_buffer_ptr, match_bytes) ==
946                             0) {
947                                 if (match_bytes == (ssize_t) strlen(ptr)) {
948                                         inline_cmds->new_buffer_ptr =
949                                             buffer + match_bytes -
950                                             prev_bytes_copied;
951                                         inline_cmds->cmd_found =
952                                             inline_commands_def[jj].
953                                             command;
954                                         inline_cmds->bytes_copied = 0;  /* reset it */
955                                 } else {
956                                         /* partial command */
957                                         memcpy(&inline_cmds->
958                                                inline_cmd_buffer
959                                                [inline_cmds->bytes_copied],
960                                                buffer, bytes);
961                                         inline_cmds->bytes_copied += bytes;
962                                 }
963                                 return true;
964                         }
965                         /* else - if not a match, do nothing here */
966                 }               /* for */
967         }
968
969         for (ii = prev_bytes_copied; ii < local_bytes; ii++) {
970                 if (ii && local_buffer_ptr[ii] == inline_commands_prefix[0]
971                     && inline_cmds->lf_found) {
972                         /* possible inline command. First, let's flush bytes up to ^ */
973                         inline_cmds->new_buffer_ptr =
974                             buffer + ii - prev_bytes_copied;
975                         inline_cmds->bytes_to_flush = ii;
976                         inline_cmds->lf_found = true;
977
978                         /* bytes to flush starts at inline_cmds->current_ptr */
979                         return true;
980                 } else if (local_buffer_ptr[ii] == '\n') {
981                         inline_cmds->lf_found = true;
982                 } else {
983                         inline_cmds->lf_found = false;
984                 }
985         }                       /* for */
986
987         inline_cmds->bytes_copied = 0;  /* reset it */
988         return false;           /* not an inline command */
989 }
990
991 static
992 int run_inline_command(inline_cmds_st * cmd, socket_st * hd)
993 {
994         switch (cmd->cmd_found) {
995         case INLINE_COMMAND_RESUME:
996                 return try_resume(hd);
997         case INLINE_COMMAND_RENEGOTIATE:
998                 return try_rehandshake(hd);
999         default:
1000                 return -1;
1001         }
1002 }
1003
1004 static
1005 int do_inline_command_processing(char *buffer_ptr, size_t curr_bytes,
1006                                  socket_st * hd,
1007                                  inline_cmds_st * inline_cmds)
1008 {
1009         int skip_bytes, bytes;
1010         bool inline_cmd_start_found;
1011
1012         bytes = curr_bytes;
1013
1014       continue_inline_processing:
1015         /* parse_for_inline_commands_in_buffer hunts for start of an inline command
1016          * sequence. The function maintains state information in inline_cmds. 
1017          */
1018         inline_cmd_start_found =
1019             parse_for_inline_commands_in_buffer(buffer_ptr, bytes,
1020                                                 inline_cmds);
1021         if (!inline_cmd_start_found)
1022                 return bytes;
1023
1024         /* inline_cmd_start_found is set */
1025
1026         if (inline_cmds->bytes_to_flush) {
1027                 /* start of an inline command sequence found, but is not
1028                  * at the beginning of buffer. So, we flush all preceding bytes.
1029                  */
1030                 return inline_cmds->bytes_to_flush;
1031         } else if (inline_cmds->cmd_found == INLINE_COMMAND_NONE) {
1032                 /* partial command found */
1033                 return 0;
1034         } else {
1035                 /* complete inline command found and is at the start */
1036                 if (run_inline_command(inline_cmds, hd))
1037                         return -1;
1038
1039                 inline_cmds->cmd_found = INLINE_COMMAND_NONE;
1040                 skip_bytes = inline_cmds->new_buffer_ptr - buffer_ptr;
1041
1042                 if (skip_bytes >= bytes)
1043                         return 0;
1044                 else {
1045                         buffer_ptr = inline_cmds->new_buffer_ptr;
1046                         bytes -= skip_bytes;
1047                         goto continue_inline_processing;
1048                 }
1049         }
1050 }
1051
1052 static void
1053 print_other_info(gnutls_session_t session)
1054 {
1055         int ret;
1056         gnutls_datum_t oresp;
1057
1058         ret = gnutls_ocsp_status_request_get(session, &oresp);
1059         if (ret < 0) {
1060                 oresp.data = NULL;
1061                 oresp.size = 0;
1062         }
1063
1064         if (ENABLED_OPT(VERBOSE) && oresp.data) {
1065                 gnutls_ocsp_resp_t r;
1066                 gnutls_datum_t p;
1067                 unsigned flag;
1068
1069                 ret = gnutls_ocsp_resp_init(&r);
1070                 if (ret < 0) {
1071                         fprintf(stderr, "ocsp_resp_init: %s\n",
1072                                 gnutls_strerror(ret));
1073                         return;
1074                 }
1075
1076                 ret = gnutls_ocsp_resp_import(r, &oresp);
1077                 if (ret < 0) {
1078                         fprintf(stderr, "importing response: %s\n",
1079                                 gnutls_strerror(ret));
1080                         return;
1081                 }
1082
1083                 if (print_cert != 0)
1084                         flag = GNUTLS_OCSP_PRINT_FULL;
1085                 else
1086                         flag = GNUTLS_OCSP_PRINT_COMPACT;
1087                 ret =
1088                     gnutls_ocsp_resp_print(r, flag, &p);
1089                 gnutls_ocsp_resp_deinit(r);
1090                 fputs((char*)p.data, stdout);
1091         }
1092
1093         if (HAVE_OPT(SAVE_OCSP) && oresp.data) {
1094                 FILE *fp = fopen(OPT_ARG(SAVE_OCSP), "w");
1095
1096                 if (fp != NULL) {
1097                         fwrite(oresp.data, 1, oresp.size, fp);
1098                         fclose(fp);
1099                 }
1100         }
1101 }
1102
1103 int main(int argc, char **argv)
1104 {
1105         int ret;
1106         int ii, inp;
1107         char buffer[MAX_BUF + 1];
1108         int user_term = 0, retval = 0;
1109         socket_st hd;
1110         ssize_t bytes, keyboard_bytes;
1111         char *keyboard_buffer_ptr;
1112         inline_cmds_st inline_cmds;
1113 #ifndef _WIN32
1114         struct sigaction new_action;
1115 #endif
1116
1117         cmd_parser(argc, argv);
1118
1119         gnutls_global_set_log_function(tls_log_func);
1120         gnutls_global_set_log_level(OPT_VALUE_DEBUG);
1121
1122         if ((ret = gnutls_global_init()) < 0) {
1123                 fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret));
1124                 exit(1);
1125         }
1126
1127         if (hostname == NULL) {
1128                 fprintf(stderr, "No hostname given\n");
1129                 exit(1);
1130         }
1131
1132         sockets_init();
1133
1134         init_global_tls_stuff();
1135
1136         socket_open(&hd, hostname, service, udp, CONNECT_MSG);
1137         hd.verbose = verbose;
1138
1139         if (HAVE_OPT(STARTTLS_PROTO))
1140                 socket_starttls(&hd, OPT_ARG(STARTTLS_PROTO));
1141
1142         hd.session = init_tls_session(hostname);
1143         if (starttls)
1144                 goto after_handshake;
1145
1146         ret = do_handshake(&hd);
1147
1148         if (ret < 0) {
1149                 fprintf(stderr, "*** Handshake has failed\n");
1150                 gnutls_perror(ret);
1151                 gnutls_deinit(hd.session);
1152                 return 1;
1153         } else
1154                 printf("- Handshake was completed\n");
1155
1156         if (resume != 0)
1157                 if (try_resume(&hd))
1158                         return 1;
1159
1160         print_other_info(hd.session);
1161
1162       after_handshake:
1163
1164         /* Warning!  Do not touch this text string, it is used by external
1165            programs to search for when gnutls-cli has reached this point. */
1166         printf("\n- Simple Client Mode:\n\n");
1167
1168         if (rehandshake)
1169                 if (try_rehandshake(&hd))
1170                         return 1;
1171
1172 #ifndef _WIN32
1173         new_action.sa_handler = starttls_alarm;
1174         sigemptyset(&new_action.sa_mask);
1175         new_action.sa_flags = 0;
1176
1177         sigaction(SIGALRM, &new_action, NULL);
1178 #endif
1179
1180         fflush(stdout);
1181         fflush(stderr);
1182
1183         /* do not buffer */
1184 #ifndef _WIN32
1185         setbuf(stdin, NULL);
1186 #endif
1187         setbuf(stdout, NULL);
1188         setbuf(stderr, NULL);
1189
1190         if (inline_commands) {
1191                 memset(&inline_cmds, 0, sizeof(inline_cmds_st));
1192                 inline_cmds.lf_found = true;    /* initially, at start of line */
1193         }
1194
1195         for (;;) {
1196                 if (starttls_alarmed && !hd.secure) {
1197                         /* Warning!  Do not touch this text string, it is used by
1198                            external programs to search for when gnutls-cli has
1199                            reached this point. */
1200                         fprintf(stderr, "*** Starting TLS handshake\n");
1201                         ret = do_handshake(&hd);
1202                         if (ret < 0) {
1203                                 fprintf(stderr,
1204                                         "*** Handshake has failed\n");
1205                                 user_term = 1;
1206                                 retval = 1;
1207                                 break;
1208                         }
1209                 }
1210
1211                 inp = check_net_or_keyboard_input(&hd);
1212
1213                 if (inp == IN_NET) {
1214                         memset(buffer, 0, MAX_BUF + 1);
1215                         ret = socket_recv(&hd, buffer, MAX_BUF);
1216
1217                         if (ret == 0) {
1218                                 printf
1219                                     ("- Peer has closed the GnuTLS connection\n");
1220                                 break;
1221                         } else if (handle_error(&hd, ret) < 0
1222                                    && user_term == 0) {
1223                                 fprintf(stderr,
1224                                         "*** Server has terminated the connection abnormally.\n");
1225                                 retval = 1;
1226                                 break;
1227                         } else if (ret > 0) {
1228                                 if (verbose != 0)
1229                                         printf("- Received[%d]: ", ret);
1230                                 for (ii = 0; ii < ret; ii++) {
1231                                         fputc(buffer[ii], stdout);
1232                                 }
1233                                 fflush(stdout);
1234                         }
1235
1236                         if (user_term != 0)
1237                                 break;
1238                 }
1239
1240                 if (inp == IN_KEYBOARD) {
1241                         if ((bytes =
1242                              read(fileno(stdin), buffer,
1243                                   MAX_BUF - 1)) <= 0) {
1244                                 if (hd.secure == 0) {
1245                                         /* Warning!  Do not touch this text string, it is
1246                                            used by external programs to search for when
1247                                            gnutls-cli has reached this point. */
1248                                         fprintf(stderr,
1249                                                 "*** Starting TLS handshake\n");
1250                                         ret = do_handshake(&hd);
1251                                         clearerr(stdin);
1252                                         if (ret < 0) {
1253                                                 fprintf(stderr,
1254                                                         "*** Handshake has failed\n");
1255                                                 user_term = 1;
1256                                                 retval = 1;
1257                                                 break;
1258                                         }
1259                                 } else {
1260                                         user_term = 1;
1261                                         break;
1262                                 }
1263                                 continue;
1264                         }
1265
1266                         buffer[bytes] = 0;
1267                         if (crlf != 0) {
1268                                 char *b = strchr(buffer, '\n');
1269                                 if (b != NULL) {
1270                                         strcpy(b, "\r\n");
1271                                         bytes++;
1272                                 }
1273                         }
1274
1275                         keyboard_bytes = bytes;
1276                         keyboard_buffer_ptr = buffer;
1277
1278                       inline_command_processing:
1279
1280                         if (inline_commands) {
1281                                 keyboard_bytes =
1282                                     do_inline_command_processing
1283                                     (keyboard_buffer_ptr, keyboard_bytes,
1284                                      &hd, &inline_cmds);
1285                                 if (keyboard_bytes == 0)
1286                                         continue;
1287                                 else if (keyboard_bytes < 0) {  /* error processing an inline command */
1288                                         retval = 1;
1289                                         break;
1290                                 } else {
1291                                         /* current_ptr could point to either an inline_cmd_buffer
1292                                          * or may point to start or an offset into buffer.
1293                                          */
1294                                         keyboard_buffer_ptr =
1295                                             inline_cmds.current_ptr;
1296                                 }
1297                         }
1298
1299                         if (ranges
1300                             && gnutls_record_can_use_length_hiding(hd.
1301                                                                    session))
1302                         {
1303                                 gnutls_range_st range;
1304                                 range.low = 0;
1305                                 range.high = MAX_BUF;
1306                                 ret =
1307                                     socket_send_range(&hd,
1308                                                       keyboard_buffer_ptr,
1309                                                       keyboard_bytes,
1310                                                       &range);
1311                         } else {
1312                                 ret =
1313                                     socket_send(&hd, keyboard_buffer_ptr,
1314                                                 keyboard_bytes);
1315                         }
1316
1317                         if (ret > 0) {
1318                                 if (verbose != 0)
1319                                         printf("- Sent: %d bytes\n", ret);
1320                         } else
1321                                 handle_error(&hd, ret);
1322
1323                         if (inline_commands &&
1324                             inline_cmds.new_buffer_ptr < (buffer + bytes))
1325                         {
1326                                 keyboard_buffer_ptr =
1327                                     inline_cmds.new_buffer_ptr;
1328                                 keyboard_bytes =
1329                                     (buffer + bytes) - keyboard_buffer_ptr;
1330                                 goto inline_command_processing;
1331                         }
1332                 }
1333         }
1334
1335         if (user_term != 0)
1336                 socket_bye(&hd);
1337         else
1338                 gnutls_deinit(hd.session);
1339
1340 #ifdef ENABLE_SRP
1341         if (srp_cred)
1342                 gnutls_srp_free_client_credentials(srp_cred);
1343 #endif
1344 #ifdef ENABLE_PSK
1345         if (psk_cred)
1346                 gnutls_psk_free_client_credentials(psk_cred);
1347 #endif
1348
1349         gnutls_certificate_free_credentials(xcred);
1350
1351 #ifdef ENABLE_ANON
1352         gnutls_anon_free_client_credentials(anon_cred);
1353 #endif
1354
1355         gnutls_global_deinit();
1356
1357         return retval;
1358 }
1359
1360 static
1361 void print_priority_list(void)
1362 {
1363         unsigned int idx;
1364         const char *str;
1365         unsigned int lineb = 0;
1366
1367         printf("Priority strings in GnuTLS %s:\n", gnutls_check_version(NULL));
1368
1369         fputs("\t", stdout);
1370         for (idx=0;;idx++) {
1371                 str = gnutls_priority_string_list(idx, GNUTLS_PRIORITY_LIST_INIT_KEYWORDS);
1372                 if (str == NULL)
1373                         break;
1374                 lineb += printf("%s ", str);
1375                 if (lineb > 64) {
1376                         lineb = 0;
1377                         printf("\n\t");
1378                 }
1379         }
1380
1381         printf("\n\nSpecial strings:\n");
1382         lineb = 0;
1383         fputs("\t", stdout);
1384         for (idx=0;;idx++) {
1385                 str = gnutls_priority_string_list(idx, GNUTLS_PRIORITY_LIST_SPECIAL);
1386                 if (str == NULL)
1387                         break;
1388                 if (str[0] == 0)
1389                         continue;
1390                 lineb += printf("%%%s ", str);
1391                 if (lineb > 64) {
1392                         lineb = 0;
1393                         printf("\n\t");
1394                 }
1395         }
1396         printf("\n");
1397
1398         return;
1399 }
1400
1401 static void cmd_parser(int argc, char **argv)
1402 {
1403         const char *rest = NULL;
1404
1405         int optct = optionProcess(&gnutls_cliOptions, argc, argv);
1406         argc -= optct;
1407         argv += optct;
1408
1409         if (rest == NULL && argc > 0)
1410                 rest = argv[0];
1411
1412
1413         if (HAVE_OPT(FIPS140_MODE)) {
1414                 if (gnutls_fips140_mode_enabled() != 0) {
1415                         fprintf(stderr, "library is in FIPS140-2 mode\n");
1416                         exit(0);
1417                 }
1418                 fprintf(stderr, "library is NOT in FIPS140-2 mode\n");
1419                 exit(1);
1420         }
1421
1422         if (HAVE_OPT(BENCHMARK_CIPHERS)) {
1423                 benchmark_cipher(OPT_VALUE_DEBUG);
1424                 exit(0);
1425         }
1426
1427         if (HAVE_OPT(BENCHMARK_TLS_CIPHERS)) {
1428                 benchmark_tls(OPT_VALUE_DEBUG, 1);
1429                 exit(0);
1430         }
1431
1432         if (HAVE_OPT(BENCHMARK_TLS_KX)) {
1433                 benchmark_tls(OPT_VALUE_DEBUG, 0);
1434                 exit(0);
1435         }
1436
1437         if (HAVE_OPT(PRIORITY)) {
1438                 priorities = OPT_ARG(PRIORITY);
1439         }
1440         verbose = HAVE_OPT(VERBOSE);
1441         if (verbose)
1442                 print_cert = 1;
1443         else
1444                 print_cert = HAVE_OPT(PRINT_CERT);
1445
1446         if (HAVE_OPT(LIST)) {
1447                 print_list(priorities, verbose);
1448                 exit(0);
1449         }
1450
1451         if (HAVE_OPT(PRIORITY_LIST)) {
1452                 print_priority_list();
1453                 exit(0);
1454         }
1455
1456         disable_sni = HAVE_OPT(DISABLE_SNI);
1457         disable_extensions = HAVE_OPT(DISABLE_EXTENSIONS);
1458         if (disable_extensions)
1459                 init_flags |= GNUTLS_NO_EXTENSIONS;
1460
1461         inline_commands = HAVE_OPT(INLINE_COMMANDS);
1462         if (HAVE_OPT(INLINE_COMMANDS_PREFIX)) {
1463                 if (strlen(OPT_ARG(INLINE_COMMANDS_PREFIX)) > 1) {
1464                         fprintf(stderr,
1465                                 "inline-commands-prefix value is a single US-ASCII character (octets 0 - 127)\n");
1466                         exit(1);
1467                 }
1468                 inline_commands_prefix =
1469                     (char *) OPT_ARG(INLINE_COMMANDS_PREFIX);
1470                 if (!isascii(inline_commands_prefix[0])) {
1471                         fprintf(stderr,
1472                                 "inline-commands-prefix value is a single US-ASCII character (octets 0 - 127)\n");
1473                         exit(1);
1474                 }
1475         } else
1476                 inline_commands_prefix = "^";
1477
1478         starttls = HAVE_OPT(STARTTLS);
1479         resume = HAVE_OPT(RESUME);
1480         rehandshake = HAVE_OPT(REHANDSHAKE);
1481         insecure = HAVE_OPT(INSECURE);
1482         ranges = HAVE_OPT(RANGES);
1483
1484         udp = HAVE_OPT(UDP);
1485         mtu = OPT_VALUE_MTU;
1486
1487         if (HAVE_OPT(PORT)) {
1488                 service = OPT_ARG(PORT);
1489         } else {
1490                 service = "443";
1491         }
1492
1493         record_max_size = OPT_VALUE_RECORDSIZE;
1494
1495         fingerprint = HAVE_OPT(FINGERPRINT);
1496
1497         if (HAVE_OPT(X509FMTDER))
1498                 x509ctype = GNUTLS_X509_FMT_DER;
1499         else
1500                 x509ctype = GNUTLS_X509_FMT_PEM;
1501
1502         if (HAVE_OPT(SRPUSERNAME))
1503                 srp_username = OPT_ARG(SRPUSERNAME);
1504
1505         if (HAVE_OPT(SRPPASSWD))
1506                 srp_passwd = OPT_ARG(SRPPASSWD);
1507
1508         if (HAVE_OPT(X509CAFILE))
1509                 x509_cafile = OPT_ARG(X509CAFILE);
1510
1511         if (HAVE_OPT(X509CRLFILE))
1512                 x509_crlfile = OPT_ARG(X509CRLFILE);
1513
1514         if (HAVE_OPT(X509KEYFILE))
1515                 x509_keyfile = OPT_ARG(X509KEYFILE);
1516
1517         if (HAVE_OPT(X509CERTFILE))
1518                 x509_certfile = OPT_ARG(X509CERTFILE);
1519
1520         if (HAVE_OPT(PGPKEYFILE))
1521                 pgp_keyfile = OPT_ARG(PGPKEYFILE);
1522
1523         if (HAVE_OPT(PGPCERTFILE))
1524                 pgp_certfile = OPT_ARG(PGPCERTFILE);
1525
1526         if (HAVE_OPT(PSKUSERNAME))
1527                 psk_username = OPT_ARG(PSKUSERNAME);
1528
1529         if (HAVE_OPT(PSKKEY)) {
1530                 psk_key.data = (unsigned char *) OPT_ARG(PSKKEY);
1531                 psk_key.size = strlen(OPT_ARG(PSKKEY));
1532         } else
1533                 psk_key.size = 0;
1534
1535         if (HAVE_OPT(PGPKEYRING))
1536                 pgp_keyring = OPT_ARG(PGPKEYRING);
1537
1538         crlf = HAVE_OPT(CRLF);
1539
1540         if (rest != NULL)
1541                 hostname = rest;
1542
1543         if (hostname == NULL) {
1544                 fprintf(stderr, "No hostname specified\n");
1545                 exit(1);
1546         }
1547 }
1548
1549 static void check_rehandshake(socket_st * socket, int ret)
1550 {
1551         if (socket->secure && ret == GNUTLS_E_REHANDSHAKE) {
1552                 /* There is a race condition here. If application
1553                  * data is sent after the rehandshake request,
1554                  * the server thinks we ignored his request.
1555                  * This is a bad design of this client.
1556                  */
1557                 printf("*** Received rehandshake request\n");
1558                 /* gnutls_alert_send( session, GNUTLS_AL_WARNING, GNUTLS_A_NO_RENEGOTIATION); */
1559
1560                 ret = do_handshake(socket);
1561
1562                 if (ret == 0) {
1563                         printf("*** Rehandshake was performed.\n");
1564                 } else {
1565                         printf("*** Rehandshake Failed.\n");
1566                 }
1567         }
1568 }
1569
1570
1571 static int do_handshake(socket_st * socket)
1572 {
1573         int ret;
1574
1575         gnutls_transport_set_int(socket->session, socket->fd);
1576         set_read_funcs(socket->session);
1577
1578         do {
1579                 gnutls_handshake_set_timeout(socket->session,
1580                                              GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
1581                 ret = gnutls_handshake(socket->session);
1582
1583                 if (ret < 0) {
1584                         handle_error(socket, ret);
1585                 }
1586         }
1587         while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
1588
1589         if (ret == 0) {
1590                 /* print some information */
1591                 print_info(socket->session, verbose, 0);
1592                 socket->secure = 1;
1593         } else {
1594                 gnutls_alert_send_appropriate(socket->session, ret);
1595                 shutdown(socket->fd, SHUT_RDWR);
1596         }
1597         return ret;
1598 }
1599
1600 static int
1601 srp_username_callback(gnutls_session_t session,
1602                       char **username, char **password)
1603 {
1604         if (srp_username == NULL || srp_passwd == NULL) {
1605                 return -1;
1606         }
1607
1608         *username = gnutls_strdup(srp_username);
1609         *password = gnutls_strdup(srp_passwd);
1610
1611         return 0;
1612 }
1613
1614 static int
1615 psk_callback(gnutls_session_t session, char **username,
1616              gnutls_datum_t * key)
1617 {
1618         const char *hint = gnutls_psk_client_get_hint(session);
1619         char *rawkey;
1620         char *passwd;
1621         int ret;
1622         size_t res_size;
1623         gnutls_datum_t tmp;
1624
1625         printf("- PSK client callback. ");
1626         if (hint)
1627                 printf("PSK hint '%s'\n", hint);
1628         else
1629                 printf("No PSK hint\n");
1630
1631         if (HAVE_OPT(PSKUSERNAME))
1632                 *username = gnutls_strdup(OPT_ARG(PSKUSERNAME));
1633         else {
1634                 char *p = NULL;
1635                 size_t n;
1636
1637                 printf("Enter PSK identity: ");
1638                 fflush(stdout);
1639                 getline(&p, &n, stdin);
1640
1641                 if (p == NULL) {
1642                         fprintf(stderr,
1643                                 "No username given, aborting...\n");
1644                         return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1645                 }
1646
1647                 if (p[strlen(p) - 1] == '\n')
1648                         p[strlen(p) - 1] = '\0';
1649                 if (p[strlen(p) - 1] == '\r')
1650                         p[strlen(p) - 1] = '\0';
1651
1652                 *username = gnutls_strdup(p);
1653                 free(p);
1654         }
1655         if (!*username)
1656                 return GNUTLS_E_MEMORY_ERROR;
1657
1658         passwd = getpass("Enter key: ");
1659         if (passwd == NULL) {
1660                 fprintf(stderr, "No key given, aborting...\n");
1661                 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1662         }
1663
1664         tmp.data = (void *) passwd;
1665         tmp.size = strlen(passwd);
1666
1667         res_size = tmp.size / 2 + 1;
1668         rawkey = gnutls_malloc(res_size);
1669         if (rawkey == NULL)
1670                 return GNUTLS_E_MEMORY_ERROR;
1671
1672         ret = gnutls_hex_decode(&tmp, rawkey, &res_size);
1673         if (ret < 0) {
1674                 fprintf(stderr, "Error deriving password: %s\n",
1675                         gnutls_strerror(ret));
1676                 gnutls_free(*username);
1677                 return ret;
1678         }
1679
1680         key->data = (void *) rawkey;
1681         key->size = res_size;
1682
1683         if (HAVE_OPT(DEBUG)) {
1684                 char hexkey[41];
1685                 res_size = sizeof(hexkey);
1686                 gnutls_hex_encode(key, hexkey, &res_size);
1687                 fprintf(stderr, "PSK username: %s\n", *username);
1688                 fprintf(stderr, "PSK hint: %s\n", hint);
1689                 fprintf(stderr, "PSK key: %s\n", hexkey);
1690         }
1691
1692         return 0;
1693 }
1694
1695 static void init_global_tls_stuff(void)
1696 {
1697         int ret;
1698
1699 #ifdef ENABLE_PKCS11
1700         if (HAVE_OPT(PROVIDER)) {
1701                 ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
1702                 if (ret < 0)
1703                         fprintf(stderr, "pkcs11_init: %s",
1704                                 gnutls_strerror(ret));
1705                 else {
1706                         ret =
1707                             gnutls_pkcs11_add_provider(OPT_ARG(PROVIDER),
1708                                                        NULL);
1709                         if (ret < 0) {
1710                                 fprintf(stderr, "pkcs11_add_provider: %s",
1711                                         gnutls_strerror(ret));
1712                                 exit(1);
1713                         }
1714                 }
1715         }
1716 #endif
1717
1718         /* X509 stuff */
1719         if (gnutls_certificate_allocate_credentials(&xcred) < 0) {
1720                 fprintf(stderr, "Certificate allocation memory error\n");
1721                 exit(1);
1722         }
1723         gnutls_certificate_set_pin_function(xcred, pin_callback, NULL);
1724
1725         if (x509_cafile != NULL) {
1726                 ret = gnutls_certificate_set_x509_trust_file(xcred,
1727                                                              x509_cafile,
1728                                                              x509ctype);
1729         } else {
1730                 if (insecure == 0) {
1731                         ret = gnutls_certificate_set_x509_system_trust(xcred);
1732                 } else {
1733                         ret = 0;
1734                 }
1735         }
1736         if (ret < 0) {
1737                 fprintf(stderr, "Error setting the x509 trust file\n");
1738         } else {
1739                 printf("Processed %d CA certificate(s).\n", ret);
1740         }
1741
1742         if (x509_crlfile != NULL) {
1743                 ret =
1744                     gnutls_certificate_set_x509_crl_file(xcred,
1745                                                          x509_crlfile,
1746                                                          x509ctype);
1747                 if (ret < 0) {
1748                         fprintf(stderr,
1749                                 "Error setting the x509 CRL file\n");
1750                 } else {
1751                         printf("Processed %d CRL(s).\n", ret);
1752                 }
1753         }
1754
1755         load_keys();
1756
1757 #ifdef ENABLE_OPENPGP
1758         if (pgp_keyring != NULL) {
1759                 ret =
1760                     gnutls_certificate_set_openpgp_keyring_file(xcred,
1761                                                                 pgp_keyring,
1762                                                                 GNUTLS_OPENPGP_FMT_BASE64);
1763                 if (ret < 0) {
1764                         fprintf(stderr,
1765                                 "Error setting the OpenPGP keyring file\n");
1766                 }
1767         }
1768 #endif
1769
1770 #ifdef ENABLE_SRP
1771         if (srp_username && srp_passwd) {
1772                 /* SRP stuff */
1773                 if (gnutls_srp_allocate_client_credentials(&srp_cred) < 0) {
1774                         fprintf(stderr, "SRP authentication error\n");
1775                 }
1776
1777                 gnutls_srp_set_client_credentials_function(srp_cred,
1778                                                            srp_username_callback);
1779         }
1780 #endif
1781
1782 #ifdef ENABLE_PSK
1783         /* PSK stuff */
1784         if (gnutls_psk_allocate_client_credentials(&psk_cred) < 0) {
1785                 fprintf(stderr, "PSK authentication error\n");
1786         }
1787
1788         if (psk_username && psk_key.data) {
1789                 ret = gnutls_psk_set_client_credentials(psk_cred,
1790                                                         psk_username,
1791                                                         &psk_key,
1792                                                         GNUTLS_PSK_KEY_HEX);
1793                 if (ret < 0) {
1794                         fprintf(stderr,
1795                                 "Error setting the PSK credentials: %s\n",
1796                                 gnutls_strerror(ret));
1797                 }
1798         } else
1799                 gnutls_psk_set_client_credentials_function(psk_cred,
1800                                                            psk_callback);
1801 #endif
1802
1803 #ifdef ENABLE_ANON
1804         /* ANON stuff */
1805         if (gnutls_anon_allocate_client_credentials(&anon_cred) < 0) {
1806                 fprintf(stderr, "Anonymous authentication error\n");
1807         }
1808 #endif
1809
1810 }
1811
1812 /* OCSP check for the peer's certificate. Should be called 
1813  * only after the certificate list verification is complete.
1814  * Returns:
1815  * -1: certificate chain could not be checked fully
1816  * >=0: number of certificates verified ok
1817  */
1818 static int cert_verify_ocsp(gnutls_session_t session)
1819 {
1820         gnutls_x509_crt_t cert, issuer;
1821         const gnutls_datum_t *cert_list;
1822         unsigned int cert_list_size = 0, ok = 0;
1823         int deinit_issuer = 0, deinit_cert;
1824         gnutls_datum_t resp;
1825         unsigned char noncebuf[23];
1826         gnutls_datum_t nonce = { noncebuf, sizeof(noncebuf) };
1827         int ret;
1828         unsigned it;
1829
1830         cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
1831         if (cert_list_size == 0) {
1832                 fprintf(stderr, "No certificates found!\n");
1833                 return 0;
1834         }
1835
1836         for (it = 0; it < cert_list_size; it++) {
1837                 gnutls_x509_crt_init(&cert);
1838                 if (deinit_cert)
1839                         gnutls_x509_crt_deinit(cert);
1840                 gnutls_x509_crt_init(&cert);
1841                 deinit_cert = 1;
1842                 ret = gnutls_x509_crt_import(cert, &cert_list[it], GNUTLS_X509_FMT_DER);
1843                 if (ret < 0) {
1844                         fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
1845                         goto cleanup;
1846                 }
1847
1848                 if (deinit_issuer) {
1849                         gnutls_x509_crt_deinit(issuer);
1850                         deinit_issuer = 0;
1851                 }
1852
1853                 ret = gnutls_certificate_get_issuer(xcred, cert, &issuer, 0);
1854                 if (ret < 0 && cert_list_size - it > 1) {
1855                         gnutls_x509_crt_init(&issuer);
1856                         deinit_issuer = 1;
1857                         ret = gnutls_x509_crt_import(issuer, &cert_list[it + 1], GNUTLS_X509_FMT_DER);
1858                         if (ret < 0) {
1859                                 fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
1860                                 goto cleanup;
1861                         }
1862                 } else if (ret < 0) {
1863                         fprintf(stderr, "Cannot find issuer\n");
1864                         goto cleanup;
1865                 }
1866
1867                 ret = gnutls_rnd(GNUTLS_RND_NONCE, nonce.data, nonce.size);
1868                 if (ret < 0) {
1869                         fprintf(stderr, "gnutls_rnd: %s", gnutls_strerror(ret));
1870                         goto cleanup;
1871                 }
1872
1873                 ret = send_ocsp_request(NULL, cert, issuer, &resp, &nonce);
1874                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1875                         continue;
1876                 }
1877                 if (ret < 0) {
1878                         fprintf(stderr, "Cannot contact OCSP server\n");
1879                         goto cleanup;
1880                 }
1881
1882                 /* verify and check the response for revoked cert */
1883                 ret = check_ocsp_response(cert, issuer, &resp, &nonce, verbose);
1884                 if (ret == 1)
1885                         ok++;
1886                 else
1887                         break;
1888         }
1889
1890 cleanup:
1891         if (deinit_issuer)
1892                 gnutls_x509_crt_deinit(issuer);
1893         if (deinit_cert)
1894                 gnutls_x509_crt_deinit(cert);
1895
1896         return ok > 1 ? (int) ok : -1;
1897 }