AM_LDFLAGS = -static
endif
-CLEANFILES = spec_config.h dhcp6_messages.h dhcp6_messages.cc s-messages
+CLEANFILES = spec_config.h dhcp6_messages.h dhcp6_messages.cc \
+ sedhcp6_messages.h sedhcp6_messages.cc s-messages
man_MANS = kea-dhcp6.8
DISTCLEANFILES = $(man_MANS)
spec_config.h: spec_config.h.pre
$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
-dhcp6_messages.h dhcp6_messages.cc: s-messages
+dhcp6_messages.h dhcp6_messages.cc sedhcp6_messages.h sedhcp6_messages.cc: s-messages
-s-messages: dhcp6_messages.mes
+s-messages: dhcp6_messages.mes sedhcp6_messages.mes
$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/bin/dhcp6/dhcp6_messages.mes
+ $(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/bin/dhcp6/sedhcp6_messages.mes
touch $@
-BUILT_SOURCES = spec_config.h dhcp6_messages.h dhcp6_messages.cc
+BUILT_SOURCES = spec_config.h dhcp6_messages.h dhcp6_messages.cc \
+ sedhcp6_messages.h sedhcp6_messages.cc
# convenience archive
libdhcp6_la_SOURCES += kea_controller.cc
endif
-nodist_libdhcp6_la_SOURCES = dhcp6_messages.h dhcp6_messages.cc
-EXTRA_DIST += dhcp6_messages.mes
+nodist_libdhcp6_la_SOURCES = dhcp6_messages.h dhcp6_messages.cc
+nodist_libdhcp6_la_SOURCES += sedhcp6_messages.h sedhcp6_messages.cc
+EXTRA_DIST += dhcp6_messages.mes sedhcp6_messages.mes
sbin_PROGRAMS = kea-dhcp6
#define DHCP6_LOG_H
#include <dhcp6/dhcp6_messages.h>
+#include <dhcp6/sedhcp6_messages.h>
#include <log/logger_support.h>
#include <log/macros.h>
bool has_pubkey = false;
if (query->getOption(D6O_PUBLIC_KEY)) {
has_pubkey = true;
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, SEDHCP6_OPTION_RECEIVED)
+ .arg("public key");
if (query->getOptions(D6O_PUBLIC_KEY).size() > 1) {
answer->addOption(createStatusCode(STATUS_UnspecFail,
"More than one public key option"));
bool has_cert = false;
if (query->getOption(D6O_CERTIFICATE)) {
has_cert = true;
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, SEDHCP6_OPTION_RECEIVED)
+ .arg("certificate");
if (query->getOptions(D6O_CERTIFICATE).size() > 1) {
answer->addOption(createStatusCode(STATUS_UnspecFail,
"More than one certificate option"));
}
// Unsecure
if (!signopt_required && !signopt) {
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, SEDHCP6_UNSECURE);
return (true);
}
// signopt is true
tmstmp_opt = query->getOption(D6O_TIMESTAMP);
}
if (tmstmp_opt) {
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, SEDHCP6_OPTION_RECEIVED)
+ .arg("timestamp");
// Get timestamps in NTP format
vector<uint8_t> tmstmp_bin = tmstmp_opt->getData();
if (!ts_new.from_binary(tmstmp_bin)) {
// Update timestamps
if (update_tmstmp) {
- // TODO (ctx.host_ is a const)
- // ctx.host_->setRDlast(rd_new);
- // ctx.host_->setTSlast(ts_new);
+ Host* hp = const_cast<Host*>(ctx.host_.get());
+ hp->setRDlast(rd_new);
+ hp->setTSlast(ts_new);
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL,
+ SEDHCP6_TIMESTAMP_UPDATED);
}
}
if (state->getSignAnswers() && key && cred) {
// Add the credential (public key or certificate) option
uint16_t cred_type = D6O_PUBLIC_KEY;
+ string opt_name = "public key";
if (cred->getAsymKeyKind() == CERT) {
cred_type = D6O_CERTIFICATE;
+ opt_name = "certificate";
}
OptionBuffer buf = cred->exportkey(cred->getAsymKeyKind(), ASN1);
OptionPtr cred_opt(new Option(Option::V6, cred_type, buf));
answer->addOption(cred_opt);
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, SEDHCP6_OPTION_ADDED)
+ .arg(opt_name)
+ .arg(cred_opt->len());
// Add the signature option
uint8_t ha_id = SHA_256;
assert(sig_def);
OptionCustomPtr sig_opt(new OptionCustom(*sig_def, Option::V6, sig));
answer->addOption(sig_opt);
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, SEDHCP6_OPTION_ADDED)
+ .arg("signature")
+ .arg(sig_opt->len());
}
// Add timestamps
const OptionBuffer buf = val.to_binary();
OptionPtr tmsmtp_opt(new Option(Option::V6, D6O_TIMESTAMP, buf));
answer->addOption(tmsmtp_opt);
+ LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, SEDHCP6_OPTION_ADDED)
+ .arg("timestamp")
+ .arg(tmsmtp_opt->len());
}
}
ConstCfgSeDhcp6Ptr state =
CfgMgr::instance().getCurrentCfg()->getCfgSeDhcp6();
if (!state) {
- isc_throw(Unexpected, "no secure DHCPv6 configuration state");
+ LOG_ERROR(dhcp6_logger, SEDHCP6_SIGNATURE_FINALIZE_FAIL)
+ .arg("no secure DHCPv6 configuration state");
+ return;
}
if (!state->getSignAnswers()) {
- isc_throw(Unexpected, "Signing answers is disabled");
+ LOG_ERROR(dhcp6_logger, SEDHCP6_SIGNATURE_FINALIZE_FAIL)
+ .arg("Signing answers is disabled");
+ return;
}
CfgSeDhcp6::AsymPtr key = state->getPrivateKey();
if (!key) {
- isc_throw(Unexpected, "No private key configured");
+ LOG_ERROR(dhcp6_logger, SEDHCP6_SIGNATURE_FINALIZE_FAIL)
+ .arg("No private key configured");
+ return;
}
if (!tbs->getSignatureOffset()) {
- isc_throw(Unexpected, "null signature offset");
+ LOG_ERROR(dhcp6_logger, SEDHCP6_SIGNATURE_FINALIZE_FAIL)
+ .arg("null signature offset");
+ return;
}
// TODO
}
} else if (config_id.compare("relay-supplied-options") == 0) {
parser = new RSOOListConfigParser(config_id);
} else if (config_id.compare("secure-dhcp6") == 0) {
- parser = new SeDhcp6Parser(config_id, Option::V6);
+ parser = new SeDhcp6Parser(config_id, Option::V6);
} else {
isc_throw(DhcpConfigError,
"unsupported global configuration parameter: "
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
- [<!ENTITY mdash "—">]>
+ [<!ENTITY mdash "—">]>
<!--
- Copyright (C) 2011, 2014 Internet Systems Consortium, Inc. ("ISC")
-
--- /dev/null
+# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+$NAMESPACE isc::dhcp
+
+% SEDHCP6_OPTION_ADDED secure DHCPv6 option has been added: type %1, size %2
+This debug message is printed when a secure DHCPv6 option is added
+to an answer packet.
+
+% SEDHCP6_OPTION_RECEIVED secure DHCPv6 option has been received: type %1
+This debug message is printed when a secure DHCPv6 option is found
+during incoming packet validation.
+
+% SEDHCP6_SIGNATURE_FINALIZE_FAIL signature finalize error: %1
+This error message indicates that the signature finalize has failed.
+This is a "should not happen" condition which reflects an internal
+error.
+
+% SEDHCP6_TIMESTAMP_UPDATED timestamps have been updated
+This debug message is printed when the host timestamps have been updated.
+
+% SEDHCP6_UNSECURE incoming packet is unsecure
+This debug message is printed when the secure DHCPv6 validation
+concludes the incoming packet is unsecure.
+
#define HWTYPE_INFINIBAND 0x0020
// Secure DHCPv6 (draft-ietf-dhc-sedhcpv6-07.txt)
+// (can't use an enum because HashAlgorithm name is already taken)
#define SHA_256 1
#define SHA_512 2
#define RSASSA_PKCS1v1_5 1
isc::dhcp::OptionCollection& options,
size_t* relay_msg_offset /* = 0 */,
size_t* relay_msg_len /* = 0 */,
- size_t* signature_offset /* = 0 */) {
+ size_t* signature_offset /* = 0 */) {
size_t offset = 0;
size_t length = buf.size();
continue;
}
- if (opt_type == D6O_SIGNATURE && signature_offset) {
- // remember offset of the beginning of the (last) signature option
- *signature_offset = offset;
- }
+ if (opt_type == D6O_SIGNATURE && signature_offset) {
+ // remember offset of the beginning of the (last) signature option
+ *signature_offset = offset;
+ }
if (opt_type == D6O_VENDOR_OPTS) {
if (offset + 4 > length) {
for (OptionCollection::const_iterator it = options_.begin();
it != options_.end(); ++it) {
// Remember where the certificate is inserted
- if (it->first == D6O_CERTIFICATE) {
+ if (it->first == D6O_SIGNATURE) {
signature_offset_ = buffer_out_.getLength();
}
it->second->pack(buffer_out_);
struct in_pktinfo* pktinfo =(struct in_pktinfo *)CMSG_DATA(cmsg);
memset(pktinfo, 0, sizeof(struct in_pktinfo));
pktinfo->ipi_ifindex = pkt->getIndex();
- pktinfo->ipi_spec_dst.s_addr = htonl(pkt->getLocalAddr()); // set the source IP address
+ pktinfo->ipi_spec_dst.s_addr = htonl(pkt->getLocalAddr()); // set the source IP address
m.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
#endif
typeid(OptionCustom));
LibDhcpTest::testStdOptionDefs6(D6O_TIMESTAMP, begin, begin + 8,
- typeid(OptionCustom));
+ typeid(Option));
}
// This test checks if the DHCPv6 option definition can be searched by
///
/// @param timestamp Date in NTP format
void setRDlast(const isc::util::Ntp& timestamp) {
- rd_last_ = timestamp;
+ rd_last_ = timestamp;
}
/// @brief Returns RDlast
const isc::util::Ntp& getRDlast() const {
- return (rd_last_);
+ return (rd_last_);
}
/// @brief Sets the date of the last received and accepted timestamp
///
/// @param timestamp Date in NTP format
void setTSlast(const isc::util::Ntp& timestamp) {
- ts_last_ = timestamp;
+ ts_last_ = timestamp;
}
/// @brief Returns TSlast
const isc::util::Ntp& getTSlast() const {
- return (ts_last_);
+ return (ts_last_);
}
/// @brief Returns information about the host in the textual format.
Ntp::Ntp(const struct timeval* tv)
{
ntp_sec_ = static_cast<uint32_t>(tv->tv_sec) + EPOCH_ADJUST;
- uint32_t fcvt = (tv->tv_usec * 65536U) / 1000000UL;
+ uint64_t fcvt = (static_cast<uint64_t>(tv->tv_usec) * 65536U) / 1000000UL;
ntp_fraction_ = static_cast<uint16_t>(fcvt & 0xffff);
}