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/>.
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>
38 #include <sys/types.h>
43 /* Gnulib portability files. */
44 #include <read-file.h>
46 #include <version-etc.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
);
58 static gnutls_digest_algorithm_t default_dig
;
59 static unsigned int incert_format
, outcert_format
;
61 /* non interactive operation if set
67 tls_log_func (int level
, const char *str
)
69 fprintf (stderr
, "|<%d>| %s", level
, str
);
73 main (int argc
, char **argv
)
75 set_program_name (argv
[0]);
76 cmd_parser (argc
, argv
);
83 cmd_parser (int argc
, char **argv
)
85 int ret
, privkey_op
= 0;
88 optionProcess( &danetoolOptions
, argc
, argv
);
90 if (HAVE_OPT(OUTFILE
))
92 outfile
= safe_open_rw (OPT_ARG(OUTFILE
), privkey_op
);
94 error (EXIT_FAILURE
, errno
, "%s", OPT_ARG(OUTFILE
));
101 infile
= fopen (OPT_ARG(INFILE
), "rb");
103 error (EXIT_FAILURE
, errno
, "%s", OPT_ARG(INFILE
));
108 if (HAVE_OPT(INDER
) || HAVE_OPT(INRAW
))
109 incert_format
= GNUTLS_X509_FMT_DER
;
111 incert_format
= GNUTLS_X509_FMT_PEM
;
113 if (HAVE_OPT(OUTDER
) || HAVE_OPT(OUTRAW
))
114 outcert_format
= GNUTLS_X509_FMT_DER
;
116 outcert_format
= GNUTLS_X509_FMT_PEM
;
118 default_dig
= GNUTLS_DIG_UNKNOWN
;
121 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
;
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
;
140 error (EXIT_FAILURE
, 0, "invalid hash: %s", OPT_ARG(HASH
));
143 gnutls_global_set_log_function (tls_log_func
);
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
));
158 memset (&cinfo
, 0, sizeof (cinfo
));
160 if (HAVE_OPT(VERBOSE
))
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
);
178 gnutls_pkcs11_deinit ();
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];
191 unsigned int usage
, selector
, type
;
199 crt
= load_cert (0, cinfo
);
200 if (crt
!= NULL
&& HAVE_OPT(X509
))
202 selector
= 0; /* X.509 */
205 ret
= gnutls_x509_crt_export (crt
, GNUTLS_X509_FMT_DER
, buffer
, &size
);
207 error (EXIT_FAILURE
, 0, "export error: %s", gnutls_strerror (ret
));
209 gnutls_x509_crt_deinit (crt
);
211 else /* use public key only */
215 ret
= gnutls_pubkey_init (&pubkey
);
217 error (EXIT_FAILURE
, 0, "pubkey_init: %s", gnutls_strerror (ret
));
222 ret
= gnutls_pubkey_import_x509 (pubkey
, crt
, 0);
225 error (EXIT_FAILURE
, 0, "pubkey_import_x509: %s",
226 gnutls_strerror (ret
));
230 ret
= gnutls_pubkey_export (pubkey
, GNUTLS_X509_FMT_DER
, buffer
, &size
);
233 error (EXIT_FAILURE
, 0, "pubkey_export: %s",
234 gnutls_strerror (ret
));
237 gnutls_x509_crt_deinit(crt
);
241 pubkey
= load_pubkey (1, cinfo
);
244 ret
= gnutls_pubkey_export (pubkey
, GNUTLS_X509_FMT_DER
, buffer
, &size
);
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
);
260 error (EXIT_FAILURE
, 0, "hash error: %s", gnutls_strerror (ret
));
262 if (default_dig
== GNUTLS_DIG_SHA256
)
266 /* DANE certificate classification crap */
279 t
.size
= gnutls_hash_get_len(default_dig
);
282 ret
= gnutls_hex_encode(&t
, (void*)buffer
, &size
);
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
);