--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/cmd/SecurityCommand.cc Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2007 BBN Technologies Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <dtn-config.h>
+#endif
+
+#ifdef BSP_ENABLED
+
+#include <cstring>
+#include <cstdio>
+#include <oasys/util/Base16.h>
+
+#include "SecurityCommand.h"
+#include "security/SPD.h"
+#include "security/KeyDB.h"
+#include "security/Ciphersuite.h"
+
+namespace dtn {
+
+SecurityCommand::SecurityCommand()
+ : TclCommand("security")
+{
+ add_to_help("setpolicy [in | out] [pib] [pcb] [bab]",
+ "Set inbound or outbound policy to require the specified\n"
+ "combination of PIB, PCB, and/or BAB.");
+ add_to_help("setkey <host> <cs_num> <key>",
+ "Set the key to use for the specified host and ciphersuite\n"
+ "number. <host> may also be the wildcard symbol \"*\".");
+ add_to_help("dumpkeys",
+ "Dump the contents of the keystore to the screen.");
+ add_to_help("flushkeys",
+ "Erase all keys from the keystore.");
+}
+
+int
+SecurityCommand::exec(int argc, const char** argv, Tcl_Interp* interp)
+{
+ (void)interp;
+
+ if (argc < 2) {
+ resultf("need a security subcommand");
+ return TCL_ERROR;
+ }
+
+ const char* cmd = argv[1];
+
+ if (strcmp(cmd, "setpolicy") == 0) {
+ // security setpolicy [in | out] [psb] [cb] [bab]
+ if (argc < 3 || argc > 6) {
+ wrong_num_args(argc, argv, 2, 3, 6);
+ return TCL_ERROR;
+ }
+
+ SPD::spd_direction_t direction;
+ if (strcmp(argv[2], "in") == 0)
+ direction = SPD::SPD_DIR_IN;
+ else if (strcmp(argv[2], "out") == 0)
+ direction = SPD::SPD_DIR_OUT;
+ else {
+ resultf("invalid direction argument \"%s\" (must be one of "
+ "\"in\" or \"out\")", argv[2]);
+ return TCL_ERROR;
+ }
+
+ int policy = SPD::SPD_USE_NONE;
+ for (int i = 3; i < argc; i++) {
+ if (strcmp(argv[i], "pib") == 0)
+ policy |= SPD::SPD_USE_PIB;
+ else if (strcmp(argv[i], "pcb") == 0)
+ policy |= SPD::SPD_USE_PCB;
+ else if (strcmp(argv[i], "bab") == 0)
+ policy |= SPD::SPD_USE_BAB;
+ else {
+ resultf("invalid argument \"%s\"", argv[i]);
+ return TCL_ERROR;
+ }
+ }
+
+ SPD::set_global_policy(direction, (SPD::spd_policy_t)policy);
+
+ return TCL_OK;
+
+ } else if (strcmp(cmd, "setkey") == 0) {
+ // security setkey <host> <cs_num> <key>
+ if (argc != 5) {
+ wrong_num_args(argc, argv, 2, 5, 5);
+ return TCL_ERROR;
+ }
+
+ const char* host_arg = argv[2];
+ const char* cs_num_arg = argv[3];
+ const char* key_arg = argv[4];
+
+ int cs_num;
+ if (sscanf(cs_num_arg, "%i", &cs_num) != 1) {
+ resultf("invalid cs_num argument \"%s\"", cs_num_arg);
+ return TCL_ERROR;
+ }
+ if (! KeyDB::validate_cs_num(cs_num)) {
+ resultf("invalid ciphersuite number %#x", cs_num);
+ return TCL_ERROR;
+ }
+
+ size_t key_arg_len = strlen(key_arg);
+ if ((key_arg_len % 2) != 0) {
+ resultf("invalid key argument (must be even length)");
+ return TCL_ERROR;
+ }
+
+ size_t key_len = key_arg_len / 2;
+ if (! KeyDB::validate_key_len(cs_num, &key_len)) {
+ resultf("wrong key length for ciphersuite (expected %d bytes)",
+ (int)key_len);
+ return TCL_ERROR;
+ }
+
+ // convert key from ASCII hexadecimal to raw bytes
+ u_char* key = new u_char[key_len];
+ for (int i = 0; i < (int)key_len; i++)
+ {
+ int b = 0;
+
+ for (int j = 0; j <= 1; j++)
+ {
+ int c = (int)key_arg[2*i+j];
+ b <<= 4;
+
+ if (c >= '0' && c <= '9')
+ b |= c - '0';
+ else if (c >= 'A' && c <= 'F')
+ b |= c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ b |= c - 'a' + 10;
+ else {
+ resultf("invalid character '%c' in key argument",
+ (char)c);
+ delete key;
+ return TCL_ERROR;
+ }
+ }
+
+ key[i] = (u_char)(b);
+ }
+
+ KeyDB::Entry new_entry =
+ KeyDB::Entry(host_arg, cs_num, key, key_len);
+ KeyDB::set_key(new_entry);
+
+ delete key;
+ return TCL_OK;
+
+ } else if (strcmp(cmd, "dumpkeys") == 0) {
+ // security dumpkeys
+ if (argc != 2) {
+ wrong_num_args(argc, argv, 2, 2, 2);
+ return TCL_ERROR;
+ }
+
+ oasys::StringBuffer buf;
+ KeyDB::dump_header(&buf);
+ KeyDB::dump(&buf);
+ set_result(buf.c_str());
+ return TCL_OK;
+
+ } else if (strcmp(cmd, "flushkeys") == 0) {
+ // security flushkeys
+ if (argc != 2) {
+ wrong_num_args(argc, argv, 2, 2, 2);
+ return TCL_ERROR;
+ }
+
+ KeyDB::flush_keys();
+
+ } else {
+ resultf("no such security subcommand %s", cmd);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+} // namespace dtn
+
+#endif /* BSP_ENABLED */