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/>.
20 * In addition, as a special exception, the copyright holders give
21 * permission to link the code of portions of this program with the
22 * OpenSSL library under certain conditions as described in each
23 * individual source file, and distribute linked combinations including
26 * You must obey the GNU General Public License in all respects for all
27 * of the code used other than OpenSSL. If you modify file(s) with this
28 * exception, you may extend this exception to your version of the
29 * file(s), but you are not obligated to do so. If you do not wish to do
30 * so, delete this exception statement from your version. If you delete
31 * this exception statement from all source files in the program, then
32 * also delete it here.
37 #include <gnutls/gnutls.h>
38 #include <gnutls/x509.h>
39 #include <gnutls/openpgp.h>
40 #include <gnutls/pkcs12.h>
41 #include <gnutls/pkcs11.h>
42 #include <gnutls/abstract.h>
43 #include <gnutls/crypto.h>
46 #include <gnutls/dane.h>
56 #include <sys/types.h>
60 /* Gnulib portability files. */
61 #include <read-file.h>
65 #include "danetool-args.h"
66 #include "certtool-common.h"
69 static const char* obtain_cert(const char *hostname, const char *proto, unsigned int port,
70 const char *app_proto, unsigned quiet);
71 static void cmd_parser(int argc, char **argv);
72 static void dane_info(const char *host, const char *proto,
73 unsigned int port, unsigned int ca,
74 unsigned int domain, common_info_st * cinfo);
76 static void dane_check(const char *host, const char *proto,
77 unsigned int port, common_info_st * cinfo);
80 static gnutls_digest_algorithm_t default_dig;
82 /* non interactive operation if set
88 static void tls_log_func(int level, const char *str)
90 fprintf(stderr, "|<%d>| %s", level, str);
93 int main(int argc, char **argv)
96 cmd_parser(argc, argv);
102 static void cmd_parser(int argc, char **argv)
104 int ret, privkey_op = 0;
105 common_info_st cinfo;
106 const char *proto = "tcp";
107 unsigned int port = 443;
109 optionProcess(&danetoolOptions, argc, argv);
111 if (HAVE_OPT(OUTFILE)) {
112 outfile = safe_open_rw(OPT_ARG(OUTFILE), privkey_op);
113 if (outfile == NULL) {
114 fprintf(stderr, "%s", OPT_ARG(OUTFILE));
120 default_dig = GNUTLS_DIG_UNKNOWN;
121 if (HAVE_OPT(HASH)) {
122 if (strcasecmp(OPT_ARG(HASH), "md5") == 0) {
124 "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
125 default_dig = GNUTLS_DIG_MD5;
126 } else if (strcasecmp(OPT_ARG(HASH), "sha1") == 0)
127 default_dig = GNUTLS_DIG_SHA1;
128 else if (strcasecmp(OPT_ARG(HASH), "sha256") == 0)
129 default_dig = GNUTLS_DIG_SHA256;
130 else if (strcasecmp(OPT_ARG(HASH), "sha224") == 0)
131 default_dig = GNUTLS_DIG_SHA224;
132 else if (strcasecmp(OPT_ARG(HASH), "sha384") == 0)
133 default_dig = GNUTLS_DIG_SHA384;
134 else if (strcasecmp(OPT_ARG(HASH), "sha512") == 0)
135 default_dig = GNUTLS_DIG_SHA512;
136 else if (strcasecmp(OPT_ARG(HASH), "rmd160") == 0)
137 default_dig = GNUTLS_DIG_RMD160;
139 fprintf(stderr, "invalid hash: %s", OPT_ARG(HASH));
144 gnutls_global_set_log_function(tls_log_func);
146 if (HAVE_OPT(DEBUG)) {
147 gnutls_global_set_log_level(OPT_VALUE_DEBUG);
148 printf("Setting log level to %d\n", (int) OPT_VALUE_DEBUG);
151 if ((ret = gnutls_global_init()) < 0) {
152 fprintf(stderr, "global_init: %s", gnutls_strerror(ret));
159 memset(&cinfo, 0, sizeof(cinfo));
161 if (HAVE_OPT(INDER) || HAVE_OPT(INRAW))
162 cinfo.incert_format = GNUTLS_X509_FMT_DER;
164 cinfo.incert_format = GNUTLS_X509_FMT_PEM;
166 if (HAVE_OPT(VERBOSE))
169 if (HAVE_OPT(LOAD_PUBKEY))
170 cinfo.pubkey = OPT_ARG(LOAD_PUBKEY);
172 if (HAVE_OPT(LOAD_CERTIFICATE))
173 cinfo.cert = OPT_ARG(LOAD_CERTIFICATE);
176 port = OPT_VALUE_PORT;
178 proto = OPT_ARG(PROTO);
180 if (HAVE_OPT(TLSA_RR))
181 dane_info(OPT_ARG(HOST), proto, port,
182 HAVE_OPT(CA), ENABLED_OPT(DOMAIN), &cinfo);
183 else if (HAVE_OPT(CHECK))
184 dane_check(OPT_ARG(CHECK), proto, port, &cinfo);
191 gnutls_pkcs11_deinit();
193 gnutls_global_deinit();
196 #define MAX_CLIST_SIZE 32
197 static void dane_check(const char *host, const char *proto,
198 unsigned int port, common_info_st * cinfo)
203 int ret, retcode = 1;
205 unsigned int flags = DANE_F_IGNORE_LOCAL_RESOLVER, i;
206 unsigned int usage, type, match;
207 gnutls_datum_t data, file;
210 unsigned vflags = DANE_VFLAG_FAIL_IF_NOT_CHECKED;
212 gnutls_x509_crt_t *clist = NULL;
213 unsigned int clist_size = 0;
214 gnutls_datum_t certs[MAX_CLIST_SIZE];
216 if (ENABLED_OPT(LOCAL_DNS))
219 if (HAVE_OPT(INSECURE))
220 flags |= DANE_F_INSECURE;
222 if (HAVE_OPT(CHECK_EE))
223 vflags |= DANE_VFLAG_ONLY_CHECK_EE_USAGE;
225 if (HAVE_OPT(CHECK_CA))
226 vflags |= DANE_VFLAG_ONLY_CHECK_CA_USAGE;
229 const char *app_proto = NULL;
230 if (HAVE_OPT(APP_PROTO))
231 app_proto = OPT_ARG(APP_PROTO);
233 cinfo->cert = obtain_cert(host, proto, port, app_proto, HAVE_OPT(QUIET));
237 if (!HAVE_OPT(QUIET))
238 fprintf(stderr, "Querying DNS for %s (%s:%d)...\n", host, proto, port);
239 ret = dane_state_init(&s, flags);
241 fprintf(stderr, "dane_state_init: %s\n",
248 ret = dane_state_set_dlv_file(s, OPT_ARG(DLV));
250 fprintf(stderr, "dane_state_set_dlv_file: %s\n",
257 ret = dane_query_tlsa(s, &q, host, proto, port);
259 fprintf(stderr, "dane_query_tlsa: %s\n",
265 if (ENABLED_OPT(PRINT_RAW)) {
273 ret = dane_query_to_raw_tlsa(q, &entries, &dane_data,
274 &dane_data_len, &secure, &bogus);
276 fprintf(stderr, "dane_query_to_raw_tlsa: %s\n",
282 for (i=0;i<entries;i++) {
285 t.data = (void*)dane_data[i];
286 t.size = dane_data_len[i];
288 str_size = t.size * 2 + 1;
289 str = gnutls_malloc(str_size);
291 ret = gnutls_hex_encode(&t, str, &str_size);
293 fprintf(stderr, "gnutls_hex_encode: %s\n",
298 fprintf(outfile, "[%u]: %s\n", i, str);
301 fprintf(outfile, "\n");
305 ret = gnutls_load_file(cinfo->cert, &file);
307 fprintf(stderr, "gnutls_load_file: %s\n",
308 gnutls_strerror(ret));
314 gnutls_x509_crt_list_import2(&clist,
321 "gnutls_x509_crt_list_import2: %s\n",
322 gnutls_strerror(ret));
327 if (clist_size > 0) {
328 for (i = 0; i < MIN(MAX_CLIST_SIZE,clist_size); i++) {
330 gnutls_x509_crt_export2(clist
337 "gnutls_x509_crt_export2: %s\n",
347 entries = dane_query_entries(q);
348 for (i = 0; i < entries; i++) {
349 ret = dane_query_data(q, i, &usage, &type, &match, &data);
351 fprintf(stderr, "dane_query_data: %s\n",
358 ret = gnutls_hex_encode(&data, (void *) lbuffer, &size);
360 fprintf(stderr, "gnutls_hex_encode: %s\n",
366 if (entries > 1 && !HAVE_OPT(QUIET))
367 fprintf(outfile, "\n==== Entry %d ====\n", i + 1);
370 "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n",
371 port, proto, host, usage, type, match, lbuffer);
373 if (!HAVE_OPT(QUIET)) {
374 str = dane_cert_usage_name(usage);
375 if (str == NULL) str= "Unknown";
376 fprintf(outfile, "Certificate usage: %s (%.2x)\n", str, usage);
378 str = dane_cert_type_name(type);
379 if (str == NULL) str= "Unknown";
380 fprintf(outfile, "Certificate type: %s (%.2x)\n", str, type);
382 str = dane_match_type_name(match);
383 if (str == NULL) str= "Unknown";
384 fprintf(outfile, "Contents: %s (%.2x)\n", str, match);
385 fprintf(outfile, "Data: %s\n", lbuffer);
388 /* Verify the DANE data */
394 dane_verify_crt(s, certs, clist_size,
395 GNUTLS_CRT_X509, host,
396 proto, port, 0, vflags,
400 "dane_verify_crt: %s\n",
407 dane_verification_status_print(status,
412 "dane_verification_status_print: %s\n",
418 if (!HAVE_OPT(QUIET))
419 fprintf(outfile, "\nVerification: %s\n", out.data);
420 gnutls_free(out.data);
422 /* if there is at least one correct accept */
427 "\nCertificate could not be obtained. You can explicitly load the certificate using --load-certificate.\n");
431 if (clist_size > 0) {
432 for (i = 0; i < clist_size; i++) {
433 gnutls_free(certs[i].data);
434 gnutls_x509_crt_deinit(clist[i]);
441 dane_query_deinit(q);
442 dane_state_deinit(s);
445 if (del != 0 && cinfo->cert) {
452 "This functionality is disabled (GnuTLS was not compiled with support for DANE).\n");
457 static void dane_info(const char *host, const char *proto,
458 unsigned int port, unsigned int ca,
459 unsigned int domain, common_info_st * cinfo)
461 gnutls_pubkey_t pubkey;
462 gnutls_x509_crt_t crt;
463 unsigned char digest[64];
466 unsigned int usage, selector, type;
474 crt = load_cert(0, cinfo);
475 if (crt != NULL && HAVE_OPT(X509)) {
476 selector = 0; /* X.509 */
480 gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER,
483 fprintf(stderr, "export error: %s\n",
484 gnutls_strerror(ret));
488 gnutls_x509_crt_deinit(crt);
489 } else { /* use public key only */
493 ret = gnutls_pubkey_init(&pubkey);
495 fprintf(stderr, "pubkey_init: %s\n",
496 gnutls_strerror(ret));
502 ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
504 fprintf(stderr, "pubkey_import_x509: %s\n",
505 gnutls_strerror(ret));
511 gnutls_pubkey_export(pubkey,
515 fprintf(stderr, "pubkey_export: %s\n",
516 gnutls_strerror(ret));
520 gnutls_x509_crt_deinit(crt);
522 pubkey = load_pubkey(1, cinfo);
526 gnutls_pubkey_export(pubkey,
530 fprintf(stderr, "export error: %s\n",
531 gnutls_strerror(ret));
536 gnutls_pubkey_deinit(pubkey);
539 if (default_dig != GNUTLS_DIG_SHA256
540 && default_dig != GNUTLS_DIG_SHA512) {
541 if (default_dig != GNUTLS_DIG_UNKNOWN)
543 "Unsupported digest. Assuming SHA256.\n");
544 default_dig = GNUTLS_DIG_SHA256;
547 ret = gnutls_hash_fast(default_dig, lbuffer, size, digest);
549 fprintf(stderr, "hash error: %s\n", gnutls_strerror(ret));
553 if (default_dig == GNUTLS_DIG_SHA256)
558 /* DANE certificate classification crap */
572 t.size = gnutls_hash_get_len(default_dig);
575 ret = gnutls_hex_encode(&t, (void *) lbuffer, &size);
577 fprintf(stderr, "hex encode error: %s\n",
578 gnutls_strerror(ret));
582 fprintf(outfile, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n",
583 port, proto, host, usage, selector, type, lbuffer);
594 static int cert_callback(gnutls_session_t session)
596 const gnutls_datum_t *cert_list;
597 unsigned int cert_list_size = 0;
601 struct priv_st *priv;
603 cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
604 if (cert_list_size == 0) {
605 fprintf(stderr, "no certificates sent by server!\n");
609 priv = gnutls_session_get_ptr(session);
611 for (i=0;i<cert_list_size;i++) {
612 ret = gnutls_pem_base64_encode_alloc("CERTIFICATE", &cert_list[i], &t);
614 fprintf(stderr, "error[%d]: %s\n", __LINE__,
615 gnutls_strerror(ret));
619 write(priv->fd, t.data, t.size);
627 static int get_cert(socket_st *hd, const char *hostname, unsigned udp, int fd)
629 gnutls_certificate_credentials_t xcred;
630 gnutls_session_t session;
637 ret = gnutls_certificate_allocate_credentials(&xcred);
639 fprintf(stderr, "error[%d]: %s\n", __LINE__,
640 gnutls_strerror(ret));
643 gnutls_certificate_set_verify_function(xcred, cert_callback);
645 ret = gnutls_init(&session, (udp?GNUTLS_DATAGRAM:0)|GNUTLS_CLIENT);
647 fprintf(stderr, "error[%d]: %s\n", __LINE__,
648 gnutls_strerror(ret));
651 gnutls_session_set_ptr(session, &priv);
652 gnutls_transport_set_int(session, hd->fd);
654 gnutls_set_default_priority(session);
655 if (hostname && is_ip(hostname)==0) {
656 gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, strlen(hostname));
658 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
661 ret = gnutls_handshake(session);
662 } while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_WARNING_ALERT_RECEIVED);
663 /* we don't care on the result */
665 gnutls_deinit(session);
666 gnutls_certificate_free_credentials(xcred);
674 static const char *obtain_cert(const char *hostname, const char *proto, unsigned port,
675 const char *app_proto, unsigned quiet)
680 static char tmpfile[32];
682 const char *str = "Obtaining certificate from";
685 if (strcmp(proto, "udp") == 0)
687 else if (strcmp(proto, "tcp") != 0) {
688 /* we cannot handle this protocol */
692 strcpy(tmpfile, "danetool-certXXXXXX");
695 snprintf(txt_port, sizeof(txt_port), "%u", port);
699 service = port_to_service(txt_port, proto);
700 socket_open(&hd, hostname, service, udp, str);
702 if (app_proto == NULL) app_proto = service;
703 socket_starttls(&hd, app_proto);
706 fd = mkstemp(tmpfile);
709 fprintf(stderr, "error[%d]: %s\n", __LINE__,
714 ret = get_cert(&hd, hostname, udp, fd);