2 # include <sys/types.h>
6 #include <gnutls/gnutls.h>
7 #include <gnutls/x509.h>
8 #include <gnutls/openpgp.h>
10 #include <gnutls-common.h>
17 static char buffer
[5*1024];
19 #define PRINTX(x,y) if (y[0]!=0) printf(" # %s %s\n", x, y)
20 #define PRINT_PGP_NAME(X) PRINTX( "NAME:", name)
22 const char str_unknown
[] = "(unknown)";
24 static const char *my_ctime(const time_t * tv
)
29 if ( ( (tp
= localtime(tv
)) == NULL
) ||
30 (!strftime(buf
, sizeof buf
, "%a %b %e %H:%M:%S %Z %Y\n", tp
)) )
31 strcpy(buf
, str_unknown
);/* make sure buf text isn't garbage */
37 void print_x509_info(gnutls_session_t session
, const char* hostname
)
39 gnutls_x509_crt_t crt
;
40 const gnutls_datum_t
*cert_list
;
41 unsigned int cert_list_size
= 0;
47 size_t digest_size
= sizeof(digest
);
49 size_t serial_size
= sizeof(serial
);
52 unsigned int bits
, algo
;
53 time_t expiret
, activet
;
55 cert_list
= gnutls_certificate_get_peers(session
, &cert_list_size
);
58 if (cert_list_size
== 0) {
59 fprintf(stderr
, "No certificates found!\n");
63 printf(" - Got a certificate list of %d certificates.\n\n",
66 for (j
= 0; j
< cert_list_size
; j
++) {
68 gnutls_x509_crt_init(&crt
);
70 gnutls_x509_crt_import(crt
, &cert_list
[j
],
73 const char* str
= gnutls_strerror(ret
);
74 if (str
== NULL
) str
= str_unknown
;
75 fprintf(stderr
, "Decoding error: %s\n", str
);
79 printf(" - Certificate[%d] info:\n", j
);
84 size
= sizeof(buffer
);
86 ret
= gnutls_x509_crt_export( crt
, GNUTLS_X509_FMT_PEM
, buffer
, &size
);
88 fprintf(stderr
, "Encoding error: %s\n", gnutls_strerror(ret
));
92 fputs( buffer
, stdout
);
96 if (j
==0 && hostname
!= NULL
) { /* Check the hostname of the first certificate
97 * if it matches the name of the host we
100 if (gnutls_x509_crt_check_hostname( crt
, hostname
)==0) {
101 printf(" # The hostname in the certificate does NOT match '%s'.\n", hostname
);
103 printf(" # The hostname in the certificate matches '%s'.\n", hostname
);
110 gnutls_datum_t xml_data
;
112 ret
= gnutls_x509_crt_to_xml( crt
, &xml_data
, 0);
114 const char* str
= gnutls_strerror(ret
);
115 if (str
== NULL
) str
= str_unknown
;
116 fprintf(stderr
, "XML encoding error: %s\n",
121 printf("%s", xml_data
.data
);
122 gnutls_free( xml_data
.data
);
126 expiret
= gnutls_x509_crt_get_expiration_time(crt
);
127 activet
= gnutls_x509_crt_get_activation_time(crt
);
129 printf(" # valid since: %s", my_ctime(&activet
));
130 printf(" # expires at: %s", my_ctime(&expiret
));
133 /* Print the serial number of the certificate.
135 if (gnutls_x509_crt_get_serial(crt
, serial
, &serial_size
)
138 for (i
= 0; i
< serial_size
; i
++) {
139 sprintf(print
, "%.2x ",
140 (unsigned char) serial
[i
]);
143 printf(" # serial number: %s\n", printable
);
146 /* Print the fingerprint of the certificate
148 digest_size
= sizeof(digest
);
149 if ((ret
=gnutls_x509_crt_get_fingerprint(crt
, GNUTLS_DIG_MD5
, digest
, &digest_size
))
151 const char* str
= gnutls_strerror(ret
);
152 if (str
== NULL
) str
= str_unknown
;
153 fprintf(stderr
, "Error in fingerprint calculation: %s\n", str
);
156 for (i
= 0; i
< digest_size
; i
++) {
157 sprintf(print
, "%.2x ",
158 (unsigned char) digest
[i
]);
161 printf(" # fingerprint: %s\n", printable
);
164 /* Print the version of the X.509
167 printf(" # version: #%d\n",
168 gnutls_x509_crt_get_version(crt
));
170 algo
= gnutls_x509_crt_get_pk_algorithm(crt
, &bits
);
171 printf(" # public key algorithm: ");
172 if (algo
== GNUTLS_PK_RSA
) {
174 printf(" # Modulus: %d bits\n", bits
);
175 } else if (algo
== GNUTLS_PK_DSA
) {
177 printf(" # Exponent: %d bits\n", bits
);
182 dn_size
= sizeof(dn
);
183 ret
= gnutls_x509_crt_get_dn(crt
, dn
, &dn_size
);
185 printf(" # Subject's DN: %s\n", dn
);
187 dn_size
= sizeof(dn
);
188 ret
= gnutls_x509_crt_get_issuer_dn(crt
, dn
, &dn_size
);
190 printf(" # Issuer's DN: %s\n", dn
);
193 gnutls_x509_crt_deinit(crt
);
201 #ifdef HAVE_LIBOPENCDK
203 void print_openpgp_info(gnutls_session_t session
, const char* hostname
)
207 size_t digest_size
= sizeof(digest
);
213 size_t name_len
= sizeof(name
);
214 gnutls_openpgp_key crt
;
215 const gnutls_datum_t
*cert_list
;
216 unsigned int cert_list_size
= 0;
220 cert_list
= gnutls_certificate_get_peers(session
, &cert_list_size
);
222 if (cert_list_size
> 0) {
223 unsigned int algo
, bits
;
225 gnutls_openpgp_key_init(&crt
);
227 gnutls_openpgp_key_import(crt
, &cert_list
[0], GNUTLS_OPENPGP_FMT_RAW
);
229 const char* str
= gnutls_strerror(ret
);
230 if (str
== NULL
) str
= str_unknown
;
231 fprintf(stderr
, "Decoding error: %s\n", str
);
238 size
= sizeof(buffer
);
240 ret
= gnutls_openpgp_key_export( crt
, GNUTLS_OPENPGP_FMT_BASE64
, buffer
, &size
);
242 fprintf(stderr
, "Encoding error: %s\n", gnutls_strerror(ret
));
245 fputs( "\n", stdout
);
246 fputs( buffer
, stdout
);
247 fputs( "\n", stdout
);
250 if (hostname
!= NULL
) { /* Check the hostname of the first certificate
251 * if it matches the name of the host we
254 if (gnutls_openpgp_key_check_hostname( crt
, hostname
)==0) {
255 printf(" # The hostname in the key does NOT match '%s'.\n", hostname
);
257 printf(" # The hostname in the key matches '%s'.\n", hostname
);
262 gnutls_datum_t xml_data
;
264 ret
= gnutls_openpgp_key_to_xml( crt
, &xml_data
, 0);
266 const char* str
= gnutls_strerror(ret
);
267 if (str
== NULL
) str
= str_unknown
;
268 fprintf(stderr
, "XML encoding error: %s\n",
273 printf("%s", xml_data
.data
);
274 gnutls_free( xml_data
.data
);
279 activet
= gnutls_openpgp_key_get_creation_time( crt
);
280 expiret
= gnutls_openpgp_key_get_expiration_time( crt
);
282 printf(" # Key was created at: %s", my_ctime(&activet
));
283 printf(" # Key expires: ");
285 printf("%s", my_ctime(&expiret
));
289 if (gnutls_openpgp_key_get_fingerprint(crt
, digest
, &digest_size
) >= 0)
292 for (i
= 0; i
< digest_size
; i
++) {
293 sprintf(print
, "%.2x ",
294 (unsigned char) digest
[i
]);
298 printf(" # PGP Key version: %d\n",
299 gnutls_openpgp_key_get_version(crt
));
302 gnutls_openpgp_key_get_pk_algorithm(crt
, &bits
);
304 printf(" # PGP Key public key algorithm: ");
306 if (algo
== GNUTLS_PK_RSA
) {
308 printf(" # Modulus: %d bits\n", bits
);
309 } else if (algo
== GNUTLS_PK_DSA
) {
311 printf(" # Exponent: %d bits\n", bits
);
316 printf(" # PGP Key fingerprint: %s\n", printable
);
318 name_len
= sizeof(name
);
319 if (gnutls_openpgp_key_get_name(crt
, 0, name
, &name_len
) < 0) {
321 "Could not extract name\n");
323 PRINT_PGP_NAME(name
);
328 gnutls_openpgp_key_deinit( crt
);
335 void print_cert_vrfy(gnutls_session_t session
)
341 ret
= gnutls_certificate_verify_peers2(session
, &status
);
347 if (ret
== GNUTLS_E_NO_CERTIFICATE_FOUND
)
348 printf("- Peer did not send any certificate.\n");
350 printf("- Could not verify certificate (err: %s (%d))\n",
351 gnutls_strerror(ret
), ret
);
355 if (gnutls_certificate_type_get(session
)==GNUTLS_CRT_X509
) {
356 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
357 printf("- Peer's certificate issuer is unknown\n");
358 if (status
& GNUTLS_CERT_INVALID
)
359 printf("- Peer's certificate is NOT trusted\n");
361 printf("- Peer's certificate is trusted\n");
363 if (status
& GNUTLS_CERT_INVALID
)
364 printf("- Peer's key is invalid\n");
366 printf("- Peer's key is valid\n");
367 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
368 printf("- Could not find a signer of the peer's key\n");
372 int print_info(gnutls_session_t session
, const char* hostname
)
375 gnutls_credentials_type_t cred
;
376 gnutls_kx_algorithm_t kx
;
379 /* print the key exchange's algorithm name
381 kx
= gnutls_kx_get(session
);
383 cred
= gnutls_auth_get_type(session
);
386 case GNUTLS_CRD_ANON
:
387 printf("- Anonymous DH using prime of %d bits, secret key "
388 "of %d bits, and peer's public key is %d bits.\n",
389 gnutls_dh_get_prime_bits(session
),
390 gnutls_dh_get_secret_bits(session
),
391 gnutls_dh_get_peers_public_bits(session
));
396 /* This should be only called in server
399 if (gnutls_srp_server_get_username(session
) != NULL
)
400 printf("- SRP authentication. Connected as '%s'\n",
401 gnutls_srp_server_get_username(session
));
404 case GNUTLS_CRD_CERTIFICATE
:
407 size_t dns_size
= sizeof(dns
);
410 /* This fails in client side */
411 if (gnutls_server_name_get
412 (session
, dns
, &dns_size
, &type
, 0) == 0) {
413 printf("- Given server name[%d]: %s\n",
418 print_cert_info(session
, hostname
);
420 print_cert_vrfy(session
);
422 /* Check if we have been using ephemeral Diffie Hellman.
424 if (kx
== GNUTLS_KX_DHE_RSA
|| kx
== GNUTLS_KX_DHE_DSS
) {
426 ("- Ephemeral DH using prime of %d bits, secret key "
427 "of %d bits, and peer's public key is %d bits.\n",
428 gnutls_dh_get_prime_bits(session
),
429 gnutls_dh_get_secret_bits(session
),
430 gnutls_dh_get_peers_public_bits(session
));
437 gnutls_protocol_get_name(gnutls_protocol_get_version(session
));
438 if (tmp
!= NULL
) printf("- Version: %s\n", tmp
);
440 tmp
= gnutls_kx_get_name(kx
);
441 if (tmp
!= NULL
) printf("- Key Exchange: %s\n", tmp
);
443 tmp
= gnutls_cipher_get_name(gnutls_cipher_get(session
));
444 if (tmp
!= NULL
) printf("- Cipher: %s\n", tmp
);
446 tmp
= gnutls_mac_get_name(gnutls_mac_get(session
));
447 if (tmp
!= NULL
) printf("- MAC: %s\n", tmp
);
449 tmp
= gnutls_compression_get_name(gnutls_compression_get(session
));
450 if (tmp
!= NULL
) printf("- Compression: %s\n", tmp
);
457 void print_cert_info(gnutls_session_t session
, const char* hostname
)
460 printf("- Certificate type: ");
461 switch (gnutls_certificate_type_get(session
)) {
462 case GNUTLS_CRT_X509
:
464 print_x509_info(session
, hostname
);
466 #ifdef HAVE_LIBOPENCDK
467 case GNUTLS_CRT_OPENPGP
:
469 print_openpgp_info(session
, hostname
);
478 void print_list(void)
480 /* FIXME: This is hard coded. Make it print all the supported
484 printf("Certificate types:");
486 printf(", OPENPGP\n");
488 printf("Protocols:");
490 printf(", SSL3.0\n");
493 printf(" AES-128-CBC");
494 printf(", 3DES-CBC");
496 printf(", ARCFOUR-40\n");
503 printf("Key exchange algorithms:");
505 printf(", RSA-EXPORT");
511 printf(", ANON-DH\n");
513 printf("Compression methods:");
518 void print_license(void)
521 "\nCopyright (C) 2001-2003 Nikos Mavroyanopoulos\n"
522 "This program is free software; you can redistribute it and/or modify \n"
523 "it under the terms of the GNU General Public License as published by \n"
524 "the Free Software Foundation; either version 2 of the License, or \n"
525 "(at your option) any later version. \n" "\n"
526 "This program is distributed in the hope that it will be useful, \n"
527 "but WITHOUT ANY WARRANTY; without even the implied warranty of \n"
528 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n"
529 "GNU General Public License for more details. \n" "\n"
530 "You should have received a copy of the GNU General Public License \n"
531 "along with this program; if not, write to the Free Software \n"
532 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n");
535 void parse_protocols(char **protocols
, int protocols_size
,
536 int *protocol_priority
)
540 if (protocols
!= NULL
&& protocols_size
> 0) {
541 for (j
= i
= 0; i
< protocols_size
; i
++) {
542 if (strncasecmp(protocols
[i
], "SSL", 3) == 0)
543 protocol_priority
[j
++] = GNUTLS_SSL3
;
544 if (strncasecmp(protocols
[i
], "TLS", 3) == 0)
545 protocol_priority
[j
++] = GNUTLS_TLS1
;
547 protocol_priority
[j
] = 0;
551 void parse_ciphers(char **ciphers
, int nciphers
, int *cipher_priority
)
555 if (ciphers
!= NULL
&& nciphers
> 0) {
556 for (j
= i
= 0; i
< nciphers
; i
++) {
557 if (strncasecmp(ciphers
[i
], "AES", 3) == 0)
558 cipher_priority
[j
++] =
559 GNUTLS_CIPHER_AES_128_CBC
;
560 if (strncasecmp(ciphers
[i
], "3DE", 3) == 0)
561 cipher_priority
[j
++] =
562 GNUTLS_CIPHER_3DES_CBC
;
563 if (strcasecmp(ciphers
[i
], "ARCFOUR-40") == 0)
564 cipher_priority
[j
++] =
565 GNUTLS_CIPHER_ARCFOUR_40
;
566 if (strcasecmp(ciphers
[i
], "ARCFOUR") == 0)
567 cipher_priority
[j
++] =
568 GNUTLS_CIPHER_ARCFOUR_128
;
569 if (strncasecmp(ciphers
[i
], "NUL", 3) == 0)
570 cipher_priority
[j
++] = GNUTLS_CIPHER_NULL
;
572 cipher_priority
[j
] = 0;
576 void parse_macs(char **macs
, int nmacs
, int *mac_priority
)
579 if (macs
!= NULL
&& nmacs
> 0) {
580 for (j
= i
= 0; i
< nmacs
; i
++) {
581 if (strncasecmp(macs
[i
], "MD5", 3) == 0)
582 mac_priority
[j
++] = GNUTLS_MAC_MD5
;
583 if (strncasecmp(macs
[i
], "RMD", 3) == 0)
584 mac_priority
[j
++] = GNUTLS_MAC_RMD160
;
585 if (strncasecmp(macs
[i
], "SHA", 3) == 0)
586 mac_priority
[j
++] = GNUTLS_MAC_SHA
;
592 void parse_ctypes(char **ctype
, int nctype
, int *cert_type_priority
)
595 if (ctype
!= NULL
&& nctype
> 0) {
596 for (j
= i
= 0; i
< nctype
; i
++) {
597 if (strncasecmp(ctype
[i
], "OPE", 3) == 0)
598 cert_type_priority
[j
++] =
600 if (strncasecmp(ctype
[i
], "X", 1) == 0)
601 cert_type_priority
[j
++] = GNUTLS_CRT_X509
;
603 cert_type_priority
[j
] = 0;
607 void parse_kx(char **kx
, int nkx
, int *kx_priority
)
610 if (kx
!= NULL
&& nkx
> 0) {
611 for (j
= i
= 0; i
< nkx
; i
++) {
612 if (strcasecmp(kx
[i
], "SRP") == 0)
613 kx_priority
[j
++] = GNUTLS_KX_SRP
;
614 if (strcasecmp(kx
[i
], "SRP-RSA") == 0)
615 kx_priority
[j
++] = GNUTLS_KX_SRP_RSA
;
616 if (strcasecmp(kx
[i
], "SRP-DSS") == 0)
617 kx_priority
[j
++] = GNUTLS_KX_SRP_DSS
;
618 if (strcasecmp(kx
[i
], "RSA") == 0)
619 kx_priority
[j
++] = GNUTLS_KX_RSA
;
620 if (strcasecmp(kx
[i
], "RSA-EXPORT") == 0)
621 kx_priority
[j
++] = GNUTLS_KX_RSA_EXPORT
;
622 if (strncasecmp(kx
[i
], "DHE-RSA", 7) == 0)
623 kx_priority
[j
++] = GNUTLS_KX_DHE_RSA
;
624 if (strncasecmp(kx
[i
], "DHE-DSS", 7) == 0)
625 kx_priority
[j
++] = GNUTLS_KX_DHE_DSS
;
626 if (strncasecmp(kx
[i
], "ANON", 4) == 0)
627 kx_priority
[j
++] = GNUTLS_KX_ANON_DH
;
633 void parse_comp(char **comp
, int ncomp
, int *comp_priority
)
636 if (comp
!= NULL
&& ncomp
> 0) {
637 for (j
= i
= 0; i
< ncomp
; i
++) {
638 if (strncasecmp(comp
[i
], "NUL", 3) == 0)
639 comp_priority
[j
++] = GNUTLS_COMP_NULL
;
640 if (strncasecmp(comp
[i
], "ZLI", 3) == 0)
641 comp_priority
[j
++] = GNUTLS_COMP_ZLIB
;
643 comp_priority
[j
] = 0;
648 #ifndef HAVE_INET_NTOP
651 # include <winsock.h>
653 # include <sys/socket.h>
654 # include <netinet/in.h>
655 # include <arpa/inet.h>
658 const char *inet_ntop(int af
__attribute__((unused
)), const void *src
,
659 char *dst
, size_t cnt
)
663 ret
= inet_ntoa( *((struct in_addr
*)src
));
665 if (strlen(ret
) > cnt
) {
674 void sockets_init( void)
677 WORD wVersionRequested
;
680 wVersionRequested
= MAKEWORD(1, 1);
681 if (WSAStartup(wVersionRequested
, &wsaData
) != 0) {
682 perror("WSA_STARTUP_ERROR");