servlib/security/KeyDB.cc
changeset 0 2b3e5ec03512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/security/KeyDB.cc	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,285 @@
+/*
+ * 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 <string>
+#include <oasys/compat/inttypes.h>
+#include <oasys/util/StringBuffer.h>
+
+#include "KeyDB.h"
+#include "Ciphersuite.h"
+
+namespace dtn {
+
+template <>
+KeyDB* oasys::Singleton<KeyDB, false>::instance_ = NULL;
+
+static const char * log = "/dtn/bundle/security";
+
+KeyDB::KeyDB()
+{
+}
+
+KeyDB::~KeyDB()
+{
+}
+
+void
+KeyDB::init()
+{
+    if (instance_ != NULL) 
+    {
+        PANIC("KeyDB already initialized");
+    }
+    
+    instance_ = new KeyDB();
+	log_debug_p(log, "KeyDB::init() done");
+}
+
+void
+KeyDB::set_key(Entry& entry)
+{
+    EntryList& keys = instance()->keys_;
+    EntryList::iterator iter;
+
+    for (iter = keys.begin(); iter != keys.end(); iter++)
+    {
+        if (iter->match(entry)) {
+            *iter = entry;
+            return;
+        }
+    }
+    
+    // if we get here then there was no existing matching entry;
+    // insert the new entry just before any existing wildcard entries
+    for (iter = keys.begin();
+         iter != keys.end() && iter->host() != std::string("*");
+         iter++)
+    {
+    }
+    keys.insert(iter, entry);
+	log_debug_p(log, "KeyDB::set_key() done");
+}
+
+const KeyDB::Entry*
+KeyDB::find_key(const char* host, u_int16_t cs_num)
+{
+    EntryList& keys = instance()->keys_;
+    EntryList::iterator iter;
+	log_debug_p(log, "KeyDB::find_key()");
+
+    for (iter = keys.begin(); iter != keys.end(); iter++)
+    {
+        if (iter->match_wildcard(host, cs_num))
+            return &(*iter);
+    }
+    
+    // not found
+    return NULL;
+}
+
+void
+KeyDB::del_key(const char* host, u_int16_t cs_num)
+{
+    EntryList& keys = instance()->keys_;
+    EntryList::iterator iter;
+	log_debug_p(log, "KeyDB::del_key()");
+
+    for (iter = keys.begin(); iter != keys.end(); iter++)
+    {
+        if (iter->match(host, cs_num)) {
+            keys.erase(iter);
+            return;
+        }
+    }
+
+    // if not found, then nothing to do
+}
+
+void
+KeyDB::flush_keys()
+{
+	log_debug_p(log, "KeyDB::flush_keys()");
+    instance()->keys_.clear();
+}
+
+/// Dump the current contents of the KeyDB in human-readable form.
+void
+KeyDB::dump(oasys::StringBuffer* buf)
+{
+    EntryList& keys = instance()->keys_;
+    EntryList::iterator iter;
+
+    for (iter = keys.begin(); iter != keys.end(); iter++)
+        iter->dump(buf);
+}
+
+/// Dump a human-readable header for the output of dump().
+void
+KeyDB::dump_header(oasys::StringBuffer* buf)
+{
+    KeyDB::Entry::dump_header(buf);
+}
+
+/// Validate the specified ciphersuite number (see if it corresponds
+/// to a registered ciphersuite).
+bool
+KeyDB::validate_cs_num(u_int16_t cs_num)
+{
+    return (Ciphersuite::find_suite(cs_num) != NULL);
+}
+
+bool
+KeyDB::validate_key_len(u_int16_t cs_num, size_t* key_len)
+{
+    Ciphersuite* cs =
+        dynamic_cast<Ciphersuite*>(Ciphersuite::find_suite(cs_num));
+    if (cs == NULL)
+        return false;
+    if (*key_len != cs->result_len()) {
+        *key_len = cs->result_len();
+        return false;
+    }
+
+    return true;
+}
+
+/// Detailed constructor.
+KeyDB::Entry::Entry(const char* host, u_int16_t cs_num, const u_char* key,
+                    size_t key_len)
+    : host_(host),
+      cs_num_(cs_num),
+      key_len_(key_len)
+{
+    ASSERT(key != NULL);
+    ASSERT(key_len != 0);
+
+    key_ = new u_char[key_len];
+    memcpy(key_, key, key_len);
+}
+
+/// Default constructor.
+KeyDB::Entry::Entry()
+    : host_(""),
+      cs_num_(0),
+      key_(NULL),
+      key_len_(0)
+{
+}
+
+/// Copy constructor.
+KeyDB::Entry::Entry(const Entry& other)
+    : host_(other.host_),
+      cs_num_(other.cs_num_),
+      key_len_(other.key_len_)
+{
+    if (other.key_ == NULL)
+        key_ = NULL;
+    else {
+        key_ = new u_char[other.key_len_];
+        memcpy(key_, other.key_, other.key_len_);
+    }
+}
+
+/// Destructor.
+KeyDB::Entry::~Entry()
+{
+    if (key_ != NULL) {
+        memset(key_, 0, key_len_);
+        delete key_;
+        key_len_ = 0;
+    } else
+        ASSERT(key_len_ == 0);
+}
+
+/// Assignment operator.
+void
+KeyDB::Entry::operator=(const Entry& other)
+{
+    if (key_ != NULL) {
+        memset(key_, 0, key_len_);
+        delete key_;
+    }
+
+    host_   = other.host_;
+    cs_num_ = other.cs_num_;
+
+    if (other.key_ == NULL)
+        key_ = NULL;
+    else {
+        key_ = new u_char[other.key_len_];
+        memcpy(key_, other.key_, other.key_len_);
+    }
+
+    key_len_ = other.key_len_;
+}
+
+/// Determine if two entries have the same host and ciphersuite
+/// number.
+bool
+KeyDB::Entry::match(const Entry& other) const
+{
+    return (host_ == other.host_ && cs_num_ == other.cs_num_);
+}
+
+/// Determine if this entry matches the given host and ciphersuite
+/// number.
+bool
+KeyDB::Entry::match(const char* host, u_int16_t cs_num) const
+{
+    return (host_ == std::string(host) && cs_num_ == cs_num);
+}
+
+/// Same as match(), but also matches wildcard entries (where host
+/// is "*").
+bool
+KeyDB::Entry::match_wildcard(const char* host, u_int16_t cs_num) const
+{
+    return ((host_ == std::string(host) || host_ == std::string("*"))
+            && cs_num_ == cs_num);
+}
+
+/// Dump this entry to a StringBuffer in human-readable form.
+void
+KeyDB::Entry::dump(oasys::StringBuffer* buf) const
+{
+    buf->appendf("%15s   0x%03x  ", host_.c_str(), cs_num_);
+    //buf->appendf("(-- not shown --)");
+    for (int i = 0; i < (int)key_len_; i++)
+        buf->appendf("%02x", (int)key_[i]);
+    buf->appendf("\n");
+}
+
+/// Dump a human-readable header for the output of dump().
+void
+KeyDB::Entry::dump_header(oasys::StringBuffer* buf)
+{
+    buf->appendf("host              cs_num   key\n"                );
+    buf->appendf("---------------   ------   -------------------\n");
+}
+
+} // namespace dtn
+
+#endif  /* BSP_ENABLED */