13#include <boost/foreach.hpp> 
   27using namespace std::chrono;
 
   44    if (!
cfg_.getClientKeyTab().empty()) {
 
   45        char* krb5_client_ktname = getenv(
"KRB5_CLIENT_KTNAME");
 
   46        if (krb5_client_ktname) {
 
   51        setenv(
"KRB5_CLIENT_KTNAME", 
cfg_.getClientKeyTab().c_str(), 1);
 
   53    if (!
cfg_.getCredsCache().empty()) {
 
   54        char* krb5ccname = getenv(
"KRB5CCNAME");
 
   60        setenv(
"KRB5CCNAME", 
cfg_.getCredsCache().c_str(), 1);
 
 
   70    cfg_.buildServerRevMap(d2_config);
 
 
   76    for (
auto const& server : 
cfg_.getServerList()) {
 
   83    uint32_t max_tkey_lifetime = 
cfg_.getMaxKeyLifetime();
 
   84    if (max_tkey_lifetime > 0) {
 
   87                            max_tkey_lifetime * 1000,
 
 
   99    for (
auto const& server : 
cfg_.getServerList()) {
 
  103        if (server->getTimer()) {
 
  104            server->getTimer()->cancel();
 
  105            server->getTimer().reset();
 
  108    for (
auto const& key : 
keys_) {
 
  109        key->getTKeyExchange().reset();
 
  117        } 
catch (
const std::exception& ex) {
 
  130    if (!
cfg_.getClientKeyTab().empty()) {
 
  134            unsetenv(
"KRB5_CLIENT_KTNAME");
 
  137    if (!
cfg_.getCredsCache().empty()) {
 
  141            unsetenv(
"KRB5CCNAME");
 
 
  148                       time_point<std::chrono::system_clock> now) {
 
  150    stats_mgr.
addValue(
"gss-tsig-key-created",
 
  151                       static_cast<int64_t
>(1));
 
  154                                              "gss-tsig-key-created"),
 
  155                       static_cast<int64_t
>(1));
 
  167    mkey->setParentID(server->getID());
 
  168    mkey->setInception(now);
 
  169    mkey->setExpire(now + seconds(server->getKeyLifetime()));
 
  170    static_cast<void>(
keys_.insert(mkey));
 
  172    if (!server->getGssReplayFlag()) {
 
  173        flags &= ~GSS_C_REPLAY_FLAG;
 
  175    if (server->getGssSequenceFlag()) {
 
  176        flags |= GSS_C_SEQUENCE_FLAG;
 
  180                                                   server->getExchangeTimeout(),
 
  184            if (mkey->getTKeyExchange()) {
 
  185                mkey->getTKeyExchange()->doExchange();
 
 
  192    for (
auto const& server : 
cfg_.getServerList()) {
 
 
  204    auto const now = system_clock::now();
 
  205    const std::chrono::seconds retry_dur(server->getRetryInterval());
 
  206    const std::chrono::seconds rekey_dur(server->getRekeyInterval());
 
  208    auto const& range = idx.equal_range(server->getID());
 
  210        BOOST_FOREACH(
auto const& key, range) {
 
  211            lock_guard<mutex> lock(*key->mutex_);
 
  212            if (!newest || (newest->getInception() < key->getInception())) {
 
  216                if (now >= key->getExpire()) {
 
  225            switch (newest->getStatus()) {
 
  239            ((now + retry_dur >= newest->getExpire()) ||
 
  240             (now >= newest->getInception() + rekey_dur))) {
 
  248    } 
catch (
const std::exception& ex) {
 
  251            .arg(server->getID())
 
  256            .arg(server->getID());
 
  258    auto timer = server->getTimer();
 
  264    if (retry || !newest) {
 
  266                     server->getRetryInterval() * 1000,
 
  269            .arg(server->getID())
 
  270            .arg(server->getRetryInterval());
 
  274    auto const rekey_date = newest->getInception() + rekey_dur;
 
  275    const std::chrono::system_clock::duration rekey_interval(rekey_date - now);
 
  277        (duration_cast<nanoseconds>(rekey_interval).count() + 999999) / 1000000;
 
  278    if (interval < server->getRetryInterval()) {
 
  279        interval = server->getRetryInterval();
 
  284        .arg(server->getID())
 
  285        .arg(interval / 1000);
 
 
  290    return (
cfg_.getServer(
id));
 
 
  295                     bool& useGssTsig, 
bool& fallback) {
 
  304    fallback = server->getFallback();
 
  305    auto now = system_clock::now();
 
  307    auto const& range = idx.equal_range(server->getID());
 
  309    BOOST_FOREACH(
auto const& key, range) {
 
  310        lock_guard<mutex> lock(*key->mutex_);
 
  312            if (now >= key->getExpire()) {
 
  321            .arg(candidate->getKeyNameStr());
 
 
  331    if (it == 
keys_.cend()) {
 
 
  340    auto now = system_clock::now();
 
  341    std::chrono::seconds max_age(
cfg_.getMaxKeyLifetime() * 3);
 
  342    list<ManagedKeyPtr> to_purge;
 
  343    for (
auto const& key : 
keys_) {
 
  344        lock_guard<mutex> lock(*key->mutex_);
 
  345        if (key->getExpire() + max_age < now) {
 
  346            to_purge.push_back(key);
 
  351    if (to_purge.empty()) {
 
  356    for (
auto const& key : to_purge) {
 
  357        auto it = 
keys_.find(key->getKeyNameStr());
 
  358        if (it != 
keys_.end()) {
 
  359            key->getTKeyExchange().reset();
 
  366        .arg(to_purge.size());
 
 
  386                      << command->str() << 
"' command");
 
  392                      << 
"' command are not a map");
 
  399                      << command->str() << 
"' command");
 
  405                      << command->str() << 
"' command");
 
  408        id = server_id->stringValue();
 
  409        server = 
cfg_.getServer(
id);
 
  410    } 
catch (
const std::exception& ex) {
 
  419    msg << 
"GSS-TSIG server[" << 
id << 
"] ";
 
  430        auto const& range = idx.equal_range(server->getID());
 
  431        BOOST_FOREACH(
auto const& key, range) {
 
  432            keys->add(key->toElement());
 
  434        desc->set(
"keys", keys);
 
 
  447    args->set(
"gss-tsig-servers", servers);
 
  452    for (
auto const& server : 
cfg_.getServerList()) {
 
  455        auto const& range = idx.equal_range(server->getID());
 
  456        BOOST_FOREACH(
auto const& key, range) {
 
  457            keys->add(key->toElement());
 
  459        desc->set(
"keys", keys);
 
  460        key_count += keys->size();
 
  465    msg << servers->size() << 
" GSS-TSIG servers";
 
  467    if (servers->empty()) {
 
  470        msg << 
" and " << key_count << 
" keys";
 
 
  485    args->set(
"gss-tsig-servers", servers);
 
  486    args->set(
"gss-tsig-keys", keys);
 
  489    for (
auto const& server : 
cfg_.getServerList()) {
 
  494    for (
auto const& key : 
keys_) {
 
  499    msg << servers->size() << 
" GSS-TSIG servers and " 
  500        << keys->size() << 
" keys";
 
  502    if (servers->empty() && keys->empty()) {
 
 
  527                      << command->str() << 
"' command");
 
  533                      << 
"' command are not a map");
 
  540                      << command->str() << 
"' command");
 
  546                      << command->str() << 
"' command");
 
  549        name = key_name->stringValue();
 
  551    } 
catch (
const std::exception& ex) {
 
  560    msg << 
"GSS-TSIG key '" << 
name << 
"' ";
 
 
  591                      << command->str() << 
"' command");
 
  597                      << 
"' command are not a map");
 
  604                      << command->str() << 
"' command");
 
  610                      << command->str() << 
"' command");
 
  613        name = key_name->stringValue();
 
  615    } 
catch (
const std::exception& ex) {
 
  624    msg << 
"GSS-TSIG key '" << 
name << 
"' ";
 
  631        bool can_expire = 
true;
 
  633            lock_guard<mutex> lock(*key->mutex_);
 
  641            msg << 
"can't be expired";
 
 
  668                      << command->str() << 
"' command");
 
  674                      << 
"' command are not a map");
 
  681                      << command->str() << 
"' command");
 
  687                      << command->str() << 
"' command");
 
  690        name = key_name->stringValue();
 
  692    } 
catch (
const std::exception& ex) {
 
  701    msg << 
"GSS-TSIG key '" << 
name << 
"' ";
 
  710        if (it != 
keys_.end()) {
 
  711            key->getTKeyExchange().reset();
 
 
  735                      << command->str() << 
"' command");
 
  741                      << 
"' command are not a map");
 
  748                      << command->str() << 
"' command");
 
  754                      << command->str() << 
"' command");
 
  757        id = server_id->stringValue();
 
  758    } 
catch (
const std::exception& ex) {
 
  767    auto now = system_clock::now();
 
  768    list<ManagedKeyPtr> to_purge;
 
  770    auto const& range = idx.equal_range(
id);
 
  771    BOOST_FOREACH(
auto const& key, range) {
 
  772        lock_guard<mutex> lock(*key->mutex_);
 
  773        auto status = key->getStatus();
 
  779            if (now < key->getExpire()) {
 
  784            to_purge.push_back(key);
 
  787            to_purge.push_back(key);
 
  793    for (
auto const& key : to_purge) {
 
  794        auto it = 
keys_.find(key->getKeyNameStr());
 
  795        if (it != 
keys_.end()) {
 
  796            key->getTKeyExchange().reset();
 
  802    msg << to_purge.size() << 
" purged keys for GSS-TSIG server[" << 
id << 
"]";
 
  804    if (to_purge.empty()) {
 
 
  817    auto now = system_clock::now();
 
  818    list<ManagedKeyPtr> to_purge;
 
  819    for (
auto const& key : 
keys_) {
 
  820        lock_guard<mutex> lock(*key->mutex_);
 
  821        auto status = key->getStatus();
 
  827            if (now < key->getExpire()) {
 
  832            to_purge.push_back(key);
 
  835            to_purge.push_back(key);
 
  841    for (
auto const& key : to_purge) {
 
  842        auto it = 
keys_.find(key->getKeyNameStr());
 
  843        if (it != 
keys_.end()) {
 
  844            key->getTKeyExchange().reset();
 
  850    msg << to_purge.size() << 
" purged GSS-TSIG keys";
 
  852    if (to_purge.empty()) {
 
 
  877                      << command->str() << 
"' command");
 
  883                      << 
"' command are not a map");
 
  890                      << command->str() << 
"' command");
 
  896                      << command->str() << 
"' command");
 
  899        id = server_id->stringValue();
 
  900        server = 
cfg_.getServer(
id);
 
  901    } 
catch (
const std::exception& ex) {
 
  910    msg << 
"GSS-TSIG server[" << 
id << 
"] ";
 
  917        auto now = system_clock::now();
 
 
  937    if (command_name != 
"status-get") {
 
  943    if (!response || (response->getType() != 
Element::map)) {
 
  948    if (!resp_args || (resp_args->getType() != 
Element::map)) {
 
  952    ElementPtr mutable_resp_args = boost::const_pointer_cast<Element>(resp_args);
 
 
static ElementPtr create(const Position &pos=ZERO_POSITION())
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
The IOService class is a wrapper for the ASIO io_context class.
The IntervalTimer class is a wrapper for the ASIO boost::asio::deadline_timer class.
static const std::list< std::string > STAT_NAMES
Server TKEY exchange statistics names.
void rekeyAllHandler(isc::hooks::CalloutHandle &handle)
The gss-tsig-rekey-all command handler.
std::unique_ptr< std::string > krb5_client_ktname_prev_
The previous value of client key table environment variable.
isc::asiolink::IOServicePtr io_service_
The hook I/O service.
GssTsigImpl()
Constructor.
void purgeAllHandler(isc::hooks::CalloutHandle &handle)
The gss-tsig-purge-all command handler.
void finishConfigure(isc::d2::D2CfgContextPtr d2_config)
Finish configure.
GssTsigCfg cfg_
GSS-TSIG hook configuration.
void commandProcessed(isc::hooks::CalloutHandle &handle)
The command_processed handler.
void start()
Start method.
void keyExpireHandler(isc::hooks::CalloutHandle &handle)
The gss-tsig-key-expire command handler.
void purgeHandler(isc::hooks::CalloutHandle &handle)
The gss-tsig-purge command handler.
void rekeyHandler(isc::hooks::CalloutHandle &handle)
The gss-tsig-rekey command handler.
void getAllHandler(isc::hooks::CalloutHandle &handle) const
The gss-tsig-get-all command handler.
void configure(isc::data::ConstElementPtr config)
Configure.
void keyDelHandler(isc::hooks::CalloutHandle &handle)
The gss-tsig-key-del command handler.
DnsServerPtr getServer(const std::string &id) const
Get the DNS server from its ID.
void processAllServersKeys(bool rekey=false)
Process GSS-TSIG keys for all servers.
ManagedKeyList keys_
Map of GSS-TSIG keys by name.
ManagedKeyPtr findKey(const d2::DnsServerInfoPtr &server_info, bool &useGssTsig, bool &fallback)
Find a GSS-TSIG key by server info.
void purgeKeys()
Purge very old GSS-TSIG keys.
void processServerKeys(DnsServerPtr server, bool rekey=false)
Process GSS-TSIG keys for a specific server.
std::unique_ptr< std::string > krb5ccname_prev_
The previous value of credential cache environment variable.
void keyGetHandler(isc::hooks::CalloutHandle &handle) const
The gss-tsig-key-get command handler.
isc::asiolink::IntervalTimerPtr purge_timer_
The purge periodic timer.
virtual ~GssTsigImpl()
Destructor.
void listHandler(isc::hooks::CalloutHandle &handle) const
The gss-tsig-list command handler.
void getHandler(isc::hooks::CalloutHandle &handle) const
The gss-tsig-get command handler.
void createKey(DnsServerPtr server, std::chrono::time_point< std::chrono::system_clock > now)
Create new GSS-TSIG key.
static std::string genName(const std::string &server)
Create a random name from a suffix.
@ EXPIRED
Expired (no longer usable).
@ NOT_READY
Not yet ready (not yet usable).
The TKeyExchange class handles communication with the DNS server.
static const OM_uint32 TKEY_EXCHANGE_FLAGS
The default TKEY exchange flags.
Per-packet callout handle.
void getArgument(const std::string &name, T &value) const
Get argument.
void setArgument(const std::string &name, T value)
Set argument.
Statistics Manager class.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
bool del(const std::string &name)
Removes specified statistic.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
int rekey(CalloutHandle &handle)
The gss-tsig-rekey command.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
std::string parseCommand(ConstElementPtr &arg, ConstElementPtr command)
Parses the given command into a string containing the actual command and an ElementPtr containing the...
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< DnsServerInfo > DnsServerInfoPtr
Defines a pointer for DnsServerInfo instances.
boost::shared_ptr< D2CfgContext > D2CfgContextPtr
Pointer to a configuration context.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Element > ElementPtr
const isc::log::MessageID GSS_TSIG_MANAGER_STOP_GENERAL_ERROR
const isc::log::MessageID START_REKEY_TIMER
const isc::log::MessageID KEY_LOOKUP_DISABLED
const isc::log::MessageID GSS_TSIG_NEW_KEY
boost::shared_ptr< DnsServer > DnsServerPtr
A pointer to a DNS server.
const isc::log::MessageID GSS_TSIG_MANAGER_STOP_ERROR
const isc::log::MessageID GSS_TSIG_OLD_KEY_REMOVED
const isc::log::MessageID KEY_LOOKUP_NONE
const isc::log::MessageID KEY_LOOKUP_FOUND
const isc::log::MessageID GSS_TSIG_MANAGER_STARTED
const isc::log::MessageID KEY_PROCESSING_FAILED_UNSPECIFIED_ERROR
const isc::log::MessageID START_RETRY_TIMER
boost::shared_ptr< ManagedKey > ManagedKeyPtr
Type of pointer to a Managed GSS-TSIG key.
const isc::log::MessageID KEY_PROCESSING_FAILED
isc::log::Logger gss_tsig_logger("gss-tsig-hooks")
const isc::log::MessageID GSS_TSIG_MANAGER_STOPPED
const int DBGLVL_TRACE_BASIC
Trace basic operations.
Defines the logger used by the top-level component of kea-lfc.
Tag for the server ID index for searching GSS-TSIG key.