summaryrefslogtreecommitdiffstats
path: root/src/hci
diff options
context:
space:
mode:
authorMichael Brown2016-08-25 16:40:27 +0200
committerMichael Brown2016-08-31 18:11:14 +0200
commiteed12580388950d53e5f3436de484e4e170a2c5f (patch)
treefe3926395653ecbf9afa2a9d95db29acd5900f2d /src/hci
parent[crypto] Add certstat() to display basic certificate information (diff)
downloadipxe-eed12580388950d53e5f3436de484e4e170a2c5f.tar.gz
ipxe-eed12580388950d53e5f3436de484e4e170a2c5f.tar.xz
ipxe-eed12580388950d53e5f3436de484e4e170a2c5f.zip
[cmdline] Add certificate management commands
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/hci')
-rw-r--r--src/hci/commands/cert_cmd.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/src/hci/commands/cert_cmd.c b/src/hci/commands/cert_cmd.c
new file mode 100644
index 00000000..24b18bf5
--- /dev/null
+++ b/src/hci/commands/cert_cmd.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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 any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/x509.h>
+#include <ipxe/certstore.h>
+#include <ipxe/image.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/imgmgmt.h>
+#include <usr/certmgmt.h>
+
+/** @file
+ *
+ * Certificate management commands
+ *
+ */
+
+/** "cert<xxx>" options */
+struct cert_options {
+ /** Certificate subject name */
+ char *name;
+ /** Keep certificate file after parsing */
+ int keep;
+};
+
+/** "cert<xxx>" option list */
+static union {
+ /* "certstore" takes both options */
+ struct option_descriptor certstore[2];
+ /* "certstat" takes only --subject */
+ struct option_descriptor certstat[1];
+ /* "certfree" takes only --subject */
+ struct option_descriptor certfree[1];
+} opts = {
+ .certstore = {
+ OPTION_DESC ( "subject", 's', required_argument,
+ struct cert_options, name, parse_string ),
+ OPTION_DESC ( "keep", 'k', no_argument,
+ struct cert_options, keep, parse_flag ),
+ },
+};
+
+/** A "cert<xxx>" command descriptor */
+struct cert_command_descriptor {
+ /** Command descriptor */
+ struct command_descriptor cmd;
+ /** Payload
+ *
+ * @v cert X.509 certificate
+ * @ret rc Return status code
+ */
+ int ( * payload ) ( struct x509_certificate *cert );
+};
+
+/**
+ * Construct "cert<xxx>" command descriptor
+ *
+ * @v _struct Options structure type
+ * @v _options Option descriptor array
+ * @v _min_args Minimum number of non-option arguments
+ * @v _max_args Maximum number of non-option arguments
+ * @v _usage Command usage
+ * @v _payload Payload method
+ * @ret _command Command descriptor
+ */
+#define CERT_COMMAND_DESC( _struct, _options, _min_args, _max_args, \
+ _usage, _payload ) \
+ { \
+ .cmd = COMMAND_DESC ( _struct, _options, _min_args, \
+ _max_args, _usage ), \
+ .payload = _payload, \
+ }
+
+/**
+ * Execute "cert<xxx>" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v certcmd Command descriptor
+ * @ret rc Return status code
+ */
+static int cert_exec ( int argc, char **argv,
+ struct cert_command_descriptor *certcmd ) {
+ struct command_descriptor *cmd = &certcmd->cmd;
+ struct cert_options opts;
+ struct image *image = NULL;
+ struct x509_certificate *cert;
+ struct x509_certificate *tmp;
+ unsigned int count = 0;
+ size_t offset = 0;
+ int next;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 )
+ goto err_parse;
+
+ /* Acquire image, if applicable */
+ if ( ( optind < argc ) &&
+ ( ( rc = imgacquire ( argv[optind], 0, &image ) ) != 0 ) )
+ goto err_acquire;
+
+ /* Get first entry in certificate store */
+ tmp = list_first_entry ( &certstore.links, struct x509_certificate,
+ store.list );
+
+ /* Iterate over certificates */
+ while ( 1 ) {
+
+ /* Get next certificate from image or store as applicable */
+ if ( image ) {
+
+ /* Get next certificate from image */
+ if ( offset >= image->len )
+ break;
+ next = image_x509 ( image, offset, &cert );
+ if ( next < 0 ) {
+ rc = next;
+ printf ( "Could not parse certificate: %s\n",
+ strerror ( rc ) );
+ goto err_x509;
+ }
+ offset = next;
+
+ } else {
+
+ /* Get next certificate from store */
+ cert = tmp;
+ if ( ! cert )
+ break;
+ tmp = list_next_entry ( tmp, &certstore.links,
+ store.list );
+ x509_get ( cert );
+ }
+
+ /* Skip non-matching names, if a name was specified */
+ if ( opts.name && ( x509_check_name ( cert, opts.name ) != 0 )){
+ x509_put ( cert );
+ continue;
+ }
+
+ /* Execute payload */
+ if ( ( rc = certcmd->payload ( cert ) ) != 0 ) {
+ x509_put ( cert );
+ goto err_payload;
+ }
+
+ /* Count number of certificates processed */
+ count++;
+
+ /* Drop reference to certificate */
+ x509_put ( cert );
+ }
+
+ /* Fail if a name was specified and no matching certificates
+ * were found.
+ */
+ if ( opts.name && ( count == 0 ) ) {
+ printf ( "\"%s\" : no such certificate\n", opts.name );
+ rc = -ENOENT;
+ goto err_none;
+ }
+
+ err_none:
+ err_payload:
+ err_x509:
+ if ( image && ( ! opts.keep ) )
+ unregister_image ( image );
+ err_acquire:
+ err_parse:
+ return rc;
+}
+
+/**
+ * "certstat" payload
+ *
+ * @v cert X.509 certificate
+ * @ret rc Return status code
+ */
+static int certstat_payload ( struct x509_certificate *cert ) {
+
+ certstat ( cert );
+ return 0;
+}
+
+/** "certstat" command descriptor */
+static struct cert_command_descriptor certstat_cmd =
+ CERT_COMMAND_DESC ( struct cert_options, opts.certstat, 0, 0, NULL,
+ certstat_payload );
+
+/**
+ * The "certstat" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int certstat_exec ( int argc, char **argv ) {
+
+ return cert_exec ( argc, argv, &certstat_cmd );
+}
+
+/**
+ * "certstore" payload
+ *
+ * @v cert X.509 certificate
+ * @ret rc Return status code
+ */
+static int certstore_payload ( struct x509_certificate *cert ) {
+
+ /* Mark certificate as having been added explicitly */
+ cert->flags |= X509_FL_EXPLICIT;
+
+ return 0;
+}
+
+/** "certstore" command descriptor */
+static struct cert_command_descriptor certstore_cmd =
+ CERT_COMMAND_DESC ( struct cert_options, opts.certstore, 0, 1,
+ "[<uri|image>]", certstore_payload );
+
+/**
+ * The "certstore" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int certstore_exec ( int argc, char **argv ) {
+
+ return cert_exec ( argc, argv, &certstore_cmd );
+}
+
+/**
+ * "certfree" payload
+ *
+ * @v cert X.509 certificate
+ * @ret rc Return status code
+ */
+static int certfree_payload ( struct x509_certificate *cert ) {
+
+ /* Remove from certificate store */
+ certstore_del ( cert );
+
+ return 0;
+}
+
+/** "certfree" command descriptor */
+static struct cert_command_descriptor certfree_cmd =
+ CERT_COMMAND_DESC ( struct cert_options, opts.certfree, 0, 0, NULL,
+ certfree_payload );
+
+/**
+ * The "certfree" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int certfree_exec ( int argc, char **argv ) {
+
+ return cert_exec ( argc, argv, &certfree_cmd );
+}
+
+/** Certificate management commands */
+struct command certmgmt_commands[] __command = {
+ {
+ .name = "certstat",
+ .exec = certstat_exec,
+ },
+ {
+ .name = "certstore",
+ .exec = certstore_exec,
+ },
+ {
+ .name = "certfree",
+ .exec = certfree_exec,
+ },
+};