charon-cmd: load certificates and RSA private keys
authorMartin Willi <martin@revosec.ch>
Tue, 26 Mar 2013 14:42:06 +0000 (15:42 +0100)
committerMartin Willi <martin@revosec.ch>
Mon, 6 May 2013 13:28:26 +0000 (15:28 +0200)
src/charon-cmd/Makefile.am
src/charon-cmd/charon-cmd.c
src/charon-cmd/cmd/cmd_creds.c [new file with mode: 0644]
src/charon-cmd/cmd/cmd_creds.h [new file with mode: 0644]
src/charon-cmd/cmd/cmd_options.c
src/charon-cmd/cmd/cmd_options.h

index ff360c1..2c9f1ba 100644 (file)
@@ -3,6 +3,7 @@ sbin_PROGRAMS = charon-cmd
 charon_cmd_SOURCES = \
        cmd/cmd_options.h cmd/cmd_options.c \
        cmd/cmd_connection.h cmd/cmd_connection.c \
+       cmd/cmd_creds.h cmd/cmd_creds.c \
        charon-cmd.c
 
 charon-cmd.o : $(top_builddir)/config.status
index 90cc8b6..4969c96 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "cmd/cmd_options.h"
 #include "cmd/cmd_connection.h"
+#include "cmd/cmd_creds.h"
 
 /**
  * Loglevel configuration
@@ -46,6 +47,11 @@ static level_t levels[DBG_MAX];
 static cmd_connection_t *conn;
 
 /**
+ * Credential backend
+ */
+static cmd_creds_t *creds;
+
+/**
  * hook in library for debugging messages
  */
 extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
@@ -76,6 +82,14 @@ static void cleanup_conn()
 }
 
 /**
+ * Clean up credentials atexit()
+ */
+static void cleanup_creds()
+{
+       DESTROY_IF(creds);
+}
+
+/**
  * Run the daemon and handle unix signals
  */
 static int run()
@@ -253,7 +267,8 @@ static void handle_arguments(int argc, char *argv[])
                                printf("%s, strongSwan %s\n", "charon-cmd", VERSION);
                                exit(0);
                        default:
-                               if (conn->handle(conn, opt, optarg))
+                               if (conn->handle(conn, opt, optarg) ||
+                                       creds->handle(creds, opt, optarg))
                                {
                                        continue;
                                }
@@ -300,24 +315,12 @@ int main(int argc, char *argv[])
        {
                levels[group] = LEVEL_CTRL;
        }
-       conn = cmd_connection_create();
-       atexit(cleanup_conn);
-
-       handle_arguments(argc, argv);
+       charon->load_loggers(charon, levels, TRUE);
 
        if (!lookup_uid_gid())
        {
                exit(SS_RC_INITIALIZATION_FAILED);
        }
-       charon->load_loggers(charon, levels, TRUE);
-
-       if (uname(&utsname) != 0)
-       {
-               memset(&utsname, 0, sizeof(utsname));
-       }
-       DBG1(DBG_DMN, "Starting charon-cmd IKE client (strongSwan %s, %s %s, %s)",
-                VERSION, utsname.sysname, utsname.release, utsname.machine);
-
        if (!charon->initialize(charon,
                        lib->settings->get_str(lib->settings, "charon-cmd.load", PLUGINS)))
        {
@@ -328,6 +331,20 @@ int main(int argc, char *argv[])
                exit(SS_RC_INITIALIZATION_FAILED);
        }
 
+       conn = cmd_connection_create();
+       atexit(cleanup_conn);
+       creds = cmd_creds_create();
+       atexit(cleanup_creds);
+
+       handle_arguments(argc, argv);
+
+       if (uname(&utsname) != 0)
+       {
+               memset(&utsname, 0, sizeof(utsname));
+       }
+       DBG1(DBG_DMN, "Starting charon-cmd IKE client (strongSwan %s, %s %s, %s)",
+                VERSION, utsname.sysname, utsname.release, utsname.machine);
+
        /* add handler for SEGV and ILL,
         * INT, TERM and HUP are handled by sigwait() in run() */
        action.sa_handler = segv_handler;
