2022-05-23 17:38:46 +03:00
|
|
|
// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC")
|
2018-06-18 15:46:51 +02:00
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <dhcp/dhcp6.h>
|
|
|
|
#include <dhcp/libdhcp++.h>
|
|
|
|
#include <dhcp/option6_auth.h>
|
|
|
|
#include <dhcp/option_space.h>
|
|
|
|
#include <exceptions/exceptions.h>
|
|
|
|
#include <util/io_utilities.h>
|
2018-07-12 14:48:12 +02:00
|
|
|
#include <util/encode/hex.h>
|
2018-06-18 15:46:51 +02:00
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace isc::util;
|
|
|
|
|
|
|
|
namespace isc {
|
|
|
|
namespace dhcp {
|
|
|
|
|
2018-07-12 14:48:12 +02:00
|
|
|
Option6Auth::Option6Auth(const uint8_t proto, const uint8_t algo,
|
|
|
|
const uint8_t method, const uint64_t rdm,
|
|
|
|
const std::vector<uint8_t>& info)
|
2018-06-18 15:46:51 +02:00
|
|
|
: Option(Option::V6, D6O_AUTH),
|
|
|
|
protocol_(proto), algorithm_(algo),
|
|
|
|
rdm_method_(method), rdm_value_(rdm),
|
|
|
|
auth_info_(info) {
|
|
|
|
}
|
|
|
|
|
|
|
|
OptionPtr
|
|
|
|
Option6Auth::clone() const {
|
2018-07-12 14:48:12 +02:00
|
|
|
return (cloneInternal<Option6Auth>());
|
2018-06-18 15:46:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-05-06 00:16:48 +03:00
|
|
|
Option6Auth::pack(isc::util::OutputBuffer& buf, bool) const {
|
2018-06-18 15:51:16 +02:00
|
|
|
if (buf.getCapacity() < (OPTION6_AUTH_MIN_LEN + OPTION6_HASH_MSG_LEN + OPTION6_HDR)) {
|
|
|
|
isc_throw(OutOfRange, "Option " << type_ << "Buffer too small for"
|
|
|
|
"packing data");
|
2018-06-18 15:46:51 +02:00
|
|
|
}
|
2018-07-12 14:48:12 +02:00
|
|
|
|
|
|
|
//header = option code + length
|
2018-06-18 15:46:51 +02:00
|
|
|
buf.writeUint16(type_);
|
|
|
|
// length = 11 bytes fixed field length+ length of auth information
|
|
|
|
buf.writeUint16(11 + uint16_t(auth_info_.size()));
|
|
|
|
// protocol 1 byte
|
|
|
|
buf.writeUint8(protocol_);
|
2021-01-22 01:36:41 +02:00
|
|
|
// algorithm 1 byte
|
2018-06-18 15:46:51 +02:00
|
|
|
buf.writeUint8(algorithm_);
|
|
|
|
// replay detection method
|
|
|
|
buf.writeUint8(rdm_method_);
|
|
|
|
// replay detection value
|
|
|
|
buf.writeUint64( rdm_value_);
|
|
|
|
// authentication information for reconfig msg
|
2018-07-12 14:48:12 +02:00
|
|
|
// should have zero
|
2018-06-18 15:46:51 +02:00
|
|
|
|
|
|
|
for (auto i : auth_info_) {
|
|
|
|
buf.writeUint8(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Option6Auth::packHashInput(isc::util::OutputBuffer& buf) const {
|
2018-06-18 15:51:16 +02:00
|
|
|
if (buf.getCapacity() < (OPTION6_AUTH_MIN_LEN + OPTION6_HASH_MSG_LEN + OPTION6_HDR)) {
|
|
|
|
isc_throw(OutOfRange, "Option " << type_ << "Buffer too small for"
|
2018-06-18 15:46:51 +02:00
|
|
|
"computing hash input");
|
|
|
|
}
|
|
|
|
|
2018-07-12 14:48:12 +02:00
|
|
|
//header = option code + length
|
2018-06-18 15:46:51 +02:00
|
|
|
buf.writeUint16(type_);
|
|
|
|
// length = 11 bytes fixed field length+ length of auth information
|
|
|
|
buf.writeUint16(OPTION6_AUTH_MIN_LEN + OPTION6_HASH_MSG_LEN);
|
|
|
|
// protocol 1 byte
|
|
|
|
buf.writeUint8(protocol_);
|
2021-01-22 01:36:41 +02:00
|
|
|
// algorithm 1 byte
|
2018-06-18 15:46:51 +02:00
|
|
|
buf.writeUint8(algorithm_);
|
|
|
|
// replay detection method
|
|
|
|
buf.writeUint8(rdm_method_);
|
|
|
|
// replay detection value
|
|
|
|
buf.writeUint64(rdm_value_);
|
|
|
|
// authentication information for reconfig msg
|
2018-07-12 14:48:12 +02:00
|
|
|
// should have zero
|
2018-06-18 15:46:51 +02:00
|
|
|
for (uint8_t i = 0; i < OPTION6_HASH_MSG_LEN; i++) {
|
|
|
|
buf.writeUint8(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Option6Auth::unpack(OptionBufferConstIter begin,
|
|
|
|
OptionBufferConstIter end) {
|
|
|
|
// throw if it contains length less than minimum size of the auth option
|
|
|
|
if (distance(begin, end) < Option6Auth::OPTION6_AUTH_MIN_LEN) {
|
|
|
|
isc_throw(OutOfRange, "Option " << type_ << " truncated");
|
|
|
|
}
|
2018-07-12 14:48:12 +02:00
|
|
|
|
2018-06-18 15:46:51 +02:00
|
|
|
protocol_ = *begin;
|
|
|
|
begin += sizeof(uint8_t);
|
|
|
|
|
|
|
|
algorithm_ = *begin;
|
|
|
|
begin += sizeof(uint8_t);
|
|
|
|
|
|
|
|
rdm_method_ = *begin;
|
|
|
|
begin += sizeof(uint8_t);
|
|
|
|
|
|
|
|
rdm_value_ = isc::util::readUint64(&(*begin), sizeof(uint64_t));
|
|
|
|
begin += sizeof(uint64_t);
|
|
|
|
|
|
|
|
auth_info_.erase(auth_info_.begin(), auth_info_.end());
|
|
|
|
std::for_each(begin, end, [this](uint8_t msgdata)
|
|
|
|
{ auth_info_.push_back(msgdata); });
|
|
|
|
}
|
|
|
|
|
2018-07-12 14:48:12 +02:00
|
|
|
std::string
|
2018-06-18 15:46:51 +02:00
|
|
|
Option6Auth::toText(int indent) const {
|
|
|
|
stringstream output;
|
|
|
|
std::string in(indent, ' '); //base indent
|
2018-07-12 14:48:12 +02:00
|
|
|
|
|
|
|
output << in << "protocol=" << static_cast<int>(protocol_)
|
|
|
|
<< ", algorithm=" << static_cast<int>(algorithm_)
|
|
|
|
<< ", rdm method=" << static_cast<int>(rdm_method_)
|
|
|
|
<< ", rdm value=" << rdm_value_
|
|
|
|
<< ", value=" << isc::util::encode::encodeHex(auth_info_);
|
|
|
|
|
2018-06-18 15:51:16 +02:00
|
|
|
return output.str();
|
2018-06-18 15:46:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} // end namespace dhcp
|
|
|
|
} // end namespace isc
|