Separated DANE functionality from certtool and added danetool.
[gnutls.git] / src / danetool.c
blob52fd03223fe2e175a68eb2cbbcb9053e9d474f2a
1 /*
2 * Copyright (C) 2003-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/>.
21 #include <config.h>
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>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <error.h>
43 /* Gnulib portability files. */
44 #include <read-file.h>
45 #include <progname.h>
46 #include <version-etc.h>
48 #include <common.h>
49 #include "danetool-args.h"
50 #include "certtool-common.h"
52 static void cmd_parser (int argc, char **argv);
53 static void dane_info(const char* host, const char* proto, unsigned int port,
54 unsigned int ca, unsigned int local, common_info_st * cinfo);
56 FILE *outfile;
57 FILE *infile;
58 static gnutls_digest_algorithm_t default_dig;
59 static unsigned int incert_format, outcert_format;
61 /* non interactive operation if set
63 int batch;
66 static void
67 tls_log_func (int level, const char *str)
69 fprintf (stderr, "|<%d>| %s", level, str);
72 int
73 main (int argc, char **argv)
75 set_program_name (argv[0]);
76 cmd_parser (argc, argv);
78 return 0;
82 static void
83 cmd_parser (int argc, char **argv)
85 int ret, privkey_op = 0;
86 common_info_st cinfo;
88 optionProcess( &danetoolOptions, argc, argv);
90 if (HAVE_OPT(OUTFILE))
92 outfile = safe_open_rw (OPT_ARG(OUTFILE), privkey_op);
93 if (outfile == NULL)
94 error (EXIT_FAILURE, errno, "%s", OPT_ARG(OUTFILE));
96 else
97 outfile = stdout;
99 if (HAVE_OPT(INFILE))
101 infile = fopen (OPT_ARG(INFILE), "rb");
102 if (infile == NULL)
103 error (EXIT_FAILURE, errno, "%s", OPT_ARG(INFILE));
105 else
106 infile = stdin;
108 if (HAVE_OPT(INDER) || HAVE_OPT(INRAW))
109 incert_format = GNUTLS_X509_FMT_DER;
110 else
111 incert_format = GNUTLS_X509_FMT_PEM;
113 if (HAVE_OPT(OUTDER) || HAVE_OPT(OUTRAW))
114 outcert_format = GNUTLS_X509_FMT_DER;
115 else
116 outcert_format = GNUTLS_X509_FMT_PEM;
118 default_dig = GNUTLS_DIG_UNKNOWN;
119 if (HAVE_OPT(HASH))
121 if (strcasecmp (OPT_ARG(HASH), "md5") == 0)
123 fprintf (stderr,
124 "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
125 default_dig = GNUTLS_DIG_MD5;
127 else if (strcasecmp (OPT_ARG(HASH), "sha1") == 0)
128 default_dig = GNUTLS_DIG_SHA1;
129 else if (strcasecmp (OPT_ARG(HASH), "sha256") == 0)
130 default_dig = GNUTLS_DIG_SHA256;
131 else if (strcasecmp (OPT_ARG(HASH), "sha224") == 0)
132 default_dig = GNUTLS_DIG_SHA224;
133 else if (strcasecmp (OPT_ARG(HASH), "sha384") == 0)
134 default_dig = GNUTLS_DIG_SHA384;
135 else if (strcasecmp (OPT_ARG(HASH), "sha512") == 0)
136 default_dig = GNUTLS_DIG_SHA512;
137 else if (strcasecmp (OPT_ARG(HASH), "rmd160") == 0)
138 default_dig = GNUTLS_DIG_RMD160;
139 else
140 error (EXIT_FAILURE, 0, "invalid hash: %s", OPT_ARG(HASH));
143 gnutls_global_set_log_function (tls_log_func);
145 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 error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret));
154 #ifdef ENABLE_PKCS11
155 pkcs11_common();
156 #endif
158 memset (&cinfo, 0, sizeof (cinfo));
160 if (HAVE_OPT(VERBOSE))
161 cinfo.verbose = 1;
163 if (HAVE_OPT(LOAD_PUBKEY))
164 cinfo.pubkey = OPT_ARG(LOAD_PUBKEY);
166 if (HAVE_OPT(LOAD_CERTIFICATE))
167 cinfo.cert = OPT_ARG(LOAD_CERTIFICATE);
169 if (HAVE_OPT(TLSA_RR))
170 dane_info (OPT_ARG(HOST), OPT_ARG(PROTO), OPT_VALUE_PORT,
171 HAVE_OPT(CA), HAVE_OPT(LOCAL), &cinfo);
172 else
173 USAGE(1);
175 fclose (outfile);
177 #ifdef ENABLE_PKCS11
178 gnutls_pkcs11_deinit ();
179 #endif
180 gnutls_global_deinit ();
183 static void dane_info(const char* host, const char* proto, unsigned int port,
184 unsigned int ca, unsigned int local, common_info_st * cinfo)
186 gnutls_pubkey_t pubkey;
187 gnutls_x509_crt_t crt;
188 unsigned char digest[64];
189 gnutls_datum_t t;
190 int ret;
191 unsigned int usage, selector, type;
192 size_t size;
194 if (proto == NULL)
195 proto = "tcp";
196 if (port == 0)
197 port = 443;
199 crt = load_cert (0, cinfo);
200 if (crt != NULL && HAVE_OPT(X509))
202 selector = 0; /* X.509 */
204 size = buffer_size;
205 ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_DER, buffer, &size);
206 if (ret < 0)
207 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
209 gnutls_x509_crt_deinit (crt);
211 else /* use public key only */
213 selector = 1;
215 ret = gnutls_pubkey_init (&pubkey);
216 if (ret < 0)
217 error (EXIT_FAILURE, 0, "pubkey_init: %s", gnutls_strerror (ret));
219 if (crt != NULL)
222 ret = gnutls_pubkey_import_x509 (pubkey, crt, 0);
223 if (ret < 0)
225 error (EXIT_FAILURE, 0, "pubkey_import_x509: %s",
226 gnutls_strerror (ret));
229 size = buffer_size;
230 ret = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_DER, buffer, &size);
231 if (ret < 0)
233 error (EXIT_FAILURE, 0, "pubkey_export: %s",
234 gnutls_strerror (ret));
237 gnutls_x509_crt_deinit(crt);
239 else
241 pubkey = load_pubkey (1, cinfo);
243 size = buffer_size;
244 ret = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_DER, buffer, &size);
245 if (ret < 0)
246 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
249 gnutls_pubkey_deinit (pubkey);
252 if (default_dig != GNUTLS_DIG_SHA256 && default_dig != GNUTLS_DIG_SHA512)
254 if (default_dig != GNUTLS_DIG_UNKNOWN) fprintf(stderr, "Unsupported digest. Assuming SHA256.\n");
255 default_dig = GNUTLS_DIG_SHA256;
258 ret = gnutls_hash_fast(default_dig, buffer, size, digest);
259 if (ret < 0)
260 error (EXIT_FAILURE, 0, "hash error: %s", gnutls_strerror (ret));
262 if (default_dig == GNUTLS_DIG_SHA256)
263 type = 1;
264 else type = 2;
266 /* DANE certificate classification crap */
267 if (local==0)
269 if (ca) usage = 0;
270 else usage = 1;
272 else
274 if (ca) usage = 2;
275 else usage = 3;
278 t.data = digest;
279 t.size = gnutls_hash_get_len(default_dig);
281 size = buffer_size;
282 ret = gnutls_hex_encode(&t, (void*)buffer, &size);
283 if (ret < 0)
284 error (EXIT_FAILURE, 0, "hex encode error: %s", gnutls_strerror (ret));
286 fprintf(outfile, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n", port, proto, host, usage, selector, type, buffer);