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 unsigned int cert_list_size
= 0;
48 size_t digest_size
= sizeof(digest
);
50 size_t serial_size
= sizeof(serial
);
53 unsigned int bits
, algo
;
54 time_t expiret
, activet
;
56 cert_list
= gnutls_certificate_get_peers(session
, &cert_list_size
);
59 if (cert_list_size
== 0) {
60 fprintf(stderr
, "No certificates found!\n");
64 printf(" - Got a certificate list of %d certificates.\n\n",
67 for (j
= 0; j
< cert_list_size
; j
++) {
69 gnutls_x509_crt_init(&crt
);
71 gnutls_x509_crt_import(crt
, &cert_list
[j
],
74 const char* str
= gnutls_strerror(ret
);
75 if (str
== NULL
) str
= str_unknown
;
76 fprintf(stderr
, "Decoding error: %s\n", str
);
80 printf(" - Certificate[%d] info:\n", j
);
85 size
= sizeof(buffer
);
87 ret
= gnutls_x509_crt_export( crt
, GNUTLS_X509_FMT_PEM
, buffer
, &size
);
89 fprintf(stderr
, "Encoding error: %s\n", gnutls_strerror(ret
));
93 fputs( buffer
, stdout
);
97 if (j
==0 && hostname
!= NULL
) { /* Check the hostname of the first certificate
98 * if it matches the name of the host we
101 if (gnutls_x509_crt_check_hostname( crt
, hostname
)==0) {
102 printf(" # The hostname in the certificate does NOT match '%s'.\n", hostname
);
104 printf(" # The hostname in the certificate matches '%s'.\n", hostname
);
111 gnutls_datum xml_data
;
113 ret
= gnutls_x509_crt_to_xml( crt
, &xml_data
, 0);
115 const char* str
= gnutls_strerror(ret
);
116 if (str
== NULL
) str
= str_unknown
;
117 fprintf(stderr
, "XML encoding error: %s\n",
122 printf("%s", xml_data
.data
);
123 gnutls_free( xml_data
.data
);
127 expiret
= gnutls_x509_crt_get_expiration_time(crt
);
128 activet
= gnutls_x509_crt_get_activation_time(crt
);
130 printf(" # valid since: %s", my_ctime(&activet
));
131 printf(" # expires at: %s", my_ctime(&expiret
));
134 /* Print the serial number of the certificate.
136 if (gnutls_x509_crt_get_serial(crt
, serial
, &serial_size
)
139 for (i
= 0; i
< serial_size
; i
++) {
140 sprintf(print
, "%.2x ",
141 (unsigned char) serial
[i
]);
144 printf(" # serial number: %s\n", printable
);
147 /* Print the fingerprint of the certificate
149 digest_size
= sizeof(digest
);
150 if ((ret
=gnutls_x509_crt_get_fingerprint(crt
, GNUTLS_DIG_MD5
, digest
, &digest_size
))
152 const char* str
= gnutls_strerror(ret
);
153 if (str
== NULL
) str
= str_unknown
;
154 fprintf(stderr
, "Error in fingerprint calculation: %s\n", str
);
157 for (i
= 0; i
< digest_size
; i
++) {
158 sprintf(print
, "%.2x ",
159 (unsigned char) digest
[i
]);
162 printf(" # fingerprint: %s\n", printable
);
165 /* Print the version of the X.509
168 printf(" # version: #%d\n",
169 gnutls_x509_crt_get_version(crt
));
171 algo
= gnutls_x509_crt_get_pk_algorithm(crt
, &bits
);
172 printf(" # public key algorithm: ");
173 if (algo
== GNUTLS_PK_RSA
) {
175 printf(" # Modulus: %d bits\n", bits
);
176 } else if (algo
== GNUTLS_PK_DSA
) {
178 printf(" # Exponent: %d bits\n", bits
);
183 dn_size
= sizeof(dn
);
184 ret
= gnutls_x509_crt_get_dn(crt
, dn
, &dn_size
);
186 printf(" # Subject's DN: %s\n", dn
);
188 dn_size
= sizeof(dn
);
189 ret
= gnutls_x509_crt_get_issuer_dn(crt
, dn
, &dn_size
);
191 printf(" # Issuer's DN: %s\n", dn
);
194 gnutls_x509_crt_deinit(crt
);
202 #ifdef HAVE_LIBOPENCDK
204 void print_openpgp_info(gnutls_session session
, const char* hostname
)
208 size_t digest_size
= sizeof(digest
);
214 size_t name_len
= sizeof(name
);
215 gnutls_openpgp_key crt
;
216 const gnutls_datum
*cert_list
;
217 unsigned int cert_list_size
= 0;
221 cert_list
= gnutls_certificate_get_peers(session
, &cert_list_size
);
223 if (cert_list_size
> 0) {
224 unsigned int algo
, bits
;
226 gnutls_openpgp_key_init(&crt
);
228 gnutls_openpgp_key_import(crt
, &cert_list
[0], GNUTLS_OPENPGP_FMT_RAW
);
230 const char* str
= gnutls_strerror(ret
);
231 if (str
== NULL
) str
= str_unknown
;
232 fprintf(stderr
, "Decoding error: %s\n", str
);
239 size
= sizeof(buffer
);
241 ret
= gnutls_openpgp_key_export( crt
, GNUTLS_OPENPGP_FMT_BASE64
, buffer
, &size
);
243 fprintf(stderr
, "Encoding error: %s\n", gnutls_strerror(ret
));
246 fputs( "\n", stdout
);
247 fputs( buffer
, stdout
);
248 fputs( "\n", stdout
);
251 if (hostname
!= NULL
) { /* Check the hostname of the first certificate
252 * if it matches the name of the host we
255 if (gnutls_openpgp_key_check_hostname( crt
, hostname
)==0) {
256 printf(" # The hostname in the key does NOT match '%s'.\n", hostname
);
258 printf(" # The hostname in the key matches '%s'.\n", hostname
);
263 gnutls_datum xml_data
;
265 ret
= gnutls_openpgp_key_to_xml( crt
, &xml_data
, 0);
267 const char* str
= gnutls_strerror(ret
);
268 if (str
== NULL
) str
= str_unknown
;
269 fprintf(stderr
, "XML encoding error: %s\n",
274 printf("%s", xml_data
.data
);
275 gnutls_free( xml_data
.data
);
280 activet
= gnutls_openpgp_key_get_creation_time( crt
);
281 expiret
= gnutls_openpgp_key_get_expiration_time( crt
);
283 printf(" # Key was created at: %s", my_ctime(&activet
));
284 printf(" # Key expires: ");
286 printf("%s", my_ctime(&expiret
));
290 if (gnutls_openpgp_key_get_fingerprint(crt
, digest
, &digest_size
) >= 0)
293 for (i
= 0; i
< digest_size
; i
++) {
294 sprintf(print
, "%.2x ",
295 (unsigned char) digest
[i
]);
299 printf(" # PGP Key version: %d\n",
300 gnutls_openpgp_key_get_version(crt
));
303 gnutls_openpgp_key_get_pk_algorithm(crt
, &bits
);
305 printf(" # PGP Key public key algorithm: ");
307 if (algo
== GNUTLS_PK_RSA
) {
309 printf(" # Modulus: %d bits\n", bits
);
310 } else if (algo
== GNUTLS_PK_DSA
) {
312 printf(" # Exponent: %d bits\n", bits
);
317 printf(" # PGP Key fingerprint: %s\n", printable
);
319 name_len
= sizeof(name
);
320 if (gnutls_openpgp_key_get_name(crt
, 0, name
, &name_len
) < 0) {
322 "Could not extract name\n");
324 PRINT_PGP_NAME(name
);
329 gnutls_openpgp_key_deinit( crt
);
336 void print_cert_vrfy(gnutls_session session
)
342 ret
= gnutls_certificate_verify_peers2(session
, &status
);
348 if (ret
== GNUTLS_E_NO_CERTIFICATE_FOUND
)
349 printf("- Peer did not send any certificate.\n");
351 printf("- Could not verify certificate (err: %s (%d))\n",
352 gnutls_strerror(ret
), ret
);
356 if (gnutls_certificate_type_get(session
)==GNUTLS_CRT_X509
) {
357 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
358 printf("- Peer's certificate issuer is unknown\n");
359 if (status
& GNUTLS_CERT_INVALID
)
360 printf("- Peer's certificate is NOT trusted\n");
362 printf("- Peer's certificate is trusted\n");
364 if (status
& GNUTLS_CERT_INVALID
)
365 printf("- Peer's key is invalid\n");
367 printf("- Peer's key is valid\n");
368 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
369 printf("- Could not find a signer of the peer's key\n");
373 int print_info(gnutls_session session
, const char* hostname
)
376 gnutls_credentials_type cred
;
377 gnutls_kx_algorithm kx
;
380 /* print the key exchange's algorithm name
382 kx
= gnutls_kx_get(session
);
384 cred
= gnutls_auth_get_type(session
);
387 case GNUTLS_CRD_ANON
:
388 printf("- Anonymous DH using prime of %d bits, secret key "
389 "of %d bits, and peer's public key is %d bits.\n",
390 gnutls_dh_get_prime_bits(session
),
391 gnutls_dh_get_secret_bits(session
),
392 gnutls_dh_get_peers_public_bits(session
));
397 /* This should be only called in server
400 if (gnutls_srp_server_get_username(session
) != NULL
)
401 printf("- SRP authentication. Connected as '%s'\n",
402 gnutls_srp_server_get_username(session
));
405 case GNUTLS_CRD_CERTIFICATE
:
408 size_t dns_size
= sizeof(dns
);
411 /* This fails in client side */
412 if (gnutls_server_name_get
413 (session
, dns
, &dns_size
, &type
, 0) == 0) {
414 printf("- Given server name[%d]: %s\n",
419 print_cert_info(session
, hostname
);
421 print_cert_vrfy(session
);
423 /* Check if we have been using ephemeral Diffie Hellman.
425 if (kx
== GNUTLS_KX_DHE_RSA
|| kx
== GNUTLS_KX_DHE_DSS
) {
427 ("- Ephemeral DH using prime of %d bits, secret key "
428 "of %d bits, and peer's public key is %d bits.\n",
429 gnutls_dh_get_prime_bits(session
),
430 gnutls_dh_get_secret_bits(session
),
431 gnutls_dh_get_peers_public_bits(session
));
438 gnutls_protocol_get_name(gnutls_protocol_get_version(session
));
439 if (tmp
!= NULL
) printf("- Version: %s\n", tmp
);
441 tmp
= gnutls_kx_get_name(kx
);
442 if (tmp
!= NULL
) printf("- Key Exchange: %s\n", tmp
);
444 tmp
= gnutls_cipher_get_name(gnutls_cipher_get(session
));
445 if (tmp
!= NULL
) printf("- Cipher: %s\n", tmp
);
447 tmp
= gnutls_mac_get_name(gnutls_mac_get(session
));
448 if (tmp
!= NULL
) printf("- MAC: %s\n", tmp
);
450 tmp
= gnutls_compression_get_name(gnutls_compression_get(session
));
451 if (tmp
!= NULL
) printf("- Compression: %s\n", tmp
);
458 void print_cert_info(gnutls_session session
, const char* hostname
)
461 printf("- Certificate type: ");
462 switch (gnutls_certificate_type_get(session
)) {
463 case GNUTLS_CRT_X509
:
465 print_x509_info(session
, hostname
);
467 #ifdef HAVE_LIBOPENCDK
468 case GNUTLS_CRT_OPENPGP
:
470 print_openpgp_info(session
, hostname
);
479 void print_list(void)
481 /* FIXME: This is hard coded. Make it print all the supported
485 printf("Certificate types:");
487 printf(", OPENPGP\n");
489 printf("Protocols:");
491 printf(", SSL3.0\n");
494 printf(" AES-128-CBC");
495 printf(", 3DES-CBC");
497 printf(", ARCFOUR-40\n");
504 printf("Key exchange algorithms:");
506 printf(", RSA-EXPORT");
512 printf(", ANON-DH\n");
514 printf("Compression methods:");
520 void print_license(void)
523 "\nCopyright (C) 2001-2003 Nikos Mavroyanopoulos\n"
524 "This program is free software; you can redistribute it and/or modify \n"
525 "it under the terms of the GNU General Public License as published by \n"
526 "the Free Software Foundation; either version 2 of the License, or \n"
527 "(at your option) any later version. \n" "\n"
528 "This program is distributed in the hope that it will be useful, \n"
529 "but WITHOUT ANY WARRANTY; without even the implied warranty of \n"
530 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n"
531 "GNU General Public License for more details. \n" "\n"
532 "You should have received a copy of the GNU General Public License \n"
533 "along with this program; if not, write to the Free Software \n"
534 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n");
537 void parse_protocols(char **protocols
, int protocols_size
,
538 int *protocol_priority
)
542 if (protocols
!= NULL
&& protocols_size
> 0) {
543 for (j
= i
= 0; i
< protocols_size
; i
++) {
544 if (strncasecmp(protocols
[i
], "SSL", 3) == 0)
545 protocol_priority
[j
++] = GNUTLS_SSL3
;
546 if (strncasecmp(protocols
[i
], "TLS", 3) == 0)
547 protocol_priority
[j
++] = GNUTLS_TLS1
;
549 protocol_priority
[j
] = 0;
553 void parse_ciphers(char **ciphers
, int nciphers
, int *cipher_priority
)
557 if (ciphers
!= NULL
&& nciphers
> 0) {
558 for (j
= i
= 0; i
< nciphers
; i
++) {
559 if (strncasecmp(ciphers
[i
], "AES", 3) == 0)
560 cipher_priority
[j
++] =
561 GNUTLS_CIPHER_AES_128_CBC
;
562 if (strncasecmp(ciphers
[i
], "3DE", 3) == 0)
563 cipher_priority
[j
++] =
564 GNUTLS_CIPHER_3DES_CBC
;
565 if (strcasecmp(ciphers
[i
], "ARCFOUR-40") == 0)
566 cipher_priority
[j
++] =
567 GNUTLS_CIPHER_ARCFOUR_40
;
568 if (strcasecmp(ciphers
[i
], "ARCFOUR") == 0)
569 cipher_priority
[j
++] =
570 GNUTLS_CIPHER_ARCFOUR_128
;
571 if (strncasecmp(ciphers
[i
], "NUL", 3) == 0)
572 cipher_priority
[j
++] = GNUTLS_CIPHER_NULL
;
574 cipher_priority
[j
] = 0;
578 void parse_macs(char **macs
, int nmacs
, int *mac_priority
)
581 if (macs
!= NULL
&& nmacs
> 0) {
582 for (j
= i
= 0; i
< nmacs
; i
++) {
583 if (strncasecmp(macs
[i
], "MD5", 3) == 0)
584 mac_priority
[j
++] = GNUTLS_MAC_MD5
;
585 if (strncasecmp(macs
[i
], "RMD", 3) == 0)
586 mac_priority
[j
++] = GNUTLS_MAC_RMD160
;
587 if (strncasecmp(macs
[i
], "SHA", 3) == 0)
588 mac_priority
[j
++] = GNUTLS_MAC_SHA
;
594 void parse_ctypes(char **ctype
, int nctype
, int *cert_type_priority
)
597 if (ctype
!= NULL
&& nctype
> 0) {
598 for (j
= i
= 0; i
< nctype
; i
++) {
599 if (strncasecmp(ctype
[i
], "OPE", 3) == 0)
600 cert_type_priority
[j
++] =
602 if (strncasecmp(ctype
[i
], "X", 1) == 0)
603 cert_type_priority
[j
++] = GNUTLS_CRT_X509
;
605 cert_type_priority
[j
] = 0;
609 void parse_kx(char **kx
, int nkx
, int *kx_priority
)
612 if (kx
!= NULL
&& nkx
> 0) {
613 for (j
= i
= 0; i
< nkx
; i
++) {
614 if (strcasecmp(kx
[i
], "SRP") == 0)
615 kx_priority
[j
++] = GNUTLS_KX_SRP
;
616 if (strcasecmp(kx
[i
], "SRP-RSA") == 0)
617 kx_priority
[j
++] = GNUTLS_KX_SRP_RSA
;
618 if (strcasecmp(kx
[i
], "SRP-DSS") == 0)
619 kx_priority
[j
++] = GNUTLS_KX_SRP_DSS
;
620 if (strcasecmp(kx
[i
], "RSA") == 0)
621 kx_priority
[j
++] = GNUTLS_KX_RSA
;
622 if (strcasecmp(kx
[i
], "RSA-EXPORT") == 0)
623 kx_priority
[j
++] = GNUTLS_KX_RSA_EXPORT
;
624 if (strncasecmp(kx
[i
], "DHE-RSA", 7) == 0)
625 kx_priority
[j
++] = GNUTLS_KX_DHE_RSA
;
626 if (strncasecmp(kx
[i
], "DHE-DSS", 7) == 0)
627 kx_priority
[j
++] = GNUTLS_KX_DHE_DSS
;
628 if (strncasecmp(kx
[i
], "ANON", 4) == 0)
629 kx_priority
[j
++] = GNUTLS_KX_ANON_DH
;
635 void parse_comp(char **comp
, int ncomp
, int *comp_priority
)
638 if (comp
!= NULL
&& ncomp
> 0) {
639 for (j
= i
= 0; i
< ncomp
; i
++) {
640 if (strncasecmp(comp
[i
], "NUL", 3) == 0)
641 comp_priority
[j
++] = GNUTLS_COMP_NULL
;
642 if (strncasecmp(comp
[i
], "ZLI", 3) == 0)
643 comp_priority
[j
++] = GNUTLS_COMP_ZLIB
;
644 if (strncasecmp(comp
[i
], "LZO", 3) == 0)
645 comp_priority
[j
++] = GNUTLS_COMP_LZO
;
647 comp_priority
[j
] = 0;
652 #ifndef HAVE_INET_NTOP
655 # include <winsock.h>
657 # include <sys/socket.h>
658 # include <netinet/in.h>
659 # include <arpa/inet.h>
662 const char *inet_ntop(int af
__attribute__((unused
)), const void *src
,
663 char *dst
, size_t cnt
)
667 ret
= inet_ntoa( *((struct in_addr
*)src
));
669 if (strlen(ret
) > cnt
) {
678 void sockets_init( void)
681 WORD wVersionRequested
;
684 wVersionRequested
= MAKEWORD(1, 1);
685 if (WSAStartup(wVersionRequested
, &wsaData
) != 0) {
686 perror("WSA_STARTUP_ERROR");