diff --git a/src/charon-cmd/cmd/cmd_creds.c b/src/charon-cmd/cmd/cmd_creds.c
new file mode 100644 (file)
index 0000000..45f1652
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * 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 "cmd_creds.h"
+
+#include <utils/debug.h>
+#include <credentials/sets/mem_cred.h>
+
+typedef struct private_cmd_creds_t private_cmd_creds_t;
+
+/**
+ * Private data of an cmd_creds_t object.
+ */
+struct private_cmd_creds_t {
+
+       /**
+        * Public cmd_creds_t interface.
+        */
+       cmd_creds_t public;
+
+       /**
+        * Reused in-memory credential set
+        */
+       mem_cred_t *creds;
+};
+
+/**
+ * Load a trusted certificate from path
+ */
+static void load_cert(private_cmd_creds_t *this, char *path)
+{
+       certificate_t *cert;
+
+       cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+                                                         BUILD_FROM_FILE, path, BUILD_END);
+       if (!cert)
+       {
+               DBG1(DBG_CFG, "loading certificate from '%s' failed", path);
+               exit(1);
+       }
+       this->creds->add_cert(this->creds, TRUE, cert);
+}
+
+/**
+ * Load a private key of given kind from path
+ */
+static void load_key(private_cmd_creds_t *this, key_type_t type, char *path)
+{
+       private_key_t *privkey;
+
+       privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+                                                                BUILD_FROM_FILE, path, BUILD_END);
+       if (!privkey)
+       {
+               DBG1(DBG_CFG, "loading %N private key from '%s' failed",
+                        key_type_names, type, path);
+               exit(1);
+       }
+       this->creds->add_key(this->creds, privkey);
+}
+
+METHOD(cmd_creds_t, handle, bool,
+       private_cmd_creds_t *this, cmd_option_type_t opt, char *arg)
+{
+       switch (opt)
+       {
+               case CMD_OPT_CERT:
+                       load_cert(this, arg);
+                       break;
+               case CMD_OPT_RSA:
+                       load_key(this, KEY_RSA, arg);
+                       break;
+               default:
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+METHOD(cmd_creds_t, destroy, void,
+       private_cmd_creds_t *this)
+{
+       lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
+       this->creds->destroy(this->creds);
+       free(this);
+}
+
+/**
+ * See header
+ */
+cmd_creds_t *cmd_creds_create()
+{
+       private_cmd_creds_t *this;
+
+       INIT(this,
+               .public = {
+                       .handle = _handle,
+                       .destroy = _destroy,
+               },
+               .creds = mem_cred_create(),
+       );
+
+       lib->credmgr->add_set(lib->credmgr, &this->creds->set);
+
+       return &this->public;
+}
diff --git a/src/charon-cmd/cmd/cmd_creds.h b/src/charon-cmd/cmd/cmd_creds.h
new file mode 100644 (file)
index 0000000..053e596
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup cmd_creds cmd_creds
+ * @{ @ingroup cmd
+ */
+
+#ifndef CMD_CREDS_H_
+#define CMD_CREDS_H_
+
+#include <library.h>
+
+#include "cmd_options.h"
+
+typedef struct cmd_creds_t cmd_creds_t;
+
+/**
+ * Credential backend providing certificates, private keys and shared secrets.
+ */
+struct cmd_creds_t {
+
+       /**
+        * Handle a command line options related to credentials.
+        *
+        * @param opt           option to handle
+        * @param arg           option argument
+        * @return                      TRUE if option handled
+        */
+       bool (*handle)(cmd_creds_t *this, cmd_option_type_t opt, char *arg);
+
+       /**
+        * Destroy a cmd_creds_t.
+        */
+       void (*destroy)(cmd_creds_t *this);
+};
+
+/**
+ * Create a cmd_creds instance.
+ */
+cmd_creds_t *cmd_creds_create();
+
+#endif /** CMD_CREDS_H_ @}*/
index 899cdd1..4344bf2 100644 (file)
@@ -29,4 +29,8 @@ cmd_option_t cmd_options[CMD_OPT_COUNT] = {
          "DNS name or address to connect to" },
        { CMD_OPT_IDENTITY, "identity", required_argument, "identity",
          "identity the client uses for the IKE exchange" },
+       { CMD_OPT_CERT, "cert", required_argument, "path",
+         "trusted certificate, for authentication or trust chain validation" },
+       { CMD_OPT_RSA, "rsa", required_argument, "path",
+         "RSA private key to use for authentication" },
 };
index 81fb54f..358108d 100644 (file)
@@ -32,6 +32,8 @@ enum cmd_option_type_t {
        CMD_OPT_VERSION,
        CMD_OPT_HOST,
        CMD_OPT_IDENTITY,
+       CMD_OPT_CERT,
+       CMD_OPT_RSA,
 
        CMD_OPT_COUNT
 };