2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3 * Author: Nikos Mavrogiannopoulos
5 * This file is part of GnuTLS.
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.
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.
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/>.
23 /* Work around problem reported in
24 <http://permalink.gmane.org/gmane.comp.lib.gnulib.bugs/15755>.*/
25 #if GETTIMEOFDAY_CLOBBERS_LOCALTIME
34 #include <gnutls/gnutls.h>
35 #include <gnutls/x509.h>
36 #include <gnutls/openpgp.h>
37 #include <gnutls/crypto.h>
42 # include <gnutls/pkcs11.h>
45 #define SU(x) (x!=NULL?x:"Unknown")
47 const char str_unknown
[] = "(unknown)";
49 /* Hex encodes the given data.
52 raw_to_string (const unsigned char *raw
, size_t raw_size
)
54 static char buf
[1024];
59 if (raw_size
* 3 + 1 >= sizeof (buf
))
62 for (i
= 0; i
< raw_size
; i
++)
64 sprintf (&(buf
[i
* 3]), "%02X%s", raw
[i
],
65 (i
== raw_size
- 1) ? "" : ":");
67 buf
[sizeof (buf
) - 1] = '\0';
73 print_x509_info_compact (gnutls_session_t session
)
75 gnutls_x509_crt_t crt
;
76 const gnutls_datum_t
*cert_list
;
77 unsigned int cert_list_size
= 0;
81 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
82 if (cert_list_size
== 0)
84 fprintf (stderr
, "No certificates found!\n");
88 gnutls_x509_crt_init (&crt
);
90 gnutls_x509_crt_import (crt
, &cert_list
[0],
94 fprintf (stderr
, "Decoding error: %s\n",
95 gnutls_strerror (ret
));
100 gnutls_x509_crt_print (crt
, GNUTLS_CRT_PRINT_COMPACT
, &cinfo
);
103 printf ("- X.509 cert: %s\n", cinfo
.data
);
104 gnutls_free (cinfo
.data
);
107 gnutls_x509_crt_deinit (crt
);
111 print_x509_info (gnutls_session_t session
, int flag
, int print_cert
)
113 gnutls_x509_crt_t crt
;
114 const gnutls_datum_t
*cert_list
;
115 unsigned int cert_list_size
= 0, j
;
118 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
119 if (cert_list_size
== 0)
121 fprintf (stderr
, "No certificates found!\n");
125 printf ("- Certificate type: X.509\n");
126 printf ("- Got a certificate list of %d certificates.\n",
129 for (j
= 0; j
< cert_list_size
; j
++)
131 gnutls_datum_t cinfo
;
133 gnutls_x509_crt_init (&crt
);
135 gnutls_x509_crt_import (crt
, &cert_list
[j
],
136 GNUTLS_X509_FMT_DER
);
139 fprintf (stderr
, "Decoding error: %s\n",
140 gnutls_strerror (ret
));
144 printf ("- Certificate[%d] info:\n - ", j
);
145 if (flag
== GNUTLS_CRT_PRINT_COMPACT
&& j
> 0) flag
= GNUTLS_CRT_PRINT_ONELINE
;
148 gnutls_x509_crt_print (crt
, flag
, &cinfo
);
151 printf ("%s\n", cinfo
.data
);
152 gnutls_free (cinfo
.data
);
161 gnutls_x509_crt_export (crt
, GNUTLS_X509_FMT_PEM
, p
,
163 if (ret
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
168 fprintf (stderr
, "gnutls_malloc\n");
173 gnutls_x509_crt_export (crt
, GNUTLS_X509_FMT_PEM
,
178 fprintf (stderr
, "Encoding error: %s\n",
179 gnutls_strerror (ret
));
184 fputs ("\n", stdout
);
186 fputs ("\n", stdout
);
191 gnutls_x509_crt_deinit (crt
);
195 #ifdef ENABLE_OPENPGP
197 print_openpgp_info_compact (gnutls_session_t session
)
200 gnutls_openpgp_crt_t crt
;
201 const gnutls_datum_t
*cert_list
;
202 unsigned int cert_list_size
= 0;
205 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
207 if (cert_list_size
> 0)
209 gnutls_datum_t cinfo
;
211 gnutls_openpgp_crt_init (&crt
);
212 ret
= gnutls_openpgp_crt_import (crt
, &cert_list
[0],
213 GNUTLS_OPENPGP_FMT_RAW
);
216 fprintf (stderr
, "Decoding error: %s\n",
217 gnutls_strerror (ret
));
222 gnutls_openpgp_crt_print (crt
, GNUTLS_CRT_PRINT_COMPACT
, &cinfo
);
225 printf ("- OpenPGP cert: %s\n", cinfo
.data
);
226 gnutls_free (cinfo
.data
);
229 gnutls_openpgp_crt_deinit (crt
);
234 print_openpgp_info (gnutls_session_t session
, int flag
, int print_cert
)
237 gnutls_openpgp_crt_t crt
;
238 const gnutls_datum_t
*cert_list
;
239 unsigned int cert_list_size
= 0;
242 printf ("- Certificate type: OpenPGP\n");
244 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
246 if (cert_list_size
> 0)
248 gnutls_datum_t cinfo
;
250 gnutls_openpgp_crt_init (&crt
);
251 ret
= gnutls_openpgp_crt_import (crt
, &cert_list
[0],
252 GNUTLS_OPENPGP_FMT_RAW
);
255 fprintf (stderr
, "Decoding error: %s\n",
256 gnutls_strerror (ret
));
261 gnutls_openpgp_crt_print (crt
, flag
, &cinfo
);
264 printf ("- %s\n", cinfo
.data
);
265 gnutls_free (cinfo
.data
);
274 gnutls_openpgp_crt_export (crt
,
275 GNUTLS_OPENPGP_FMT_BASE64
,
277 if (ret
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
282 fprintf (stderr
, "gnutls_malloc\n");
287 gnutls_openpgp_crt_export (crt
,
288 GNUTLS_OPENPGP_FMT_BASE64
,
293 fprintf (stderr
, "Encoding error: %s\n",
294 gnutls_strerror (ret
));
299 fputs ("\n", stdout
);
304 gnutls_openpgp_crt_deinit (crt
);
310 /* returns false (0) if not verified, or true (1) otherwise
313 cert_verify (gnutls_session_t session
, const char* hostname
)
316 unsigned int status
= 0;
320 rc
= gnutls_certificate_verify_peers3 (session
, hostname
, &status
);
321 if (rc
== GNUTLS_E_NO_CERTIFICATE_FOUND
)
323 printf ("- Peer did not send any certificate.\n");
329 printf ("- Could not verify certificate (err: %s)\n",
330 gnutls_strerror (rc
));
334 type
= gnutls_certificate_type_get (session
);
335 rc
= gnutls_certificate_verification_status_print( status
, type
, &out
, 0);
338 printf ("- Could not print verification flags (err: %s)\n",
339 gnutls_strerror (rc
));
343 printf ("- %s", out
.data
);
345 gnutls_free(out
.data
);
354 print_dh_info (gnutls_session_t session
, const char *str
, int print
)
356 printf ("- %sDiffie-Hellman parameters\n", str
);
357 printf (" - Using prime: %d bits\n",
358 gnutls_dh_get_prime_bits (session
));
359 printf (" - Secret key: %d bits\n",
360 gnutls_dh_get_secret_bits (session
));
361 printf (" - Peer's public key: %d bits\n",
362 gnutls_dh_get_peers_public_bits (session
));
367 gnutls_datum_t raw_gen
= { NULL
, 0 };
368 gnutls_datum_t raw_prime
= { NULL
, 0 };
369 gnutls_dh_params_t dh_params
= NULL
;
370 unsigned char *params_data
= NULL
;
371 size_t params_data_size
= 0;
373 ret
= gnutls_dh_get_group (session
, &raw_gen
, &raw_prime
);
376 fprintf (stderr
, "gnutls_dh_get_group %d\n", ret
);
380 ret
= gnutls_dh_params_init (&dh_params
);
383 fprintf (stderr
, "gnutls_dh_params_init %d\n", ret
);
388 gnutls_dh_params_import_raw (dh_params
, &raw_prime
,
392 fprintf (stderr
, "gnutls_dh_params_import_raw %d\n", ret
);
396 ret
= gnutls_dh_params_export_pkcs3 (dh_params
,
400 if (ret
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
402 fprintf (stderr
, "gnutls_dh_params_export_pkcs3 %d\n",
407 params_data
= gnutls_malloc (params_data_size
);
410 fprintf (stderr
, "gnutls_malloc %d\n", ret
);
414 ret
= gnutls_dh_params_export_pkcs3 (dh_params
,
420 fprintf (stderr
, "gnutls_dh_params_export_pkcs3-2 %d\n",
425 printf (" - PKCS#3 format:\n\n%.*s\n", (int) params_data_size
,
429 gnutls_free (params_data
);
430 gnutls_free (raw_prime
.data
);
431 gnutls_free (raw_gen
.data
);
432 gnutls_dh_params_deinit (dh_params
);
437 print_ecdh_info (gnutls_session_t session
, const char *str
)
441 printf ("- %sEC Diffie-Hellman parameters\n", str
);
443 curve
= gnutls_ecc_curve_get (session
);
445 printf (" - Using curve: %s\n", gnutls_ecc_curve_get_name (curve
));
446 printf (" - Curve size: %d bits\n",
447 gnutls_ecc_curve_get_size (curve
) * 8);
452 print_info (gnutls_session_t session
, int verbose
, int print_cert
)
455 gnutls_credentials_type_t cred
;
456 gnutls_kx_algorithm_t kx
;
457 unsigned char session_id
[33];
458 size_t session_id_size
= sizeof (session_id
);
460 /* print session ID */
461 gnutls_session_get_id (session
, session_id
, &session_id_size
);
462 printf ("- Session ID: %s\n",
463 raw_to_string (session_id
, session_id_size
));
465 /* print the key exchange's algorithm name
467 kx
= gnutls_kx_get (session
);
469 cred
= gnutls_auth_get_type (session
);
473 case GNUTLS_CRD_ANON
:
474 if (kx
== GNUTLS_KX_ANON_ECDH
)
475 print_ecdh_info (session
, "Anonymous ");
477 print_dh_info (session
, "Anonymous ", verbose
);
482 /* This should be only called in server
485 if (gnutls_srp_server_get_username (session
) != NULL
)
486 printf ("- SRP authentication. Connected as '%s'\n",
487 gnutls_srp_server_get_username (session
));
492 /* This returns NULL in server side.
494 if (gnutls_psk_client_get_hint (session
) != NULL
)
495 printf ("- PSK authentication. PSK hint '%s'\n",
496 gnutls_psk_client_get_hint (session
));
497 /* This returns NULL in client side.
499 if (gnutls_psk_server_get_username (session
) != NULL
)
500 printf ("- PSK authentication. Connected as '%s'\n",
501 gnutls_psk_server_get_username (session
));
502 if (kx
== GNUTLS_KX_DHE_PSK
)
503 print_dh_info (session
, "Ephemeral ", verbose
);
504 if (kx
== GNUTLS_KX_ECDHE_PSK
)
505 print_ecdh_info (session
, "Ephemeral ");
509 printf ("- TLS/IA authentication\n");
511 case GNUTLS_CRD_CERTIFICATE
:
514 size_t dns_size
= sizeof (dns
);
517 /* This fails in client side */
518 if (gnutls_server_name_get
519 (session
, dns
, &dns_size
, &type
, 0) == 0)
521 printf ("- Given server name[%d]: %s\n", type
, dns
);
526 print_cert_info (session
, verbose
, print_cert
);
528 if (kx
== GNUTLS_KX_DHE_RSA
|| kx
== GNUTLS_KX_DHE_DSS
)
529 print_dh_info (session
, "Ephemeral ", verbose
);
530 else if (kx
== GNUTLS_KX_ECDHE_RSA
531 || kx
== GNUTLS_KX_ECDHE_ECDSA
)
532 print_ecdh_info (session
, "Ephemeral ");
536 SU (gnutls_protocol_get_name
537 (gnutls_protocol_get_version (session
)));
538 printf ("- Version: %s\n", tmp
);
540 tmp
= SU (gnutls_kx_get_name (kx
));
541 printf ("- Key Exchange: %s\n", tmp
);
543 tmp
= SU (gnutls_cipher_get_name (gnutls_cipher_get (session
)));
544 printf ("- Cipher: %s\n", tmp
);
546 tmp
= SU (gnutls_mac_get_name (gnutls_mac_get (session
)));
547 printf ("- MAC: %s\n", tmp
);
550 SU (gnutls_compression_get_name
551 (gnutls_compression_get (session
)));
552 printf ("- Compression: %s\n", tmp
);
559 rc
= gnutls_session_channel_binding (session
,
560 GNUTLS_CB_TLS_UNIQUE
, &cb
);
562 fprintf (stderr
, "Channel binding error: %s\n",
563 gnutls_strerror (rc
));
568 printf ("- Channel binding 'tls-unique': ");
569 for (i
= 0; i
< cb
.size
; i
++)
570 printf ("%02x", cb
.data
[i
]);
575 /* Warning: Do not print anything more here. The 'Compression:'
576 output MUST be the last non-verbose output. This is used by
577 Emacs starttls.el code. */
585 print_cert_info (gnutls_session_t session
, int verbose
, int print_cert
)
589 if (verbose
) flag
= GNUTLS_CRT_PRINT_FULL
;
590 else flag
= GNUTLS_CRT_PRINT_COMPACT
;
592 if (gnutls_certificate_client_get_request_status (session
) != 0)
593 printf ("- Server has requested a certificate.\n");
595 switch (gnutls_certificate_type_get (session
))
597 case GNUTLS_CRT_X509
:
598 print_x509_info (session
, flag
, print_cert
);
600 #ifdef ENABLE_OPENPGP
601 case GNUTLS_CRT_OPENPGP
:
602 print_openpgp_info (session
, flag
, print_cert
);
606 printf ("Unknown type\n");
612 print_cert_info_compact (gnutls_session_t session
)
615 if (gnutls_certificate_client_get_request_status (session
) != 0)
616 printf ("- Server has requested a certificate.\n");
618 switch (gnutls_certificate_type_get (session
))
620 case GNUTLS_CRT_X509
:
621 print_x509_info_compact (session
);
623 #ifdef ENABLE_OPENPGP
624 case GNUTLS_CRT_OPENPGP
:
625 print_openpgp_info_compact (session
);
629 printf ("Unknown type\n");
635 print_list (const char *priorities
, int verbose
)
643 gnutls_kx_algorithm_t kx
;
644 gnutls_cipher_algorithm_t cipher
;
645 gnutls_mac_algorithm_t mac
;
646 gnutls_protocol_t version
;
647 gnutls_priority_t pcache
;
648 const unsigned int *list
;
650 if (priorities
!= NULL
)
652 printf ("Cipher suites for %s\n", priorities
);
654 ret
= gnutls_priority_init (&pcache
, priorities
, &err
);
657 fprintf (stderr
, "Syntax error at: %s\n", err
);
664 gnutls_priority_get_cipher_suite_index (pcache
, i
,
666 if (ret
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
668 if (ret
== GNUTLS_E_UNKNOWN_CIPHER_SUITE
)
672 gnutls_cipher_suite_info (idx
, id
, NULL
, NULL
, NULL
,
676 printf ("%-50s\t0x%02x, 0x%02x\t%s\n",
677 name
, (unsigned char) id
[0],
678 (unsigned char) id
[1],
679 gnutls_protocol_get_name (version
));
684 ret
= gnutls_priority_certificate_type_list (pcache
, &list
);
686 printf ("Certificate types: ");
687 if (ret
== 0) printf("none\n");
688 for (i
= 0; i
< (unsigned)ret
; i
++)
691 gnutls_certificate_type_get_name (list
[i
]));
692 if (i
+1!=(unsigned)ret
)
700 ret
= gnutls_priority_protocol_list (pcache
, &list
);
702 printf ("Protocols: ");
703 if (ret
== 0) printf("none\n");
704 for (i
= 0; i
< (unsigned)ret
; i
++)
706 printf ("VERS-%s", gnutls_protocol_get_name (list
[i
]));
707 if (i
+1!=(unsigned)ret
)
715 ret
= gnutls_priority_compression_list (pcache
, &list
);
717 printf ("Compression: ");
718 if (ret
== 0) printf("none\n");
719 for (i
= 0; i
< (unsigned)ret
; i
++)
722 gnutls_compression_get_name (list
[i
]));
723 if (i
+1!=(unsigned)ret
)
731 ret
= gnutls_priority_ecc_curve_list (pcache
, &list
);
733 printf ("Elliptic curves: ");
734 if (ret
== 0) printf("none\n");
735 for (i
= 0; i
< (unsigned)ret
; i
++)
738 gnutls_ecc_curve_get_name (list
[i
]));
739 if (i
+1!=(unsigned)ret
)
747 ret
= gnutls_priority_sign_list (pcache
, &list
);
749 printf ("PK-signatures: ");
750 if (ret
== 0) printf("none\n");
751 for (i
= 0; i
< (unsigned)ret
; i
++)
754 gnutls_sign_algorithm_get_name (list
[i
]));
755 if (i
+1!=(unsigned)ret
)
765 printf ("Cipher suites:\n");
766 for (i
= 0; (name
= gnutls_cipher_suite_info
767 (i
, id
, &kx
, &cipher
, &mac
, &version
)); i
++)
769 printf ("%-50s\t0x%02x, 0x%02x\t%s\n",
771 (unsigned char) id
[0], (unsigned char) id
[1],
772 gnutls_protocol_get_name (version
));
774 printf ("\tKey exchange: %s\n\tCipher: %s\n\tMAC: %s\n\n",
775 gnutls_kx_get_name (kx
),
776 gnutls_cipher_get_name (cipher
),
777 gnutls_mac_get_name (mac
));
782 const gnutls_certificate_type_t
*p
=
783 gnutls_certificate_type_list ();
785 printf ("Certificate types: ");
788 printf ("CTYPE-%s", gnutls_certificate_type_get_name (*p
));
797 const gnutls_protocol_t
*p
= gnutls_protocol_list ();
799 printf ("Protocols: ");
802 printf ("VERS-%s", gnutls_protocol_get_name (*p
));
811 const gnutls_cipher_algorithm_t
*p
= gnutls_cipher_list ();
813 printf ("Ciphers: ");
816 printf ("%s", gnutls_cipher_get_name (*p
));
825 const gnutls_mac_algorithm_t
*p
= gnutls_mac_list ();
830 printf ("%s", gnutls_mac_get_name (*p
));
839 const gnutls_kx_algorithm_t
*p
= gnutls_kx_list ();
841 printf ("Key exchange algorithms: ");
844 printf ("%s", gnutls_kx_get_name (*p
));
853 const gnutls_compression_method_t
*p
= gnutls_compression_list ();
855 printf ("Compression: ");
858 printf ("COMP-%s", gnutls_compression_get_name (*p
));
867 const gnutls_ecc_curve_t
*p
= gnutls_ecc_curve_list ();
869 printf ("Elliptic curves: ");
872 printf ("CURVE-%s", gnutls_ecc_curve_get_name (*p
));
881 const gnutls_pk_algorithm_t
*p
= gnutls_pk_list ();
883 printf ("Public Key Systems: ");
886 printf ("%s", gnutls_pk_algorithm_get_name (*p
));
895 const gnutls_sign_algorithm_t
*p
= gnutls_sign_list ();
897 printf ("PK-signatures: ");
900 printf ("SIGN-%s", gnutls_sign_algorithm_get_name (*p
));
909 int check_command(gnutls_session_t session
, const char* str
)
911 size_t len
= strnlen(str
, 128);
914 fprintf (stderr
, "*** Processing %zu bytes command: %s\n", len
, str
);
915 if (len
> 2 && str
[0] == str
[1] && str
[0] == '*')
917 if (strncmp(str
, "**REHANDSHAKE**", sizeof ("**REHANDSHAKE**") - 1) == 0)
919 fprintf (stderr
, "*** Sending rehandshake request\n");
920 gnutls_rehandshake (session
);
922 } else if (strncmp(str
, "**HEARTBEAT**", sizeof ("**HEARTBEAT**") - 1) == 0) {
923 ret
= gnutls_heartbeat_ping (session
, 300, 5, GNUTLS_HEARTBEAT_WAIT
);
926 if (ret
== GNUTLS_E_INVALID_REQUEST
)
928 fprintf(stderr
, "No heartbeat in this session\n");
932 fprintf(stderr
, "ping: %s\n", gnutls_strerror(ret
));
942 #define MIN(x,y) ((x)<(y))?(x):(y)
943 #define MAX_CACHE_TRIES 5
945 pin_callback (void *user
, int attempt
, const char *token_url
,
946 const char *token_label
, unsigned int flags
, char *pin
,
949 const char *password
;
951 int len
, cache
= MAX_CACHE_TRIES
;
952 /* allow caching of PIN */
953 static char *cached_url
= NULL
;
954 static char cached_pin
[32] = "";
956 if (flags
& GNUTLS_PIN_SO
)
957 desc
= "security officer";
961 if (flags
& GNUTLS_PIN_FINAL_TRY
)
964 printf ("*** This is the final try before locking!\n");
966 if (flags
& GNUTLS_PIN_COUNT_LOW
)
969 printf ("*** Only few tries left before locking!\n");
972 if (flags
& GNUTLS_PIN_WRONG
)
975 printf ("*** Wrong PIN has been provided!\n");
978 if (cache
> 0 && cached_url
!= NULL
)
980 if (strcmp (cached_url
, token_url
) == 0)
982 if (strlen(pin
) >= sizeof(cached_pin
))
984 fprintf (stderr
, "Too long PIN given\n");
988 fprintf(stderr
, "Re-using cached PIN for token '%s'\n", token_label
);
989 strcpy (pin
, cached_pin
);
995 printf ("Token '%s' with URL '%s' ", token_label
, token_url
);
996 printf ("requires %s PIN\n", desc
);
998 password
= getpass ("Enter PIN: ");
999 if (password
== NULL
|| password
[0] == 0)
1001 fprintf (stderr
, "No password given\n");
1005 len
= MIN (pin_max
, strlen (password
));
1006 memcpy (pin
, password
, len
);
1010 strcpy (cached_pin
, pin
);
1012 cached_url
= strdup (token_url
);
1013 cache
= MAX_CACHE_TRIES
;
1018 #ifdef ENABLE_PKCS11
1021 token_callback (void *user
, const char *label
, const unsigned retry
)
1027 fprintf (stderr
, "Could not find token %s\n", label
);
1030 printf ("Please insert token '%s' in slot and press enter\n", label
);
1031 fgets (buf
, sizeof (buf
), stdin
);
1037 pkcs11_common (void)
1040 gnutls_pkcs11_set_pin_function (pin_callback
, NULL
);
1041 gnutls_pkcs11_set_token_function (token_callback
, NULL
);