2 * Copyright (C) 2012 Free Software Foundation, Inc.
4 * This file is part of GnuTLS.
6 * GnuTLS is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuTLS is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
23 #include <gnutls/gnutls.h>
24 #include <gnutls/x509.h>
25 #include <gnutls/openpgp.h>
26 #include <gnutls/pkcs12.h>
27 #include <gnutls/pkcs11.h>
28 #include <gnutls/abstract.h>
29 #include <gnutls/crypto.h>
32 # include <gnutls/dane.h>
42 #include <sys/types.h>
47 /* Gnulib portability files. */
48 #include <read-file.h>
50 #include <version-etc.h>
53 #include "danetool-args.h"
54 #include "certtool-common.h"
56 static void cmd_parser (int argc
, char **argv
);
57 static void dane_info(const char* host
, const char* proto
, unsigned int port
,
58 unsigned int ca
, unsigned int local
, common_info_st
* cinfo
);
60 static void dane_check(const char* host
, const char* proto
, unsigned int port
,
61 common_info_st
* cinfo
);
64 static gnutls_digest_algorithm_t default_dig
;
66 /* non interactive operation if set
72 tls_log_func (int level
, const char *str
)
74 fprintf (stderr
, "|<%d>| %s", level
, str
);
78 main (int argc
, char **argv
)
80 set_program_name (argv
[0]);
81 cmd_parser (argc
, argv
);
88 cmd_parser (int argc
, char **argv
)
90 int ret
, privkey_op
= 0;
92 const char* proto
= "tcp";
93 unsigned int port
= 443;
95 optionProcess( &danetoolOptions
, argc
, argv
);
97 if (HAVE_OPT(OUTFILE
))
99 outfile
= safe_open_rw (OPT_ARG(OUTFILE
), privkey_op
);
101 error (EXIT_FAILURE
, errno
, "%s", OPT_ARG(OUTFILE
));
106 default_dig
= GNUTLS_DIG_UNKNOWN
;
109 if (strcasecmp (OPT_ARG(HASH
), "md5") == 0)
112 "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
113 default_dig
= GNUTLS_DIG_MD5
;
115 else if (strcasecmp (OPT_ARG(HASH
), "sha1") == 0)
116 default_dig
= GNUTLS_DIG_SHA1
;
117 else if (strcasecmp (OPT_ARG(HASH
), "sha256") == 0)
118 default_dig
= GNUTLS_DIG_SHA256
;
119 else if (strcasecmp (OPT_ARG(HASH
), "sha224") == 0)
120 default_dig
= GNUTLS_DIG_SHA224
;
121 else if (strcasecmp (OPT_ARG(HASH
), "sha384") == 0)
122 default_dig
= GNUTLS_DIG_SHA384
;
123 else if (strcasecmp (OPT_ARG(HASH
), "sha512") == 0)
124 default_dig
= GNUTLS_DIG_SHA512
;
125 else if (strcasecmp (OPT_ARG(HASH
), "rmd160") == 0)
126 default_dig
= GNUTLS_DIG_RMD160
;
128 error (EXIT_FAILURE
, 0, "invalid hash: %s", OPT_ARG(HASH
));
131 gnutls_global_set_log_function (tls_log_func
);
135 gnutls_global_set_log_level (OPT_VALUE_DEBUG
);
136 printf ("Setting log level to %d\n", (int)OPT_VALUE_DEBUG
);
139 if ((ret
= gnutls_global_init ()) < 0)
140 error (EXIT_FAILURE
, 0, "global_init: %s", gnutls_strerror (ret
));
146 memset (&cinfo
, 0, sizeof (cinfo
));
148 if (HAVE_OPT(INDER
) || HAVE_OPT(INRAW
))
149 cinfo
.incert_format
= GNUTLS_X509_FMT_DER
;
151 cinfo
.incert_format
= GNUTLS_X509_FMT_PEM
;
153 if (HAVE_OPT(VERBOSE
))
156 if (HAVE_OPT(LOAD_PUBKEY
))
157 cinfo
.pubkey
= OPT_ARG(LOAD_PUBKEY
);
159 if (HAVE_OPT(LOAD_CERTIFICATE
))
160 cinfo
.cert
= OPT_ARG(LOAD_CERTIFICATE
);
163 port
= OPT_VALUE_PORT
;
165 proto
= OPT_ARG(PROTO
);
167 if (HAVE_OPT(TLSA_RR
))
168 dane_info (OPT_ARG(HOST
), proto
, port
,
169 HAVE_OPT(CA
), HAVE_OPT(LOCAL
), &cinfo
);
170 else if (HAVE_OPT(CHECK
))
171 dane_check (OPT_ARG(CHECK
), proto
, port
,
179 gnutls_pkcs11_deinit ();
181 gnutls_global_deinit ();
184 static void dane_check(const char* host
, const char* proto
, unsigned int port
,
185 common_info_st
* cinfo
)
192 unsigned int flags
= DANE_F_IGNORE_LOCAL_RESOLVER
, i
;
193 unsigned int usage
, type
, match
;
194 gnutls_datum_t data
, file
;
197 if (ENABLED_OPT(LOCAL_DNS
))
200 printf("Querying %s (%s:%d)...\n", host
, proto
, port
);
201 ret
= dane_state_init(&s
, flags
);
203 error (EXIT_FAILURE
, 0, "dane_state_init: %s", dane_strerror (ret
));
205 ret
= dane_query_tlsa(s
, &q
, host
, proto
, port
);
207 error (EXIT_FAILURE
, 0, "dane_query_tlsa: %s", dane_strerror (ret
));
209 entries
= dane_query_entries(q
);
210 for (i
=0;i
<entries
;i
++)
212 ret
= dane_query_data(q
, i
, &usage
, &type
, &match
, &data
);
214 error (EXIT_FAILURE
, 0, "dane_query_data: %s", dane_strerror (ret
));
218 ret
= gnutls_hex_encode(&data
, (void*)buffer
, &size
);
220 error (EXIT_FAILURE
, 0, "gnutls_hex_encode: %s", dane_strerror (ret
));
222 if (entries
> 1) printf("\nEntry %d:\n", i
+1);
224 fprintf(outfile
, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n", port
, proto
, host
, usage
, type
, match
, buffer
);
225 printf("Certificate usage: %s (%.2x)\n", dane_cert_usage_name(usage
), usage
);
226 printf("Certificate type: %s (%.2x)\n", dane_cert_type_name(type
), type
);
227 printf("Contents: %s (%.2x)\n", dane_match_type_name(match
), match
);
228 printf("Data: %s\n", buffer
);
230 /* Verify the DANE data */
233 gnutls_x509_crt_t
*clist
;
234 unsigned int clist_size
, status
;
236 ret
= gnutls_load_file(cinfo
->cert
, &file
);
238 error (EXIT_FAILURE
, 0, "gnutls_load_file: %s", gnutls_strerror (ret
));
240 ret
= gnutls_x509_crt_list_import2( &clist
, &clist_size
, &file
, cinfo
->incert_format
, 0);
242 error (EXIT_FAILURE
, 0, "gnutls_x509_crt_list_import2: %s", gnutls_strerror (ret
));
246 gnutls_datum_t certs
[clist_size
];
250 for (i
=0;i
<clist_size
;i
++)
252 ret
= gnutls_x509_crt_export2( clist
[i
], GNUTLS_X509_FMT_DER
, &certs
[i
]);
254 error (EXIT_FAILURE
, 0, "gnutls_x509_crt_export2: %s", gnutls_strerror (ret
));
257 ret
= dane_verify_crt( s
, certs
, clist_size
, GNUTLS_CRT_X509
,
258 host
, proto
, port
, 0, 0, &status
);
260 error (EXIT_FAILURE
, 0, "dane_verify_crt: %s", dane_strerror (ret
));
262 ret
= dane_verification_status_print(status
, &out
, 0);
264 error (EXIT_FAILURE
, 0, "dane_verification_status_print: %s", dane_strerror (ret
));
266 printf("\nVerification: %s\n", out
.data
);
267 gnutls_free(out
.data
);
269 for (i
=0;i
<clist_size
;i
++)
271 gnutls_free(certs
[i
].data
);
272 gnutls_x509_crt_deinit(clist
[i
]);
280 dane_query_deinit(q
);
281 dane_state_deinit(s
);
283 fprintf(stderr
, "This functionality was disabled (GnuTLS was not compiled with support for DANE).\n");
288 static void dane_info(const char* host
, const char* proto
, unsigned int port
,
289 unsigned int ca
, unsigned int local
, common_info_st
* cinfo
)
291 gnutls_pubkey_t pubkey
;
292 gnutls_x509_crt_t crt
;
293 unsigned char digest
[64];
296 unsigned int usage
, selector
, type
;
304 crt
= load_cert (0, cinfo
);
305 if (crt
!= NULL
&& HAVE_OPT(X509
))
307 selector
= 0; /* X.509 */
310 ret
= gnutls_x509_crt_export (crt
, GNUTLS_X509_FMT_DER
, buffer
, &size
);
312 error (EXIT_FAILURE
, 0, "export error: %s", gnutls_strerror (ret
));
314 gnutls_x509_crt_deinit (crt
);
316 else /* use public key only */
320 ret
= gnutls_pubkey_init (&pubkey
);
322 error (EXIT_FAILURE
, 0, "pubkey_init: %s", gnutls_strerror (ret
));
327 ret
= gnutls_pubkey_import_x509 (pubkey
, crt
, 0);
330 error (EXIT_FAILURE
, 0, "pubkey_import_x509: %s",
331 gnutls_strerror (ret
));
335 ret
= gnutls_pubkey_export (pubkey
, GNUTLS_X509_FMT_DER
, buffer
, &size
);
338 error (EXIT_FAILURE
, 0, "pubkey_export: %s",
339 gnutls_strerror (ret
));
342 gnutls_x509_crt_deinit(crt
);
346 pubkey
= load_pubkey (1, cinfo
);
349 ret
= gnutls_pubkey_export (pubkey
, GNUTLS_X509_FMT_DER
, buffer
, &size
);
351 error (EXIT_FAILURE
, 0, "export error: %s", gnutls_strerror (ret
));
354 gnutls_pubkey_deinit (pubkey
);
357 if (default_dig
!= GNUTLS_DIG_SHA256
&& default_dig
!= GNUTLS_DIG_SHA512
)
359 if (default_dig
!= GNUTLS_DIG_UNKNOWN
) fprintf(stderr
, "Unsupported digest. Assuming SHA256.\n");
360 default_dig
= GNUTLS_DIG_SHA256
;
363 ret
= gnutls_hash_fast(default_dig
, buffer
, size
, digest
);
365 error (EXIT_FAILURE
, 0, "hash error: %s", gnutls_strerror (ret
));
367 if (default_dig
== GNUTLS_DIG_SHA256
)
371 /* DANE certificate classification crap */
384 t
.size
= gnutls_hash_get_len(default_dig
);
387 ret
= gnutls_hex_encode(&t
, (void*)buffer
, &size
);
389 error (EXIT_FAILURE
, 0, "hex encode error: %s", gnutls_strerror (ret
));
391 fprintf(outfile
, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n", port
, proto
, host
, usage
, selector
, type
, buffer
);