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