diff options
author | Tobias Brunner <tobias@strongswan.org> | 2015-07-17 11:46:16 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2015-08-17 11:29:11 +0200 |
commit | 18662e96943f3b2c2bcb38d14ffe6f080e4015d8 (patch) | |
tree | b15f57ec84780b78fa29bf6bee1a082edac38cfb /scripts | |
parent | d6f70ff68929e3b50a25fd2e11aa263beb5312e7 (diff) | |
download | strongswan-18662e96943f3b2c2bcb38d14ffe6f080e4015d8.tar.bz2 strongswan-18662e96943f3b2c2bcb38d14ffe6f080e4015d8.tar.xz |
scripts: Add script to extract the ASN.1 subject DN from a certificate
This can be useful if the subject DN has to be configured with the
asn1dn: prefix in ipsec.conf (e.g. because the actual encoding can't be
created by strongSwan's string parser/encoder).
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/Makefile.am | 3 | ||||
-rw-r--r-- | scripts/extract-dn.c | 155 |
2 files changed, 157 insertions, 1 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am index a793800b7..25456700b 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -5,7 +5,7 @@ AM_CPPFLAGS = \ noinst_PROGRAMS = bin2array bin2sql id2sql key2keyid keyid2sql oid2der \ thread_analysis dh_speed pubkey_speed crypt_burn hash_burn fetch \ - dnssec malloc_speed aes-test settings-test timeattack + dnssec malloc_speed aes-test settings-test timeattack extract-dn if USE_TLS noinst_PROGRAMS += tls_test @@ -30,6 +30,7 @@ fetch_SOURCES = fetch.c dnssec_SOURCES = dnssec.c timeattack_SOURCES = timeattack.c id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la +extract_dn_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la keyid2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la oid2der_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la diff --git a/scripts/extract-dn.c b/scripts/extract-dn.c new file mode 100644 index 000000000..01261422e --- /dev/null +++ b/scripts/extract-dn.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2015 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <getopt.h> + +#include <library.h> + +static void usage(FILE *out, char *name) +{ + fprintf(out, "Extract the ASN.1 subject DN from a certificate\n\n"); + fprintf(out, "%s [OPTIONS]\n\n", name); + fprintf(out, "Options:\n"); + fprintf(out, " -h, --help print this help.\n"); + fprintf(out, " -i, --in=FILE certificate file (default STDIN).\n"); + fprintf(out, " -f, --format=FORMAT output format (config, hex, base64, binary).\n"); + fprintf(out, "\n"); +} + +/** + * Extract the binary ASN.1 subject DN from a certificate + */ +int main(int argc, char *argv[]) +{ + identification_t *id; + certificate_t *cert; + chunk_t chunk; + enum { + FORMAT_CONFIG, + FORMAT_HEX, + FORMAT_BASE64, + FORMAT_BINARY, + } format = FORMAT_CONFIG; + int fd = 0; + char *fmt; + + library_init(NULL, "extract-dn"); + atexit(library_deinit); + + while (true) + { + struct option long_opts[] = { + {"help", no_argument, NULL, 'h' }, + {"in", required_argument, NULL, 'i' }, + {"format", required_argument, NULL, 'f' }, + {0,0,0,0 }, + }; + switch (getopt_long(argc, argv, "hi:f:", long_opts, NULL)) + { + case EOF: + break; + case 'h': + usage(stdout, argv[0]); + return 0; + case 'i': + fd = open(optarg, O_RDONLY); + if (fd == -1) + { + fprintf(stderr, "failed to open '%s': %s\n", optarg, + strerror(errno)); + usage(stderr, argv[0]); + return 1; + } + continue; + case 'f': + if (streq(optarg, "hex")) + { + format = FORMAT_HEX; + } + else if (streq(optarg, "base64")) + { + format = FORMAT_BASE64; + } + else if (streq(optarg, "bin")) + { + format = FORMAT_BINARY; + } + continue; + default: + usage(stderr, argv[0]); + return 1; + } + break; + } + /* TODO: maybe make plugins configurable */ + lib->plugins->load(lib->plugins, PLUGINS); + + if (!chunk_from_fd(fd, &chunk)) + { + fprintf(stderr, "reading input failed: %s\n", strerror(errno)); + return 1; + } + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB, chunk, BUILD_END); + chunk_free(&chunk); + if (fd != 0) + { + close(fd); + } + + if (!cert) + { + fprintf(stderr, "failed to read certificate\n"); + return 1; + } + id = cert->get_subject(cert); + if (!id) + { + fprintf(stderr, "failed to get certificate's subject DN\n"); + cert->destroy(cert); + return 1; + } + fmt = "%.*s\n"; + switch (format) + { + case FORMAT_CONFIG: + fmt = "\"asn1dn:#%.*s\"\n"; + /* fall-through */ + case FORMAT_HEX: + chunk = chunk_to_hex(id->get_encoding(id), NULL, FALSE); + printf(fmt, (int)chunk.len, chunk.ptr); + chunk_free(&chunk); + break; + case FORMAT_BASE64: + chunk = chunk_to_base64(id->get_encoding(id), NULL); + printf(fmt, (int)chunk.len, chunk.ptr); + chunk_free(&chunk); + break; + case FORMAT_BINARY: + chunk = id->get_encoding(id); + if (fwrite(chunk.ptr, chunk.len, 1, stdout) != 1) + { + fprintf(stderr, "writing subject DN failed\n"); + } + break; + } + cert->destroy(cert); + return 0; +} |