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>
40 #define SU(x) (x!=NULL?x:"Unknown")
44 const char str_unknown
[] = "(unknown)";
46 /* Hex encodes the given data.
49 raw_to_string (const unsigned char *raw
, size_t raw_size
)
51 static char buf
[1024];
56 if (raw_size
* 3 + 1 >= sizeof (buf
))
59 for (i
= 0; i
< raw_size
; i
++)
61 sprintf (&(buf
[i
* 3]), "%02X%s", raw
[i
],
62 (i
== raw_size
- 1) ? "" : ":");
64 buf
[sizeof (buf
) - 1] = '\0';
70 print_x509_info_compact (gnutls_session_t session
)
72 gnutls_x509_crt_t crt
;
73 const gnutls_datum_t
*cert_list
;
74 unsigned int cert_list_size
= 0;
78 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
79 if (cert_list_size
== 0)
81 fprintf (stderr
, "No certificates found!\n");
85 gnutls_x509_crt_init (&crt
);
87 gnutls_x509_crt_import (crt
, &cert_list
[0],
91 fprintf (stderr
, "Decoding error: %s\n",
92 gnutls_strerror (ret
));
97 gnutls_x509_crt_print (crt
, GNUTLS_CRT_PRINT_COMPACT
, &cinfo
);
100 printf ("- X.509 cert: %s\n", cinfo
.data
);
101 gnutls_free (cinfo
.data
);
104 gnutls_x509_crt_deinit (crt
);
108 print_x509_info (gnutls_session_t session
, int flag
, int print_cert
)
110 gnutls_x509_crt_t crt
;
111 const gnutls_datum_t
*cert_list
;
112 unsigned int cert_list_size
= 0, j
;
115 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
116 if (cert_list_size
== 0)
118 fprintf (stderr
, "No certificates found!\n");
122 printf ("- Certificate type: X.509\n");
123 printf ("- Got a certificate list of %d certificates.\n",
126 for (j
= 0; j
< cert_list_size
; j
++)
128 gnutls_datum_t cinfo
;
130 gnutls_x509_crt_init (&crt
);
132 gnutls_x509_crt_import (crt
, &cert_list
[j
],
133 GNUTLS_X509_FMT_DER
);
136 fprintf (stderr
, "Decoding error: %s\n",
137 gnutls_strerror (ret
));
141 printf ("- Certificate[%d] info:\n - ", j
);
142 if (flag
== GNUTLS_CRT_PRINT_COMPACT
&& j
> 0) flag
= GNUTLS_CRT_PRINT_ONELINE
;
145 gnutls_x509_crt_print (crt
, flag
, &cinfo
);
148 printf ("%s\n", cinfo
.data
);
149 gnutls_free (cinfo
.data
);
158 gnutls_x509_crt_export (crt
, GNUTLS_X509_FMT_PEM
, p
,
160 if (ret
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
165 fprintf (stderr
, "gnutls_malloc\n");
170 gnutls_x509_crt_export (crt
, GNUTLS_X509_FMT_PEM
,
175 fprintf (stderr
, "Encoding error: %s\n",
176 gnutls_strerror (ret
));
180 fputs ("\n", stdout
);
182 fputs ("\n", stdout
);
187 gnutls_x509_crt_deinit (crt
);
191 /* returns true or false, depending on whether the hostname
192 * matches to certificate */
194 verify_x509_hostname (gnutls_session_t session
, const char *hostname
)
196 gnutls_x509_crt_t crt
;
197 const gnutls_datum_t
*cert_list
;
198 unsigned int cert_list_size
= 0;
201 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
202 if (cert_list_size
== 0)
204 fprintf (stderr
, "No certificates found!\n");
208 gnutls_x509_crt_init (&crt
);
210 gnutls_x509_crt_import (crt
, &cert_list
[0],
211 GNUTLS_X509_FMT_DER
);
214 fprintf (stderr
, "Decoding error: %s\n",
215 gnutls_strerror (ret
));
219 /* Check the hostname of the first certificate if it matches
220 * the name of the host we connected to.
222 if (hostname
!= NULL
)
224 if (gnutls_x509_crt_check_hostname (crt
, hostname
) == 0)
227 ("- The hostname in the certificate does NOT match '%s'\n",
233 printf ("- The hostname in the certificate matches '%s'.\n",
239 gnutls_x509_crt_deinit (crt
);
244 #ifdef ENABLE_OPENPGP
245 /* returns true or false, depending on whether the hostname
246 * matches to certificate */
248 verify_openpgp_hostname (gnutls_session_t session
, const char *hostname
)
250 gnutls_openpgp_crt_t crt
;
251 const gnutls_datum_t
*cert_list
;
252 unsigned int cert_list_size
= 0;
255 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
256 if (cert_list_size
== 0)
258 fprintf (stderr
, "No certificates found!\n");
262 gnutls_openpgp_crt_init (&crt
);
264 gnutls_openpgp_crt_import (crt
, &cert_list
[0],
265 GNUTLS_OPENPGP_FMT_RAW
);
268 fprintf (stderr
, "Decoding error: %s\n",
269 gnutls_strerror (ret
));
273 /* Check the hostname of the first certificate if it matches
274 * the name of the host we connected to.
276 if (gnutls_openpgp_crt_check_hostname (crt
, hostname
) == 0)
279 ("- The hostname in the certificate does NOT match '%s'\n",
285 printf ("- The hostname in the certificate matches '%s'.\n",
290 gnutls_openpgp_crt_deinit (crt
);
296 print_openpgp_info_compact (gnutls_session_t session
)
299 gnutls_openpgp_crt_t crt
;
300 const gnutls_datum_t
*cert_list
;
301 unsigned int cert_list_size
= 0;
304 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
306 if (cert_list_size
> 0)
308 gnutls_datum_t cinfo
;
310 gnutls_openpgp_crt_init (&crt
);
311 ret
= gnutls_openpgp_crt_import (crt
, &cert_list
[0],
312 GNUTLS_OPENPGP_FMT_RAW
);
315 fprintf (stderr
, "Decoding error: %s\n",
316 gnutls_strerror (ret
));
321 gnutls_openpgp_crt_print (crt
, GNUTLS_CRT_PRINT_COMPACT
, &cinfo
);
324 printf ("- OpenPGP cert: %s\n", cinfo
.data
);
325 gnutls_free (cinfo
.data
);
328 gnutls_openpgp_crt_deinit (crt
);
333 print_openpgp_info (gnutls_session_t session
, int flag
, int print_cert
)
336 gnutls_openpgp_crt_t crt
;
337 const gnutls_datum_t
*cert_list
;
338 unsigned int cert_list_size
= 0;
341 printf ("- Certificate type: OpenPGP\n");
343 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
345 if (cert_list_size
> 0)
347 gnutls_datum_t cinfo
;
349 gnutls_openpgp_crt_init (&crt
);
350 ret
= gnutls_openpgp_crt_import (crt
, &cert_list
[0],
351 GNUTLS_OPENPGP_FMT_RAW
);
354 fprintf (stderr
, "Decoding error: %s\n",
355 gnutls_strerror (ret
));
360 gnutls_openpgp_crt_print (crt
, flag
, &cinfo
);
363 printf ("- %s\n", cinfo
.data
);
364 gnutls_free (cinfo
.data
);
373 gnutls_openpgp_crt_export (crt
,
374 GNUTLS_OPENPGP_FMT_BASE64
,
376 if (ret
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
381 fprintf (stderr
, "gnutls_malloc\n");
386 gnutls_openpgp_crt_export (crt
,
387 GNUTLS_OPENPGP_FMT_BASE64
,
392 fprintf (stderr
, "Encoding error: %s\n",
393 gnutls_strerror (ret
));
398 fputs ("\n", stdout
);
403 gnutls_openpgp_crt_deinit (crt
);
409 /* returns false (0) if not verified, or true (1) otherwise
412 cert_verify (gnutls_session_t session
, const char* hostname
)
415 unsigned int status
= 0;
418 rc
= gnutls_certificate_verify_peers2 (session
, &status
);
419 if (rc
== GNUTLS_E_NO_CERTIFICATE_FOUND
)
421 printf ("- Peer did not send any certificate.\n");
427 printf ("- Could not verify certificate (err: %s)\n",
428 gnutls_strerror (rc
));
432 type
= gnutls_certificate_type_get (session
);
433 if (type
== GNUTLS_CRT_X509
)
436 if (status
& GNUTLS_CERT_REVOKED
)
437 printf ("- Peer's certificate chain revoked\n");
438 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
439 printf ("- Peer's certificate issuer is unknown\n");
440 if (status
& GNUTLS_CERT_SIGNER_NOT_CA
)
441 printf ("- Peer's certificate issuer is not a CA\n");
442 if (status
& GNUTLS_CERT_INSECURE_ALGORITHM
)
444 ("- Peer's certificate chain uses insecure algorithm\n");
445 if (status
& GNUTLS_CERT_NOT_ACTIVATED
)
447 ("- Peer's certificate chain uses not yet valid certificate\n");
448 if (status
& GNUTLS_CERT_EXPIRED
)
450 ("- Peer's certificate chain uses expired certificate\n");
451 if (status
& GNUTLS_CERT_INVALID
)
452 printf ("- Peer's certificate is NOT trusted\n");
454 printf ("- Peer's certificate is trusted\n");
456 rc
= verify_x509_hostname (session
, hostname
);
457 if (rc
== 0) status
|= GNUTLS_CERT_INVALID
;
459 else if (type
== GNUTLS_CRT_OPENPGP
)
461 if (status
& GNUTLS_CERT_INVALID
)
462 printf ("- Peer's key is invalid\n");
464 printf ("- Peer's key is valid\n");
465 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
466 printf ("- Could not find a signer of the peer's key\n");
468 rc
= verify_openpgp_hostname (session
, hostname
);
469 if (rc
== 0) status
|= GNUTLS_CERT_INVALID
;
473 fprintf(stderr
, "Unknown certificate type\n");
474 status
|= GNUTLS_CERT_INVALID
;
484 print_dh_info (gnutls_session_t session
, const char *str
, int print
)
486 printf ("- %sDiffie-Hellman parameters\n", str
);
487 printf (" - Using prime: %d bits\n",
488 gnutls_dh_get_prime_bits (session
));
489 printf (" - Secret key: %d bits\n",
490 gnutls_dh_get_secret_bits (session
));
491 printf (" - Peer's public key: %d bits\n",
492 gnutls_dh_get_peers_public_bits (session
));
497 gnutls_datum_t raw_gen
= { NULL
, 0 };
498 gnutls_datum_t raw_prime
= { NULL
, 0 };
499 gnutls_dh_params_t dh_params
= NULL
;
500 unsigned char *params_data
= NULL
;
501 size_t params_data_size
= 0;
503 ret
= gnutls_dh_get_group (session
, &raw_gen
, &raw_prime
);
506 fprintf (stderr
, "gnutls_dh_get_group %d\n", ret
);
510 ret
= gnutls_dh_params_init (&dh_params
);
513 fprintf (stderr
, "gnutls_dh_params_init %d\n", ret
);
518 gnutls_dh_params_import_raw (dh_params
, &raw_prime
,
522 fprintf (stderr
, "gnutls_dh_params_import_raw %d\n", ret
);
526 ret
= gnutls_dh_params_export_pkcs3 (dh_params
,
530 if (ret
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
532 fprintf (stderr
, "gnutls_dh_params_export_pkcs3 %d\n",
537 params_data
= gnutls_malloc (params_data_size
);
540 fprintf (stderr
, "gnutls_malloc %d\n", ret
);
544 ret
= gnutls_dh_params_export_pkcs3 (dh_params
,
550 fprintf (stderr
, "gnutls_dh_params_export_pkcs3-2 %d\n",
555 printf (" - PKCS#3 format:\n\n%.*s\n", (int) params_data_size
,
559 gnutls_free (params_data
);
560 gnutls_free (raw_prime
.data
);
561 gnutls_free (raw_gen
.data
);
562 gnutls_dh_params_deinit (dh_params
);
567 print_ecdh_info (gnutls_session_t session
, const char *str
)
571 printf ("- %sEC Diffie-Hellman parameters\n", str
);
573 curve
= gnutls_ecc_curve_get (session
);
575 printf (" - Using curve: %s\n", gnutls_ecc_curve_get_name (curve
));
576 printf (" - Curve size: %d bits\n",
577 gnutls_ecc_curve_get_size (curve
) * 8);
582 print_info (gnutls_session_t session
, int print_cert
)
585 gnutls_credentials_type_t cred
;
586 gnutls_kx_algorithm_t kx
;
587 unsigned char session_id
[33];
588 size_t session_id_size
= sizeof (session_id
);
590 /* print session ID */
591 gnutls_session_get_id (session
, session_id
, &session_id_size
);
592 printf ("- Session ID: %s\n",
593 raw_to_string (session_id
, session_id_size
));
595 /* print the key exchange's algorithm name
597 kx
= gnutls_kx_get (session
);
599 cred
= gnutls_auth_get_type (session
);
603 case GNUTLS_CRD_ANON
:
604 if (kx
== GNUTLS_KX_ANON_ECDH
)
605 print_ecdh_info (session
, "Anonymous ");
607 print_dh_info (session
, "Anonymous ", verbose
);
612 /* This should be only called in server
615 if (gnutls_srp_server_get_username (session
) != NULL
)
616 printf ("- SRP authentication. Connected as '%s'\n",
617 gnutls_srp_server_get_username (session
));
622 /* This returns NULL in server side.
624 if (gnutls_psk_client_get_hint (session
) != NULL
)
625 printf ("- PSK authentication. PSK hint '%s'\n",
626 gnutls_psk_client_get_hint (session
));
627 /* This returns NULL in client side.
629 if (gnutls_psk_server_get_username (session
) != NULL
)
630 printf ("- PSK authentication. Connected as '%s'\n",
631 gnutls_psk_server_get_username (session
));
632 if (kx
== GNUTLS_KX_DHE_PSK
)
633 print_dh_info (session
, "Ephemeral ", verbose
);
634 if (kx
== GNUTLS_KX_ECDHE_PSK
)
635 print_ecdh_info (session
, "Ephemeral ");
639 printf ("- TLS/IA authentication\n");
641 case GNUTLS_CRD_CERTIFICATE
:
644 size_t dns_size
= sizeof (dns
);
647 /* This fails in client side */
648 if (gnutls_server_name_get
649 (session
, dns
, &dns_size
, &type
, 0) == 0)
651 printf ("- Given server name[%d]: %s\n", type
, dns
);
655 print_cert_info (session
, verbose
, print_cert
);
657 if (kx
== GNUTLS_KX_DHE_RSA
|| kx
== GNUTLS_KX_DHE_DSS
)
658 print_dh_info (session
, "Ephemeral ", verbose
);
659 else if (kx
== GNUTLS_KX_ECDHE_RSA
660 || kx
== GNUTLS_KX_ECDHE_ECDSA
)
661 print_ecdh_info (session
, "Ephemeral ");
665 SU (gnutls_protocol_get_name
666 (gnutls_protocol_get_version (session
)));
667 printf ("- Version: %s\n", tmp
);
669 tmp
= SU (gnutls_kx_get_name (kx
));
670 printf ("- Key Exchange: %s\n", tmp
);
672 tmp
= SU (gnutls_cipher_get_name (gnutls_cipher_get (session
)));
673 printf ("- Cipher: %s\n", tmp
);
675 tmp
= SU (gnutls_mac_get_name (gnutls_mac_get (session
)));
676 printf ("- MAC: %s\n", tmp
);
679 SU (gnutls_compression_get_name
680 (gnutls_compression_get (session
)));
681 printf ("- Compression: %s\n", tmp
);
688 rc
= gnutls_session_channel_binding (session
,
689 GNUTLS_CB_TLS_UNIQUE
, &cb
);
691 fprintf (stderr
, "Channel binding error: %s\n",
692 gnutls_strerror (rc
));
697 printf ("- Channel binding 'tls-unique': ");
698 for (i
= 0; i
< cb
.size
; i
++)
699 printf ("%02x", cb
.data
[i
]);
704 /* Warning: Do not print anything more here. The 'Compression:'
705 output MUST be the last non-verbose output. This is used by
706 Emacs starttls.el code. */
714 print_cert_info (gnutls_session_t session
, int verbose
, int print_cert
)
718 if (verbose
) flag
= GNUTLS_CRT_PRINT_FULL
;
719 else flag
= GNUTLS_CRT_PRINT_COMPACT
;
721 if (gnutls_certificate_client_get_request_status (session
) != 0)
722 printf ("- Server has requested a certificate.\n");
724 switch (gnutls_certificate_type_get (session
))
726 case GNUTLS_CRT_X509
:
727 print_x509_info (session
, flag
, print_cert
);
729 #ifdef ENABLE_OPENPGP
730 case GNUTLS_CRT_OPENPGP
:
731 print_openpgp_info (session
, flag
, print_cert
);
735 printf ("Unknown type\n");
741 print_cert_info_compact (gnutls_session_t session
)
744 if (gnutls_certificate_client_get_request_status (session
) != 0)
745 printf ("- Server has requested a certificate.\n");
747 switch (gnutls_certificate_type_get (session
))
749 case GNUTLS_CRT_X509
:
750 print_x509_info_compact (session
);
752 #ifdef ENABLE_OPENPGP
753 case GNUTLS_CRT_OPENPGP
:
754 print_openpgp_info_compact (session
);
758 printf ("Unknown type\n");
764 print_list (const char *priorities
, int verbose
)
772 gnutls_kx_algorithm_t kx
;
773 gnutls_cipher_algorithm_t cipher
;
774 gnutls_mac_algorithm_t mac
;
775 gnutls_protocol_t version
;
776 gnutls_priority_t pcache
;
777 const unsigned int *list
;
779 if (priorities
!= NULL
)
781 printf ("Cipher suites for %s\n", priorities
);
783 ret
= gnutls_priority_init (&pcache
, priorities
, &err
);
786 fprintf (stderr
, "Syntax error at: %s\n", err
);
793 gnutls_priority_get_cipher_suite_index (pcache
, i
,
795 if (ret
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
797 if (ret
== GNUTLS_E_UNKNOWN_CIPHER_SUITE
)
801 gnutls_cipher_suite_info (idx
, id
, NULL
, NULL
, NULL
,
805 printf ("%-50s\t0x%02x, 0x%02x\t%s\n",
806 name
, (unsigned char) id
[0],
807 (unsigned char) id
[1],
808 gnutls_protocol_get_name (version
));
813 ret
= gnutls_priority_certificate_type_list (pcache
, &list
);
815 printf ("Certificate types: ");
816 if (ret
== 0) printf("none\n");
817 for (i
= 0; i
< (unsigned)ret
; i
++)
820 gnutls_certificate_type_get_name (list
[i
]));
821 if (i
+1!=(unsigned)ret
)
829 ret
= gnutls_priority_protocol_list (pcache
, &list
);
831 printf ("Protocols: ");
832 if (ret
== 0) printf("none\n");
833 for (i
= 0; i
< (unsigned)ret
; i
++)
835 printf ("VERS-%s", gnutls_protocol_get_name (list
[i
]));
836 if (i
+1!=(unsigned)ret
)
844 ret
= gnutls_priority_compression_list (pcache
, &list
);
846 printf ("Compression: ");
847 if (ret
== 0) printf("none\n");
848 for (i
= 0; i
< (unsigned)ret
; i
++)
851 gnutls_compression_get_name (list
[i
]));
852 if (i
+1!=(unsigned)ret
)
860 ret
= gnutls_priority_ecc_curve_list (pcache
, &list
);
862 printf ("Elliptic curves: ");
863 if (ret
== 0) printf("none\n");
864 for (i
= 0; i
< (unsigned)ret
; i
++)
867 gnutls_ecc_curve_get_name (list
[i
]));
868 if (i
+1!=(unsigned)ret
)
876 ret
= gnutls_priority_sign_list (pcache
, &list
);
878 printf ("PK-signatures: ");
879 if (ret
== 0) printf("none\n");
880 for (i
= 0; i
< (unsigned)ret
; i
++)
883 gnutls_sign_algorithm_get_name (list
[i
]));
884 if (i
+1!=(unsigned)ret
)
894 printf ("Cipher suites:\n");
895 for (i
= 0; (name
= gnutls_cipher_suite_info
896 (i
, id
, &kx
, &cipher
, &mac
, &version
)); i
++)
898 printf ("%-50s\t0x%02x, 0x%02x\t%s\n",
900 (unsigned char) id
[0], (unsigned char) id
[1],
901 gnutls_protocol_get_name (version
));
903 printf ("\tKey exchange: %s\n\tCipher: %s\n\tMAC: %s\n\n",
904 gnutls_kx_get_name (kx
),
905 gnutls_cipher_get_name (cipher
),
906 gnutls_mac_get_name (mac
));
911 const gnutls_certificate_type_t
*p
=
912 gnutls_certificate_type_list ();
914 printf ("Certificate types: ");
917 printf ("CTYPE-%s", gnutls_certificate_type_get_name (*p
));
926 const gnutls_protocol_t
*p
= gnutls_protocol_list ();
928 printf ("Protocols: ");
931 printf ("VERS-%s", gnutls_protocol_get_name (*p
));
940 const gnutls_cipher_algorithm_t
*p
= gnutls_cipher_list ();
942 printf ("Ciphers: ");
945 printf ("%s", gnutls_cipher_get_name (*p
));
954 const gnutls_mac_algorithm_t
*p
= gnutls_mac_list ();
959 printf ("%s", gnutls_mac_get_name (*p
));
968 const gnutls_kx_algorithm_t
*p
= gnutls_kx_list ();
970 printf ("Key exchange algorithms: ");
973 printf ("%s", gnutls_kx_get_name (*p
));
982 const gnutls_compression_method_t
*p
= gnutls_compression_list ();
984 printf ("Compression: ");
987 printf ("COMP-%s", gnutls_compression_get_name (*p
));
996 const gnutls_ecc_curve_t
*p
= gnutls_ecc_curve_list ();
998 printf ("Elliptic curves: ");
1001 printf ("CURVE-%s", gnutls_ecc_curve_get_name (*p
));
1010 const gnutls_pk_algorithm_t
*p
= gnutls_pk_list ();
1012 printf ("Public Key Systems: ");
1015 printf ("%s", gnutls_pk_algorithm_get_name (*p
));
1024 const gnutls_sign_algorithm_t
*p
= gnutls_sign_list ();
1026 printf ("PK-signatures: ");
1029 printf ("SIGN-%s", gnutls_sign_algorithm_get_name (*p
));
1038 int check_command(gnutls_session_t session
, const char* str
)
1040 int len
= strlen(str
);
1042 if (len
> 2 && str
[0] == str
[1] && str
[0] == '*')
1044 if (strncmp(str
, "**REHANDSHAKE**",
1045 sizeof ("**REHANDSHAKE**") - 1) == 0)
1047 fprintf (stderr
, "*** Sending rehandshake request\n");
1048 gnutls_rehandshake (session
);