123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- // Copyright (C) 2015-2017 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/libdhcp++.h>
- #include <dhcp/option.h>
- #include <dhcp/option_definition.h>
- #include <dhcp/option_space.h>
- #include <dhcpsrv/cfg_option.h>
- #include <dhcpsrv/db_exceptions.h>
- #include <dhcpsrv/dhcpsrv_log.h>
- #include <dhcpsrv/radius_host_data_source.h>
- #include <dhcpsrv/db_exceptions.h>
- #include <util/buffer.h>
- #include <util/optional_value.h>
- #include <boost/algorithm/string/split.hpp>
- #include <boost/algorithm/string/classification.hpp>
- #include <boost/array.hpp>
- #include <boost/pointer_cast.hpp>
- #include <boost/static_assert.hpp>
- #include <radcli/radcli.h>
- #include <stdint.h>
- #include <string>
- using namespace isc;
- using namespace isc::asiolink;
- using namespace isc::dhcp;
- using namespace isc::util;
- using namespace std;
- /// @brief Maximum size of an IPv6 address represented as a text string.
- ///
- /// This is 32 hexadecimal characters written in 8 groups of four, plus seven
- /// colon separators.
- const size_t ADDRESS6_TEXT_MAX_LEN = 39;
- /// @brief Maximum length of classes stored in a dhcp4/6_client_classes
- /// columns.
- const size_t CLIENT_CLASSES_MAX_LEN = 255;
- /// @brief Maximum length of the hostname stored in DNS.
- ///
- /// This length is restricted by the length of the domain-name carried
- /// in the Client FQDN %Option (see RFC4702 and RFC4704).
- const size_t HOSTNAME_MAX_LEN = 255;
- /// @brief Maximum length of option value.
- const size_t OPTION_VALUE_MAX_LEN = 4096;
- /// @brief Maximum length of option value specified in textual format.
- const size_t OPTION_FORMATTED_VALUE_MAX_LEN = 8192;
- /// @brief Maximum length of option space name.
- const size_t OPTION_SPACE_MAX_LEN = 128;
- /// @brief Maximum length of the server hostname.
- const size_t SERVER_HOSTNAME_MAX_LEN = 64;
- /// @brief Maximum length of the boot file name.
- const size_t BOOT_FILE_NAME_MAX_LEN = 128;
- /// @brief Numeric value representing last supported identifier.
- ///
- /// This value is used to validate whether the identifier type stored in
- /// a database is within bounds. of supported identifiers.
- const uint8_t MAX_IDENTIFIER_TYPE = static_cast<uint8_t>(Host::LAST_IDENTIFIER_TYPE);
- namespace isc {
- namespace dhcp {
- RadiusHostDataSource::
- RadiusHostDataSource(const DatabaseConnection::ParameterMap& parameters) {
- int res;
- rh = rc_new();
- if (rh == NULL) {
- isc_throw(isc::Exception, "Failed to initialize Radius client");
- }
- rh = rc_config_init(rh);
- if (rh == NULL) {
- isc_throw(isc::Exception, "Failed to initialize Radius client");
- }
- res = rc_add_config(rh, "auth_order", "radius", NULL, 0);
- if (res != 0) {
- isc_throw(isc::Exception, "Failed to configure Radius auth_order");
- }
- /* TODO: just define manually the few attributes we need */
- res = rc_add_config(rh, "dictionary", "/usr/share/radcli/dictionary", NULL, 0);
- if (res != 0) {
- isc_throw(isc::Exception, "Failed to configure Radius dictionary");
- }
- res = rc_add_config(rh, "radius_timeout", "1", NULL, 0);
- if (res != 0) {
- isc_throw(isc::Exception, "Failed to configure Radius timeout");
- }
- res = rc_add_config(rh, "radius_retries", "1", NULL, 0);
- if (res != 0) {
- isc_throw(isc::Exception, "Failed to configure Radius retries");
- }
- res = rc_add_config(rh, "authserver", "127.0.0.1:1812:mysecret", NULL, 0);
- if (res != 0) {
- isc_throw(isc::Exception, "Failed to configure Radius authserver");
- }
- // Test and apply config (this also setups the necessary structures to
- // send requests to the radius server)
- res = rc_test_config(rh, "kea");
- if (res != 0) {
- isc_throw(isc::Exception, "Failed to apply radcli configuration");
- }
- // Load dictionary
- res = rc_read_dictionary(rh, rc_conf_str(rh, "dictionary"));
- if (res != 0) {
- isc_throw(isc::Exception, "Failed to read Radius dictionary");
- }
- }
- RadiusHostDataSource::~RadiusHostDataSource() {
- }
- void
- RadiusHostDataSource::add(const HostPtr& host) {
- // cannot add a host with radius
- isc_throw(NotImplemented, "RadiusHostDataSource::add not implemented");
- }
- bool
- RadiusHostDataSource::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
- // cannot delete hosts with radius
- isc_throw(NotImplemented, "RadiusHostDataSource::del not implemented");
- return false;
- }
- bool
- RadiusHostDataSource::del4(const SubnetID& subnet_id,
- const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin, const size_t identifier_len) {
- // cannot delete hosts with radius
- isc_throw(NotImplemented, "RadiusHostDataSource::del4 not implemented");
- return false;
- }
- bool
- RadiusHostDataSource::del6(const SubnetID& subnet_id,
- const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin, const size_t identifier_len) {
- // cannot delete hosts with radius
- isc_throw(NotImplemented, "RadiusHostDataSource::del6 not implemented");
- return false;
- }
- ConstHostCollection
- RadiusHostDataSource::getAll(const HWAddrPtr& hwaddr,
- const DuidPtr& duid) const {
- if (duid){
- return (getAll(Host::IDENT_DUID, &duid->getDuid()[0],
- duid->getDuid().size()));
- } else if (hwaddr) {
- return (getAll(Host::IDENT_HWADDR,
- &hwaddr->hwaddr_[0],
- hwaddr->hwaddr_.size()));
- }
- return (ConstHostCollection());
- }
- ConstHostCollection
- RadiusHostDataSource::getAll(const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin,
- const size_t identifier_len) const {
- ConstHostCollection result;
- HostPtr host;
- int res;
- VALUE_PAIR *send = NULL, *received;
- if (rc_avpair_add(rh, &send, PW_USER_NAME, identifier_begin, identifier_len, 0) == NULL)
- isc_throw(isc::Exception, "Failed to set username");
- res = rc_auth(rh, 0, send, &received, NULL);
- if (res == OK_RC) {
- VALUE_PAIR *vp = received;
- char name[128];
- char value[128];
- fprintf(stderr, "\"%s\" RADIUS Authentication OK\n", identifier_begin);
- /* print the known attributes in the reply */
- while(vp != NULL) {
- if (rc_avpair_tostr(rh, vp, name, sizeof(name), value, sizeof(value)) == 0) {
- fprintf(stderr, "%s:\t%s\n", name, value);
- }
- vp = vp->next;
- }
- host.reset(new Host(identifier_begin, identifier_len,
- identifier_type, SubnetID(),
- // TODO: set real IP address
- SubnetID(), asiolink::IOAddress("10.42.42.42")));
- result.push_back(host);
- } else {
- fprintf(stderr, "\"%s\" RADIUS Authentication failure (RC=%i)\n", identifier_begin, res);
- }
- return (result);
- }
- ConstHostCollection
- RadiusHostDataSource::getAll4(const asiolink::IOAddress& address) const {
- return (ConstHostCollection());
- }
- ConstHostPtr
- RadiusHostDataSource::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
- const DuidPtr& duid) const {
- if (hwaddr && duid) {
- isc_throw(BadValue, "Radius host data source get4() called with both"
- " hwaddr and duid, only one of them is allowed");
- }
- if (!hwaddr && !duid) {
- isc_throw(BadValue, "Radius host data source get4() called with "
- "neither hwaddr or duid specified, one of them is required");
- }
- // Choosing one of the identifiers
- if (hwaddr) {
- return (get4(subnet_id, Host::IDENT_HWADDR, &hwaddr->hwaddr_[0],
- hwaddr->hwaddr_.size()));
- } else if (duid) {
- return (get4(subnet_id, Host::IDENT_DUID, &duid->getDuid()[0],
- duid->getDuid().size()));
- }
- return (ConstHostPtr());
- }
- ConstHostPtr
- RadiusHostDataSource::get4(const SubnetID& subnet_id,
- const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin,
- const size_t identifier_len) const {
- ConstHostCollection collection = getAll(identifier_type, identifier_begin, identifier_len);
- ConstHostPtr result;
- if (!collection.empty())
- result = *collection.begin();
- return (result);
- }
- ConstHostPtr
- RadiusHostDataSource::get4(const SubnetID& subnet_id,
- const asiolink::IOAddress& address) const {
- // Not relevant for Radius
- isc_throw(NotImplemented, "RadiusHostDataSource::get4 not implemented");
- return (ConstHostPtr());
- }
- ConstHostPtr
- RadiusHostDataSource::get6(const SubnetID& subnet_id, const DuidPtr& duid,
- const HWAddrPtr& hwaddr) const {
- // TODO: libradcli call
- ConstHostPtr result = NULL;
- return (result);
- }
- ConstHostPtr
- RadiusHostDataSource::get6(const SubnetID& subnet_id,
- const Host::IdentifierType& identifier_type,
- const uint8_t* identifier_begin,
- const size_t identifier_len) const {
- // TODO: libradcli call
- ConstHostPtr result = NULL;
- return (result);
- }
- ConstHostPtr
- RadiusHostDataSource::get6(const asiolink::IOAddress& prefix,
- const uint8_t prefix_len) const {
- // TODO: libradcli call
- ConstHostPtr result = NULL;
- return (result);
- }
- ConstHostPtr
- RadiusHostDataSource::get6(const SubnetID& subnet_id,
- const asiolink::IOAddress& address) const {
- // TODO: libradcli call
- ConstHostPtr result = NULL;
- return (result);
- }
- // Miscellaneous database methods.
- std::string RadiusHostDataSource::getName() const {
- std::string name = "";
- return (name);
- }
- std::string RadiusHostDataSource::getDescription() const {
- return (std::string("Host data source that retrieves host information"
- "in radius server"));
- }
- std::pair<uint32_t, uint32_t> RadiusHostDataSource::getVersion() const {
- // TODO: Not relevant for libradcli ?
- return std::make_pair(0,0);
- }
- void
- RadiusHostDataSource::commit() {
- // Not relevant for radius.
- }
- void
- RadiusHostDataSource::rollback() {
- // Not relevant for radius.
- }
- }; // end of isc::dhcp namespace
- }; // end of isc namespace
|