1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (C) 2018-2024 Internet Systems Consortium, Inc. ("ISC")
//
// 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.h>
#include <util/encode/encode.h>

#include <sstream><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <stdint.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

using namespace std;
using namespace isc::util;

namespace isc {
namespace dhcp {

    Option6Auth::Option6Auth(const uint8_t proto, const uint8_t algo,
                             const uint8_t method, const uint64_t rdm,
                             const std::vector<uint8_t>& info)
    : Option(Option::V6, D6O_AUTH),
      protocol_(proto), algorithm_(algo),
      rdm_method_(method), rdm_value_(rdm),
      auth_info_(info) {
}

OptionPtr
Option6Auth::clone() const {
    return (cloneInternal<Option6Auth>());
}

void
Option6Auth::pack(isc::util::OutputBuffer& buf, bool) const {
    if (buf.getCapacity() < (OPTION6_AUTH_MIN_LEN + OPTION6_HASH_MSG_LEN + OPTION6_HDR)) {
       isc_throw(OutOfRange, "Option " << type_ << "Buffer too small for"
               "packing data");
    }

    //header = option code + length
    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_);
    // algorithm 1 byte
    buf.writeUint8(algorithm_);
    // replay detection method
    buf.writeUint8(rdm_method_);
    // replay detection value
    buf.writeUint64( rdm_value_);
    // authentication information for reconfig msg
    // should have zero

    for (auto const& i : auth_info_) {
        buf.writeUint8(i);
    }
}

void
Option6Auth::packHashInput(isc::util::OutputBuffer& buf) const {
    if (buf.getCapacity() < (OPTION6_AUTH_MIN_LEN + OPTION6_HASH_MSG_LEN + OPTION6_HDR)) {
       isc_throw(OutOfRange, "Option " << type_ << "Buffer too small for"
               "computing hash input");
    }

    //header = option code + length
    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_);
    // algorithm 1 byte
    buf.writeUint8(algorithm_);
    // replay detection method
    buf.writeUint8(rdm_method_);
    // replay detection value
    buf.writeUint64(rdm_value_);
    // authentication information for reconfig msg
    // should have zero
    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");
   }

   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); });
}

std::string
Option6Auth::toText(int indent) const {
    stringstream output;
    std::string in(indent, ' '); //base indent

    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_);

    return output.str();
}

} // end  namespace dhcp
} // end namespace isc