pki: Add --dn command to extract the subject DN of a certificate
authorTobias Brunner <tobias@strongswan.org>
Thu, 6 Aug 2015 16:04:38 +0000 (18:04 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 17 Aug 2015 09:34:01 +0000 (11:34 +0200)
configure.ac
scripts/Makefile.am
scripts/extract-dn.c [deleted file]
src/pki/Makefile.am
src/pki/command.h
src/pki/commands/dn.c [new file with mode: 0644]
src/pki/man/Makefile.am
src/pki/man/pki---dn.1.in [new file with mode: 0644]
src/pki/man/pki.1.in

index 545f1fb..a7ee63d 100644 (file)
@@ -1868,17 +1868,18 @@ AC_CONFIG_FILES([
        man/ipsec.secrets.5
        src/charon-cmd/charon-cmd.8
        src/pki/man/pki.1
+       src/pki/man/pki---acert.1
+       src/pki/man/pki---dn.1
        src/pki/man/pki---gen.1
        src/pki/man/pki---issue.1
        src/pki/man/pki---keyid.1
-       src/pki/man/pki---pkcs7.1
        src/pki/man/pki---pkcs12.1
+       src/pki/man/pki---pkcs7.1
        src/pki/man/pki---print.1
        src/pki/man/pki---pub.1
        src/pki/man/pki---req.1
        src/pki/man/pki---self.1
        src/pki/man/pki---signcrl.1
-       src/pki/man/pki---acert.1
        src/pki/man/pki---verify.1
        src/swanctl/swanctl.8
        src/swanctl/swanctl.conf.5.head
index 2545670..a793800 100644 (file)
@@ -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 extract-dn
+       dnssec malloc_speed aes-test settings-test timeattack
 
 if USE_TLS
   noinst_PROGRAMS += tls_test
@@ -30,7 +30,6 @@ 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
deleted file mode 100644 (file)
index 0126142..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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;
-}
index ab407e0..a3da0ab 100644 (file)
@@ -3,17 +3,18 @@ SUBDIRS = man
 bin_PROGRAMS = pki
 
 pki_SOURCES = pki.c pki.h command.c command.h \
+       commands/acert.c \
+       commands/dn.c \
        commands/gen.c \
        commands/issue.c \
        commands/keyid.c \
+       commands/pkcs12.c \
+       commands/pkcs7.c \
+       commands/print.c \
        commands/pub.c \
        commands/req.c \
        commands/self.c \
-       commands/print.c \
        commands/signcrl.c \
-       commands/acert.c \
-       commands/pkcs7.c \
-       commands/pkcs12.c \
        commands/verify.c
 
 pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
index d49adda..e55c579 100644 (file)
@@ -24,7 +24,7 @@
 /**
  * Maximum number of commands (+1).
  */
-#define MAX_COMMANDS 13
+#define MAX_COMMANDS 14
 
 /**
  * Maximum number of options in a command (+3)
diff --git a/src/pki/commands/dn.c b/src/pki/commands/dn.c
new file mode 100644 (file)
index 0000000..75585fc
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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 "pki.h"
+
+#include <credentials/certificates/certificate.h>
+
+#include <errno.h>
+
+/**
+ * Extract subject DN
+ */
+static int dn()
+{
+       identification_t *id;
+       certificate_t *cert;
+       chunk_t chunk;
+       enum {
+               FORMAT_CONFIG,
+               FORMAT_HEX,
+               FORMAT_BASE64,
+               FORMAT_BINARY,
+       } format = FORMAT_CONFIG;
+       char *arg, *file = NULL, *fmt;
+
+       while (TRUE)
+       {
+               switch (command_getopt(&arg))
+               {
+                       case 'h':
+                               return command_usage(NULL);
+                       case 'f':
+                               if (streq(arg, "hex"))
+                               {
+                                       format = FORMAT_HEX;
+                               }
+                               else if (streq(arg, "base64"))
+                               {
+                                       format = FORMAT_BASE64;
+                               }
+                               else if (streq(arg, "bin"))
+                               {
+                                       format = FORMAT_BINARY;
+                               }
+                               else if (!streq(arg, "config"))
+                               {
+                                       return command_usage( "invalid output format");
+                               }
+                               continue;
+                       case 'i':
+                               file = arg;
+                               continue;
+                       case EOF:
+                               break;
+                       default:
+                               return command_usage("invalid --print option");
+               }
+               break;
+       }
+       if (file)
+       {
+               cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+                                                                 BUILD_FROM_FILE, file, BUILD_END);
+       }
+       else
+       {
+               chunk_t chunk;
+
+               set_file_mode(stdin, CERT_ASN1_DER);
+               if (!chunk_from_fd(0, &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);
+               free(chunk.ptr);
+       }
+       if (!cert)
+       {
+               fprintf(stderr, "parsing input failed\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;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+       command_register((command_t)
+               { dn, 'd', "dn",
+               "extract the subject DN of an X.509 certificate",
+               {"[--in file] [--format config|hex|base64|bin]"},
+               {
+                       {"help",                'h', 0, "show usage information"},
+                       {"in",                  'i', 1, "input file, default: stdin"},
+                       {"format",              'f', 1, "output format, default: config"},
+               }
+       });
+}
index 4c901ae..fc94400 100644 (file)
@@ -1,15 +1,16 @@
 man1_MANS = \
        pki.1 \
+       pki---acert.1 \
+       pki---dn.1 \
        pki---gen.1 \
-       pki---self.1 \
        pki---issue.1 \
-       pki---signcrl.1 \
-       pki---acert.1 \
-       pki---req.1 \
-       pki---pkcs7.1 \
        pki---keyid.1 \
+       pki---pkcs7.1 \
        pki---print.1 \
        pki---pub.1 \
+       pki---req.1 \
+       pki---self.1 \
+       pki---signcrl.1 \
        pki---verify.1
 
 CLEANFILES = $(man1_MANS)
diff --git a/src/pki/man/pki---dn.1.in b/src/pki/man/pki---dn.1.in
new file mode 100644 (file)
index 0000000..ce1210f
--- /dev/null
@@ -0,0 +1,56 @@
+.TH "PKI \-\-DN" 1 "2015-08-06" "@PACKAGE_VERSION@" "strongSwan"
+.
+.SH "NAME"
+.
+pki \-\-dn \- Extract the subject DN of an X.509 certificate
+.
+.SH "SYNOPSIS"
+.
+.SY pki\ \-\-dn
+.OP \-\-in file
+.OP \-\-format format
+.OP \-\-debug level
+.YS
+.
+.SY pki\ \-\-dn
+.BI \-\-options\~ file
+.YS
+.
+.SY "pki \-\-dn"
+.B \-h
+|
+.B \-\-help
+.YS
+.
+.SH "DESCRIPTION"
+.
+This sub-command of
+.BR pki (1)
+extracts the ASN.1-encoded subject DistinguishedName (DN) of an X.509
+certificate and exports it in different formats.  This may be useful when
+strongSwan's identity parser is unable to produce the correct binary encoding
+from a string.
+.
+.SH "OPTIONS"
+.
+.TP
+.B "\-h, \-\-help"
+Print usage information with a summary of the available options.
+.TP
+.BI "\-v, \-\-debug " level
+Set debug level, default: 1.
+.TP
+.BI "\-+, \-\-options " file
+Read command line options from \fIfile\fR.
+.TP
+.BI "\-i, \-\-in " file
+Input file. If not given the input is read from \fISTDIN\fR.
+.TP
+.BI "\-t, \-\-format " format
+Output format. One of \fIconfig\fR (strongSwan configuration compatible),
+\fIhex\fR (hexadecimal encoding, no prefix), \fIbase64\fR (Base64 encoding,
+no prefix), \fIbin\fR (raw binary data), defaults to \fIconfig\fR.
+.
+.SH "SEE ALSO"
+.
+.BR pki (1)
index f347031..f1a2ae2 100644 (file)
@@ -1,4 +1,4 @@
-.TH PKI 1 "2013-07-31" "@PACKAGE_VERSION@" "strongSwan"
+.TH PKI 1 "2015-08-06" "@PACKAGE_VERSION@" "strongSwan"
 .
 .SH "NAME"
 .
@@ -64,6 +64,9 @@ Calculate key identifiers of a key or certificate.
 .B "\-a, \-\-print"
 Print a credential (key, certificate etc.) in human readable form.
 .TP
+.B "\-d, \-\-dn"
+Extract the subject DN of an X.509 certificate.
+.TP
 .B "\-p, \-\-pub"
 Extract a public key from a private key or certificate.
 .TP
@@ -156,5 +159,6 @@ certificates with the \-\-crl option.
 .BR pki\ \-\-pkcs7 (1),
 .BR pki\ \-\-keyid (1),
 .BR pki\ \-\-print (1),
+.BR pki\ \-\-dn (1),
 .BR pki\ \-\-pub (1),
 .BR pki\ \-\-verify (1)