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
)
340 status
= gnutls_certificate_verify_peers(session
);
343 if (status
== GNUTLS_E_NO_CERTIFICATE_FOUND
) {
344 printf("- Peer did not send any certificate.\n");
348 printf("- Could not verify certificate (err: %s)\n",
349 gnutls_strerror(status
));
353 if (gnutls_certificate_type_get(session
)==GNUTLS_CRT_X509
) {
354 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
355 printf("- Peer's certificate issuer is unknown\n");
356 if (status
& GNUTLS_CERT_INVALID
)
357 printf("- Peer's certificate is NOT trusted\n");
359 printf("- Peer's certificate is trusted\n");
361 if (status
& GNUTLS_CERT_INVALID
)
362 printf("- Peer's key is invalid\n");
364 printf("- Peer's key is valid\n");
365 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
)
366 printf("- Could not find a signer of the peer's key\n");
370 int print_info(gnutls_session session
, const char* hostname
)
373 gnutls_credentials_type cred
;
374 gnutls_kx_algorithm kx
;
377 /* print the key exchange's algorithm name
379 kx
= gnutls_kx_get(session
);
381 cred
= gnutls_auth_get_type(session
);
384 case GNUTLS_CRD_ANON
:
385 printf("- Anonymous DH using prime of %d bits, secret key "
386 "of %d bits, and peer's public key is %d bits.\n",
387 gnutls_dh_get_prime_bits(session
),
388 gnutls_dh_get_secret_bits(session
),
389 gnutls_dh_get_peers_public_bits(session
));
394 /* This should be only called in server
397 if (gnutls_srp_server_get_username(session
) != NULL
)
398 printf("- SRP authentication. Connected as '%s'\n",
399 gnutls_srp_server_get_username(session
));
402 case GNUTLS_CRD_CERTIFICATE
:
405 size_t dns_size
= sizeof(dns
);
408 /* This fails in client side */
409 if (gnutls_server_name_get
410 (session
, dns
, &dns_size
, &type
, 0) == 0) {
411 printf("- Given server name[%d]: %s\n",
416 print_cert_info(session
, hostname
);
418 print_cert_vrfy(session
);
420 /* Check if we have been using ephemeral Diffie Hellman.
422 if (kx
== GNUTLS_KX_DHE_RSA
|| kx
== GNUTLS_KX_DHE_DSS
) {
424 ("- Ephemeral DH using prime of %d bits, secret key "
425 "of %d bits, and peer's public key is %d bits.\n",
426 gnutls_dh_get_prime_bits(session
),
427 gnutls_dh_get_secret_bits(session
),
428 gnutls_dh_get_peers_public_bits(session
));
435 gnutls_protocol_get_name(gnutls_protocol_get_version(session
));
436 if (tmp
!= NULL
) printf("- Version: %s\n", tmp
);
438 tmp
= gnutls_kx_get_name(kx
);
439 if (tmp
!= NULL
) printf("- Key Exchange: %s\n", tmp
);
441 tmp
= gnutls_cipher_get_name(gnutls_cipher_get(session
));
442 if (tmp
!= NULL
) printf("- Cipher: %s\n", tmp
);
444 tmp
= gnutls_mac_get_name(gnutls_mac_get(session
));
445 if (tmp
!= NULL
) printf("- MAC: %s\n", tmp
);
447 tmp
= gnutls_compression_get_name(gnutls_compression_get(session
));
448 if (tmp
!= NULL
) printf("- Compression: %s\n", tmp
);
455 void print_cert_info(gnutls_session session
, const char* hostname
)
458 printf("- Certificate type: ");
459 switch (gnutls_certificate_type_get(session
)) {
460 case GNUTLS_CRT_X509
:
462 print_x509_info(session
, hostname
);
464 #ifdef HAVE_LIBOPENCDK
465 case GNUTLS_CRT_OPENPGP
:
467 print_openpgp_info(session
, hostname
);
476 void print_list(void)
478 /* FIXME: This is hard coded. Make it print all the supported
482 printf("Certificate types:");
484 printf(", OPENPGP\n");
486 printf("Protocols:");
488 printf(", SSL3.0\n");
491 printf(" AES-128-CBC");
492 printf(", 3DES-CBC");
494 printf(", ARCFOUR-40\n");
501 printf("Key exchange algorithms:");
503 printf(", RSA-EXPORT");
509 printf(", ANON-DH\n");
511 printf("Compression methods:");
517 void print_license(void)
520 "\nCopyright (C) 2001-2003 Nikos Mavroyanopoulos\n"
521 "This program is free software; you can redistribute it and/or modify \n"
522 "it under the terms of the GNU General Public License as published by \n"
523 "the Free Software Foundation; either version 2 of the License, or \n"
524 "(at your option) any later version. \n" "\n"
525 "This program is distributed in the hope that it will be useful, \n"
526 "but WITHOUT ANY WARRANTY; without even the implied warranty of \n"
527 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n"
528 "GNU General Public License for more details. \n" "\n"
529 "You should have received a copy of the GNU General Public License \n"
530 "along with this program; if not, write to the Free Software \n"
531 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n");
534 void parse_protocols(char **protocols
, int protocols_size
,
535 int *protocol_priority
)
539 if (protocols
!= NULL
&& protocols_size
> 0) {
540 for (j
= i
= 0; i
< protocols_size
; i
++) {
541 if (strncasecmp(protocols
[i
], "SSL", 3) == 0)
542 protocol_priority
[j
++] = GNUTLS_SSL3
;
543 if (strncasecmp(protocols
[i
], "TLS", 3) == 0)
544 protocol_priority
[j
++] = GNUTLS_TLS1
;
546 protocol_priority
[j
] = 0;
550 void parse_ciphers(char **ciphers
, int nciphers
, int *cipher_priority
)
554 if (ciphers
!= NULL
&& nciphers
> 0) {
555 for (j
= i
= 0; i
< nciphers
; i
++) {
556 if (strncasecmp(ciphers
[i
], "AES", 3) == 0)
557 cipher_priority
[j
++] =
558 GNUTLS_CIPHER_AES_128_CBC
;
559 if (strncasecmp(ciphers
[i
], "3DE", 3) == 0)
560 cipher_priority
[j
++] =
561 GNUTLS_CIPHER_3DES_CBC
;
562 if (strcasecmp(ciphers
[i
], "ARCFOUR-40") == 0)
563 cipher_priority
[j
++] =
564 GNUTLS_CIPHER_ARCFOUR_40
;
565 if (strcasecmp(ciphers
[i
], "ARCFOUR") == 0)
566 cipher_priority
[j
++] =
567 GNUTLS_CIPHER_ARCFOUR_128
;
568 if (strncasecmp(ciphers
[i
], "NUL", 3) == 0)
569 cipher_priority
[j
++] = GNUTLS_CIPHER_NULL
;
571 cipher_priority
[j
] = 0;
575 void parse_macs(char **macs
, int nmacs
, int *mac_priority
)
578 if (macs
!= NULL
&& nmacs
> 0) {
579 for (j
= i
= 0; i
< nmacs
; i
++) {
580 if (strncasecmp(macs
[i
], "MD5", 3) == 0)
581 mac_priority
[j
++] = GNUTLS_MAC_MD5
;
582 if (strncasecmp(macs
[i
], "RMD", 3) == 0)
583 mac_priority
[j
++] = GNUTLS_MAC_RMD160
;
584 if (strncasecmp(macs
[i
], "SHA", 3) == 0)
585 mac_priority
[j
++] = GNUTLS_MAC_SHA
;
591 void parse_ctypes(char **ctype
, int nctype
, int *cert_type_priority
)
594 if (ctype
!= NULL
&& nctype
> 0) {
595 for (j
= i
= 0; i
< nctype
; i
++) {
596 if (strncasecmp(ctype
[i
], "OPE", 3) == 0)
597 cert_type_priority
[j
++] =
599 if (strncasecmp(ctype
[i
], "X", 1) == 0)
600 cert_type_priority
[j
++] = GNUTLS_CRT_X509
;
602 cert_type_priority
[j
] = 0;
606 void parse_kx(char **kx
, int nkx
, int *kx_priority
)
609 if (kx
!= NULL
&& nkx
> 0) {
610 for (j
= i
= 0; i
< nkx
; i
++) {
611 if (strcasecmp(kx
[i
], "SRP") == 0)
612 kx_priority
[j
++] = GNUTLS_KX_SRP
;
613 if (strcasecmp(kx
[i
], "SRP-RSA") == 0)
614 kx_priority
[j
++] = GNUTLS_KX_SRP_RSA
;
615 if (strcasecmp(kx
[i
], "SRP-DSS") == 0)
616 kx_priority
[j
++] = GNUTLS_KX_SRP_DSS
;
617 if (strcasecmp(kx
[i
], "RSA") == 0)
618 kx_priority
[j
++] = GNUTLS_KX_RSA
;
619 if (strcasecmp(kx
[i
], "RSA-EXPORT") == 0)
620 kx_priority
[j
++] = GNUTLS_KX_RSA_EXPORT
;
621 if (strncasecmp(kx
[i
], "DHE-RSA", 7) == 0)
622 kx_priority
[j
++] = GNUTLS_KX_DHE_RSA
;
623 if (strncasecmp(kx
[i
], "DHE-DSS", 7) == 0)
624 kx_priority
[j
++] = GNUTLS_KX_DHE_DSS
;
625 if (strncasecmp(kx
[i
], "ANON", 4) == 0)
626 kx_priority
[j
++] = GNUTLS_KX_ANON_DH
;
632 void parse_comp(char **comp
, int ncomp
, int *comp_priority
)
635 if (comp
!= NULL
&& ncomp
> 0) {
636 for (j
= i
= 0; i
< ncomp
; i
++) {
637 if (strncasecmp(comp
[i
], "NUL", 3) == 0)
638 comp_priority
[j
++] = GNUTLS_COMP_NULL
;
639 if (strncasecmp(comp
[i
], "ZLI", 3) == 0)
640 comp_priority
[j
++] = GNUTLS_COMP_ZLIB
;
641 if (strncasecmp(comp
[i
], "LZO", 3) == 0)
642 comp_priority
[j
++] = GNUTLS_COMP_LZO
;
644 comp_priority
[j
] = 0;
649 #ifndef HAVE_INET_NTOP
652 # include <winsock.h>
654 # include <sys/socket.h>
655 # include <netinet/in.h>
656 # include <arpa/inet.h>
659 const char *inet_ntop(int af
__attribute__((unused
)), const void *src
,
660 char *dst
, size_t cnt
)
664 ret
= inet_ntoa( *((struct in_addr
*)src
));
666 if (strlen(ret
) > cnt
) {
675 void sockets_init( void)
678 WORD wVersionRequested
;
681 wVersionRequested
= MAKEWORD(1, 1);
682 if (WSAStartup(wVersionRequested
, &wsaData
) != 0) {
683 perror("WSA_STARTUP_ERROR");