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 ("- Status: %s\n", 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
);
459 gnutls_srtp_profile_t srtp_profile
;
462 /* print session ID */
463 gnutls_session_get_id (session
, session_id
, &session_id_size
);
464 printf ("- Session ID: %s\n",
465 raw_to_string (session_id
, session_id_size
));
467 /* print the key exchange's algorithm name
469 kx
= gnutls_kx_get (session
);
471 cred
= gnutls_auth_get_type (session
);
475 case GNUTLS_CRD_ANON
:
476 if (kx
== GNUTLS_KX_ANON_ECDH
)
477 print_ecdh_info (session
, "Anonymous ");
479 print_dh_info (session
, "Anonymous ", verbose
);
484 /* This should be only called in server
487 if (gnutls_srp_server_get_username (session
) != NULL
)
488 printf ("- SRP authentication. Connected as '%s'\n",
489 gnutls_srp_server_get_username (session
));
494 /* This returns NULL in server side.
496 if (gnutls_psk_client_get_hint (session
) != NULL
)
497 printf ("- PSK authentication. PSK hint '%s'\n",
498 gnutls_psk_client_get_hint (session
));
499 /* This returns NULL in client side.
501 if (gnutls_psk_server_get_username (session
) != NULL
)
502 printf ("- PSK authentication. Connected as '%s'\n",
503 gnutls_psk_server_get_username (session
));
504 if (kx
== GNUTLS_KX_DHE_PSK
)
505 print_dh_info (session
, "Ephemeral ", verbose
);
506 if (kx
== GNUTLS_KX_ECDHE_PSK
)
507 print_ecdh_info (session
, "Ephemeral ");
511 printf ("- TLS/IA authentication\n");
513 case GNUTLS_CRD_CERTIFICATE
:
516 size_t dns_size
= sizeof (dns
);
519 /* This fails in client side */
520 if (gnutls_server_name_get
521 (session
, dns
, &dns_size
, &type
, 0) == 0)
523 printf ("- Given server name[%d]: %s\n", type
, dns
);
528 print_cert_info (session
, verbose
, print_cert
);
530 if (kx
== GNUTLS_KX_DHE_RSA
|| kx
== GNUTLS_KX_DHE_DSS
)
531 print_dh_info (session
, "Ephemeral ", verbose
);
532 else if (kx
== GNUTLS_KX_ECDHE_RSA
533 || kx
== GNUTLS_KX_ECDHE_ECDSA
)
534 print_ecdh_info (session
, "Ephemeral ");
538 SU (gnutls_protocol_get_name
539 (gnutls_protocol_get_version (session
)));
540 printf ("- Version: %s\n", tmp
);
542 tmp
= SU (gnutls_kx_get_name (kx
));
543 printf ("- Key Exchange: %s\n", tmp
);
545 tmp
= SU (gnutls_cipher_get_name (gnutls_cipher_get (session
)));
546 printf ("- Cipher: %s\n", tmp
);
548 tmp
= SU (gnutls_mac_get_name (gnutls_mac_get (session
)));
549 printf ("- MAC: %s\n", tmp
);
552 SU (gnutls_compression_get_name
553 (gnutls_compression_get (session
)));
554 printf ("- Compression: %s\n", tmp
);
556 #ifdef ENABLE_DTLS_SRTP
557 rc
= gnutls_srtp_get_selected_profile (session
, &srtp_profile
);
559 printf ("- SRTP profile: %s\n", gnutls_srtp_get_profile_name (srtp_profile
));
566 rc
= gnutls_session_channel_binding (session
,
567 GNUTLS_CB_TLS_UNIQUE
, &cb
);
569 fprintf (stderr
, "Channel binding error: %s\n",
570 gnutls_strerror (rc
));
575 printf ("- Channel binding 'tls-unique': ");
576 for (i
= 0; i
< cb
.size
; i
++)
577 printf ("%02x", cb
.data
[i
]);
582 /* Warning: Do not print anything more here. The 'Compression:'
583 output MUST be the last non-verbose output. This is used by
584 Emacs starttls.el code. */
592 print_cert_info (gnutls_session_t session
, int verbose
, int print_cert
)
596 if (verbose
) flag
= GNUTLS_CRT_PRINT_FULL
;
597 else flag
= GNUTLS_CRT_PRINT_COMPACT
;
599 if (gnutls_certificate_client_get_request_status (session
) != 0)
600 printf ("- Server has requested a certificate.\n");
602 switch (gnutls_certificate_type_get (session
))
604 case GNUTLS_CRT_X509
:
605 print_x509_info (session
, flag
, print_cert
);
607 #ifdef ENABLE_OPENPGP
608 case GNUTLS_CRT_OPENPGP
:
609 print_openpgp_info (session
, flag
, print_cert
);
613 printf ("Unknown type\n");
619 print_cert_info_compact (gnutls_session_t session
)
622 if (gnutls_certificate_client_get_request_status (session
) != 0)
623 printf ("- Server has requested a certificate.\n");
625 switch (gnutls_certificate_type_get (session
))
627 case GNUTLS_CRT_X509
:
628 print_x509_info_compact (session
);
630 #ifdef ENABLE_OPENPGP
631 case GNUTLS_CRT_OPENPGP
:
632 print_openpgp_info_compact (session
);
636 printf ("Unknown type\n");
642 print_list (const char *priorities
, int verbose
)
650 gnutls_kx_algorithm_t kx
;
651 gnutls_cipher_algorithm_t cipher
;
652 gnutls_mac_algorithm_t mac
;
653 gnutls_protocol_t version
;
654 gnutls_priority_t pcache
;
655 const unsigned int *list
;
657 if (priorities
!= NULL
)
659 printf ("Cipher suites for %s\n", priorities
);
661 ret
= gnutls_priority_init (&pcache
, priorities
, &err
);
664 fprintf (stderr
, "Syntax error at: %s\n", err
);
671 gnutls_priority_get_cipher_suite_index (pcache
, i
,
673 if (ret
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
675 if (ret
== GNUTLS_E_UNKNOWN_CIPHER_SUITE
)
679 gnutls_cipher_suite_info (idx
, id
, NULL
, NULL
, NULL
,
683 printf ("%-50s\t0x%02x, 0x%02x\t%s\n",
684 name
, (unsigned char) id
[0],
685 (unsigned char) id
[1],
686 gnutls_protocol_get_name (version
));
691 ret
= gnutls_priority_certificate_type_list (pcache
, &list
);
693 printf ("Certificate types: ");
694 if (ret
== 0) printf("none\n");
695 for (i
= 0; i
< (unsigned)ret
; i
++)
698 gnutls_certificate_type_get_name (list
[i
]));
699 if (i
+1!=(unsigned)ret
)
707 ret
= gnutls_priority_protocol_list (pcache
, &list
);
709 printf ("Protocols: ");
710 if (ret
== 0) printf("none\n");
711 for (i
= 0; i
< (unsigned)ret
; i
++)
713 printf ("VERS-%s", gnutls_protocol_get_name (list
[i
]));
714 if (i
+1!=(unsigned)ret
)
722 ret
= gnutls_priority_compression_list (pcache
, &list
);
724 printf ("Compression: ");
725 if (ret
== 0) printf("none\n");
726 for (i
= 0; i
< (unsigned)ret
; i
++)
729 gnutls_compression_get_name (list
[i
]));
730 if (i
+1!=(unsigned)ret
)
738 ret
= gnutls_priority_ecc_curve_list (pcache
, &list
);
740 printf ("Elliptic curves: ");
741 if (ret
== 0) printf("none\n");
742 for (i
= 0; i
< (unsigned)ret
; i
++)
745 gnutls_ecc_curve_get_name (list
[i
]));
746 if (i
+1!=(unsigned)ret
)
754 ret
= gnutls_priority_sign_list (pcache
, &list
);
756 printf ("PK-signatures: ");
757 if (ret
== 0) printf("none\n");
758 for (i
= 0; i
< (unsigned)ret
; i
++)
761 gnutls_sign_algorithm_get_name (list
[i
]));
762 if (i
+1!=(unsigned)ret
)
772 printf ("Cipher suites:\n");
773 for (i
= 0; (name
= gnutls_cipher_suite_info
774 (i
, id
, &kx
, &cipher
, &mac
, &version
)); i
++)
776 printf ("%-50s\t0x%02x, 0x%02x\t%s\n",
778 (unsigned char) id
[0], (unsigned char) id
[1],
779 gnutls_protocol_get_name (version
));
781 printf ("\tKey exchange: %s\n\tCipher: %s\n\tMAC: %s\n\n",
782 gnutls_kx_get_name (kx
),
783 gnutls_cipher_get_name (cipher
),
784 gnutls_mac_get_name (mac
));
789 const gnutls_certificate_type_t
*p
=
790 gnutls_certificate_type_list ();
792 printf ("Certificate types: ");
795 printf ("CTYPE-%s", gnutls_certificate_type_get_name (*p
));
804 const gnutls_protocol_t
*p
= gnutls_protocol_list ();
806 printf ("Protocols: ");
809 printf ("VERS-%s", gnutls_protocol_get_name (*p
));
818 const gnutls_cipher_algorithm_t
*p
= gnutls_cipher_list ();
820 printf ("Ciphers: ");
823 printf ("%s", gnutls_cipher_get_name (*p
));
832 const gnutls_mac_algorithm_t
*p
= gnutls_mac_list ();
837 printf ("%s", gnutls_mac_get_name (*p
));
846 const gnutls_kx_algorithm_t
*p
= gnutls_kx_list ();
848 printf ("Key exchange algorithms: ");
851 printf ("%s", gnutls_kx_get_name (*p
));
860 const gnutls_compression_method_t
*p
= gnutls_compression_list ();
862 printf ("Compression: ");
865 printf ("COMP-%s", gnutls_compression_get_name (*p
));
874 const gnutls_ecc_curve_t
*p
= gnutls_ecc_curve_list ();
876 printf ("Elliptic curves: ");
879 printf ("CURVE-%s", gnutls_ecc_curve_get_name (*p
));
888 const gnutls_pk_algorithm_t
*p
= gnutls_pk_list ();
890 printf ("Public Key Systems: ");
893 printf ("%s", gnutls_pk_algorithm_get_name (*p
));
902 const gnutls_sign_algorithm_t
*p
= gnutls_sign_list ();
904 printf ("PK-signatures: ");
907 printf ("SIGN-%s", gnutls_sign_algorithm_get_name (*p
));
916 int check_command(gnutls_session_t session
, const char* str
)
918 size_t len
= strnlen(str
, 128);
921 fprintf (stderr
, "*** Processing %zu bytes command: %s\n", len
, str
);
922 if (len
> 2 && str
[0] == str
[1] && str
[0] == '*')
924 if (strncmp(str
, "**REHANDSHAKE**", sizeof ("**REHANDSHAKE**") - 1) == 0)
926 fprintf (stderr
, "*** Sending rehandshake request\n");
927 gnutls_rehandshake (session
);
929 } else if (strncmp(str
, "**HEARTBEAT**", sizeof ("**HEARTBEAT**") - 1) == 0) {
930 ret
= gnutls_heartbeat_ping (session
, 300, 5, GNUTLS_HEARTBEAT_WAIT
);
933 if (ret
== GNUTLS_E_INVALID_REQUEST
)
935 fprintf(stderr
, "No heartbeat in this session\n");
939 fprintf(stderr
, "ping: %s\n", gnutls_strerror(ret
));
949 #define MIN(x,y) ((x)<(y))?(x):(y)
950 #define MAX_CACHE_TRIES 5
952 pin_callback (void *user
, int attempt
, const char *token_url
,
953 const char *token_label
, unsigned int flags
, char *pin
,
956 const char *password
;
958 int len
, cache
= MAX_CACHE_TRIES
;
959 /* allow caching of PIN */
960 static char *cached_url
= NULL
;
961 static char cached_pin
[32] = "";
963 if (flags
& GNUTLS_PIN_SO
)
964 desc
= "security officer";
968 if (flags
& GNUTLS_PIN_FINAL_TRY
)
971 printf ("*** This is the final try before locking!\n");
973 if (flags
& GNUTLS_PIN_COUNT_LOW
)
976 printf ("*** Only few tries left before locking!\n");
979 if (flags
& GNUTLS_PIN_WRONG
)
982 printf ("*** Wrong PIN has been provided!\n");
985 if (cache
> 0 && cached_url
!= NULL
)
987 if (strcmp (cached_url
, token_url
) == 0)
989 if (strlen(pin
) >= sizeof(cached_pin
))
991 fprintf (stderr
, "Too long PIN given\n");
995 fprintf(stderr
, "Re-using cached PIN for token '%s'\n", token_label
);
996 strcpy (pin
, cached_pin
);
1002 printf ("Token '%s' with URL '%s' ", token_label
, token_url
);
1003 printf ("requires %s PIN\n", desc
);
1005 password
= getpass ("Enter PIN: ");
1006 if (password
== NULL
|| password
[0] == 0)
1008 fprintf (stderr
, "No password given\n");
1012 len
= MIN (pin_max
, strlen (password
));
1013 memcpy (pin
, password
, len
);
1017 strcpy (cached_pin
, pin
);
1019 cached_url
= strdup (token_url
);
1020 cache
= MAX_CACHE_TRIES
;
1025 #ifdef ENABLE_PKCS11
1028 token_callback (void *user
, const char *label
, const unsigned retry
)
1034 fprintf (stderr
, "Could not find token %s\n", label
);
1037 printf ("Please insert token '%s' in slot and press enter\n", label
);
1038 fgets (buf
, sizeof (buf
), stdin
);
1044 pkcs11_common (void)
1047 gnutls_pkcs11_set_pin_function (pin_callback
, NULL
);
1048 gnutls_pkcs11_set_token_function (token_callback
, NULL
);