2 # include <sys/types.h>
6 #include <gnutls/gnutls.h>
7 #include <gnutls/extra.h>
8 #include <gnutls/x509.h>
9 #include <gnutls/openpgp.h>
11 #include <gnutls-common.h>
18 static char buffer
[5*1024];
20 #define PRINTX(x,y) if (y[0]!=0) printf(" # %s %s\n", x, y)
21 #define PRINT_PGP_NAME(X) PRINTX( "NAME:", name)
23 const char str_unknown
[] = "(unknown)";
25 static const char *my_ctime(const time_t * tv
)
30 if ( ( (tp
= localtime(tv
)) == NULL
) ||
31 (!strftime(buf
, sizeof buf
, "%a %b %e %H:%M:%S %Z %Y\n", tp
)) )
32 strcpy(buf
, str_unknown
);/* make sure buf text isn't garbage */
38 void print_x509_info(gnutls_session session
, const char* hostname
)
41 const gnutls_datum
*cert_list
;
42 int cert_list_size
= 0, ret
;
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
< (unsigned int)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 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 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
*cert_list
;
216 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 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 session
)
339 status
= gnutls_certificate_verify_peers(session
);
342 if (status
== GNUTLS_E_NO_CERTIFICATE_FOUND
) {
343 printf("- Peer did not send any certificate.\n");
347 printf("- Could not verify certificate (err: %s)\n",
348 gnutls_strerror(status
));
352 if (gnutls_certificate_type_get(session
)==GNUTLS_CRT_X509
) {
353 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
354 printf("- Peer's certificate issuer is unknown\n");
355 if (status
& GNUTLS_CERT_INVALID
)
356 printf("- Peer's certificate is NOT trusted\n");
358 printf("- Peer's certificate is trusted\n");
360 if (status
& GNUTLS_CERT_INVALID
)
361 printf("- Peer's key is invalid\n");
363 printf("- Peer's key is valid\n");
364 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
365 printf("- Could not find a signer of the peer's key\n");
369 int print_info(gnutls_session session
, const char* hostname
)
372 gnutls_credentials_type cred
;
373 gnutls_kx_algorithm kx
;
376 /* print the key exchange's algorithm name
378 kx
= gnutls_kx_get(session
);
380 cred
= gnutls_auth_get_type(session
);
383 case GNUTLS_CRD_ANON
:
384 printf("- Anonymous DH using prime of %d bits, secret key "
385 "of %d bits, and peer's public key is %d bits.\n",
386 gnutls_dh_get_prime_bits(session
),
387 gnutls_dh_get_secret_bits(session
),
388 gnutls_dh_get_peers_public_bits(session
));
393 /* This should be only called in server
396 if (gnutls_srp_server_get_username(session
) != NULL
)
397 printf("- SRP authentication. Connected as '%s'\n",
398 gnutls_srp_server_get_username(session
));
401 case GNUTLS_CRD_CERTIFICATE
:
404 size_t dns_size
= sizeof(dns
);
407 /* This fails in client side */
408 if (gnutls_server_name_get
409 (session
, dns
, &dns_size
, &type
, 0) == 0) {
410 printf("- Given server name[%d]: %s\n",
415 print_cert_info(session
, hostname
);
417 print_cert_vrfy(session
);
419 /* Check if we have been using ephemeral Diffie Hellman.
421 if (kx
== GNUTLS_KX_DHE_RSA
|| kx
== GNUTLS_KX_DHE_DSS
) {
423 ("- Ephemeral DH using prime of %d bits, secret key "
424 "of %d bits, and peer's public key is %d bits.\n",
425 gnutls_dh_get_prime_bits(session
),
426 gnutls_dh_get_secret_bits(session
),
427 gnutls_dh_get_peers_public_bits(session
));
434 gnutls_protocol_get_name(gnutls_protocol_get_version(session
));
435 if (tmp
!= NULL
) printf("- Version: %s\n", tmp
);
437 tmp
= gnutls_kx_get_name(kx
);
438 if (tmp
!= NULL
) printf("- Key Exchange: %s\n", tmp
);
440 tmp
= gnutls_cipher_get_name(gnutls_cipher_get(session
));
441 if (tmp
!= NULL
) printf("- Cipher: %s\n", tmp
);
443 tmp
= gnutls_mac_get_name(gnutls_mac_get(session
));
444 if (tmp
!= NULL
) printf("- MAC: %s\n", tmp
);
446 tmp
= gnutls_compression_get_name(gnutls_compression_get(session
));
447 if (tmp
!= NULL
) printf("- Compression: %s\n", tmp
);
454 void print_cert_info(gnutls_session session
, const char* hostname
)
457 printf("- Certificate type: ");
458 switch (gnutls_certificate_type_get(session
)) {
459 case GNUTLS_CRT_X509
:
461 print_x509_info(session
, hostname
);
463 #ifdef HAVE_LIBOPENCDK
464 case GNUTLS_CRT_OPENPGP
:
466 print_openpgp_info(session
, hostname
);
475 void print_list(void)
477 /* FIXME: This is hard coded. Make it print all the supported
481 printf("Certificate types:");
483 printf(", OPENPGP\n");
485 printf("Protocols:");
487 printf(", SSL3.0\n");
490 printf(" AES-128-CBC");
491 printf(", 3DES-CBC");
493 printf(", ARCFOUR-40\n");
500 printf("Key exchange algorithms:");
502 printf(", RSA-EXPORT");
508 printf(", ANON-DH\n");
510 printf("Compression methods:");
516 void print_license(void)
519 "\nCopyright (C) 2001-2003 Nikos Mavroyanopoulos\n"
520 "This program is free software; you can redistribute it and/or modify \n"
521 "it under the terms of the GNU General Public License as published by \n"
522 "the Free Software Foundation; either version 2 of the License, or \n"
523 "(at your option) any later version. \n" "\n"
524 "This program is distributed in the hope that it will be useful, \n"
525 "but WITHOUT ANY WARRANTY; without even the implied warranty of \n"
526 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n"
527 "GNU General Public License for more details. \n" "\n"
528 "You should have received a copy of the GNU General Public License \n"
529 "along with this program; if not, write to the Free Software \n"
530 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n");
533 void parse_protocols(char **protocols
, int protocols_size
,
534 int *protocol_priority
)
538 if (protocols
!= NULL
&& protocols_size
> 0) {
539 for (j
= i
= 0; i
< protocols_size
; i
++) {
540 if (strncasecmp(protocols
[i
], "SSL", 3) == 0)
541 protocol_priority
[j
++] = GNUTLS_SSL3
;
542 if (strncasecmp(protocols
[i
], "TLS", 3) == 0)
543 protocol_priority
[j
++] = GNUTLS_TLS1
;
545 protocol_priority
[j
] = 0;
549 void parse_ciphers(char **ciphers
, int nciphers
, int *cipher_priority
)
553 if (ciphers
!= NULL
&& nciphers
> 0) {
554 for (j
= i
= 0; i
< nciphers
; i
++) {
555 if (strncasecmp(ciphers
[i
], "AES", 3) == 0)
556 cipher_priority
[j
++] =
557 GNUTLS_CIPHER_AES_128_CBC
;
558 if (strncasecmp(ciphers
[i
], "3DE", 3) == 0)
559 cipher_priority
[j
++] =
560 GNUTLS_CIPHER_3DES_CBC
;
561 if (strcasecmp(ciphers
[i
], "ARCFOUR-40") == 0)
562 cipher_priority
[j
++] =
563 GNUTLS_CIPHER_ARCFOUR_40
;
564 if (strcasecmp(ciphers
[i
], "ARCFOUR") == 0)
565 cipher_priority
[j
++] =
566 GNUTLS_CIPHER_ARCFOUR_128
;
567 if (strncasecmp(ciphers
[i
], "NUL", 3) == 0)
568 cipher_priority
[j
++] = GNUTLS_CIPHER_NULL
;
570 cipher_priority
[j
] = 0;
574 void parse_macs(char **macs
, int nmacs
, int *mac_priority
)
577 if (macs
!= NULL
&& nmacs
> 0) {
578 for (j
= i
= 0; i
< nmacs
; i
++) {
579 if (strncasecmp(macs
[i
], "MD5", 3) == 0)
580 mac_priority
[j
++] = GNUTLS_MAC_MD5
;
581 if (strncasecmp(macs
[i
], "RMD", 3) == 0)
582 mac_priority
[j
++] = GNUTLS_MAC_RMD160
;
583 if (strncasecmp(macs
[i
], "SHA", 3) == 0)
584 mac_priority
[j
++] = GNUTLS_MAC_SHA
;
590 void parse_ctypes(char **ctype
, int nctype
, int *cert_type_priority
)
593 if (ctype
!= NULL
&& nctype
> 0) {
594 for (j
= i
= 0; i
< nctype
; i
++) {
595 if (strncasecmp(ctype
[i
], "OPE", 3) == 0)
596 cert_type_priority
[j
++] =
598 if (strncasecmp(ctype
[i
], "X", 1) == 0)
599 cert_type_priority
[j
++] = GNUTLS_CRT_X509
;
601 cert_type_priority
[j
] = 0;
605 void parse_kx(char **kx
, int nkx
, int *kx_priority
)
608 if (kx
!= NULL
&& nkx
> 0) {
609 for (j
= i
= 0; i
< nkx
; i
++) {
610 if (strcasecmp(kx
[i
], "SRP") == 0)
611 kx_priority
[j
++] = GNUTLS_KX_SRP
;
612 if (strcasecmp(kx
[i
], "SRP-RSA") == 0)
613 kx_priority
[j
++] = GNUTLS_KX_SRP_RSA
;
614 if (strcasecmp(kx
[i
], "SRP-DSS") == 0)
615 kx_priority
[j
++] = GNUTLS_KX_SRP_DSS
;
616 if (strcasecmp(kx
[i
], "RSA") == 0)
617 kx_priority
[j
++] = GNUTLS_KX_RSA
;
618 if (strcasecmp(kx
[i
], "RSA-EXPORT") == 0)
619 kx_priority
[j
++] = GNUTLS_KX_RSA_EXPORT
;
620 if (strncasecmp(kx
[i
], "DHE-RSA", 7) == 0)
621 kx_priority
[j
++] = GNUTLS_KX_DHE_RSA
;
622 if (strncasecmp(kx
[i
], "DHE-DSS", 7) == 0)
623 kx_priority
[j
++] = GNUTLS_KX_DHE_DSS
;
624 if (strncasecmp(kx
[i
], "ANON", 4) == 0)
625 kx_priority
[j
++] = GNUTLS_KX_ANON_DH
;
631 void parse_comp(char **comp
, int ncomp
, int *comp_priority
)
634 if (comp
!= NULL
&& ncomp
> 0) {
635 for (j
= i
= 0; i
< ncomp
; i
++) {
636 if (strncasecmp(comp
[i
], "NUL", 3) == 0)
637 comp_priority
[j
++] = GNUTLS_COMP_NULL
;
638 if (strncasecmp(comp
[i
], "ZLI", 3) == 0)
639 comp_priority
[j
++] = GNUTLS_COMP_ZLIB
;
640 if (strncasecmp(comp
[i
], "LZO", 3) == 0)
641 comp_priority
[j
++] = GNUTLS_COMP_LZO
;
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");