File: secpoll-recursor.cc

package info (click to toggle)
pdns-recursor 5.3.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 11,116 kB
  • sloc: cpp: 109,672; javascript: 20,651; python: 5,657; sh: 5,114; makefile: 782; ansic: 582; xml: 37
file content (104 lines) | stat: -rw-r--r-- 3,750 bytes parent folder | download | duplicates (2)
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
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "secpoll-recursor.hh"
#include "syncres.hh"
#include "logger.hh"
#include "arguments.hh"
#include "version.hh"
#include "validate-recursor.hh"
#include "secpoll.hh"

#include <cstdint>
#ifndef PACKAGEVERSION
#define PACKAGEVERSION getPDNSVersion()
#endif

pdns::stat_t g_security_status;

void doSecPoll(time_t* last_secpoll, Logr::log_t log)
{
  if (::arg()["security-poll-suffix"].empty()) {
    return;
  }

  string pkgv(PACKAGEVERSION);
  struct timeval now{};
  Utility::gettimeofday(&now);

  /* update last_secpoll right now, even if it fails
     we don't want to retry right away and hammer the server */
  *last_secpoll = now.tv_sec;

  SyncRes resolver(now);
  if (g_dnssecmode != DNSSECMode::Off) {
    resolver.setDoDNSSEC(true);
    resolver.setDNSSECValidationRequested(true);
  }
  resolver.setId("SecPoll");

  vector<DNSRecord> ret;

  string version = "recursor-" + pkgv;
  string qstring(version.substr(0, 63) + ".security-status." + ::arg()["security-poll-suffix"]);

  if (*qstring.rbegin() != '.') {
    qstring += '.';
  }

  std::replace(qstring.begin(), qstring.end(), '+', '_');
  std::replace(qstring.begin(), qstring.end(), '~', '_');

  vState state = vState::Indeterminate;
  DNSName query(qstring);
  int res = resolver.beginResolve(query, QType(QType::TXT), 1, ret);

  if (g_dnssecmode != DNSSECMode::Off && res != 0) {
    state = resolver.getValidationState();
  }

  auto vlog = log->withValues("version", Logging::Loggable(pkgv), "query", Logging::Loggable(query));
  if (vStateIsBogus(state)) {
    SLOG(g_log << Logger::Error << "Failed to retrieve security status update for '" + pkgv + "' on '" << query << "', DNSSEC validation result was Bogus!" << endl,
         vlog->info(Logr::Error, "Failed to retrieve security status update", "validationResult", Logging::Loggable(vStateToString(state))));
    if (g_security_status == 1) { // If we were OK, go to unknown
      g_security_status = 0;
    }
    return;
  }

  if (res == RCode::NXDomain && !isReleaseVersion(pkgv)) {
    SLOG(g_log << Logger::Warning << "Not validating response for security status update, this is a non-release version" << endl,
         vlog->info(Logr::Warning, "Not validating response for security status update, this is a non-release version"));
    return;
  }

  string security_message;
  int security_status = static_cast<int>(g_security_status);

  try {
    processSecPoll(res, ret, security_status, security_message);
  }
  catch (const PDNSException& pe) {
    g_security_status = security_status;
    SLOG(g_log << Logger::Warning << "Failed to retrieve security status update for '" << pkgv << "' on '" << query << "': " << pe.reason << endl,
         vlog->error(Logr::Warning, pe.reason, "Failed to retrieve security status update"));
    return;
  }

  auto rlog = vlog->withValues("securitymessage", Logging::Loggable(security_message), "status", Logging::Loggable(security_status));
  if (g_security_status != 1 && security_status == 1) {
    SLOG(g_log << Logger::Warning << "Polled security status of version " << pkgv << ", no known issues reported: " << security_message << endl,
         rlog->info(Logr::Notice, "Polled security status of version, no known issues reported"));
  }
  if (security_status == 2) {
    SLOG(g_log << Logger::Error << "PowerDNS Security Update Recommended: " << security_message << endl,
         rlog->info(Logr::Error, "PowerDNS Security Update Recommended"));
  }
  if (security_status == 3) {
    SLOG(g_log << Logger::Error << "PowerDNS Security Update Mandatory: " << security_message << endl,
         rlog->info(Logr::Error, "PowerDNS Security Update Mandatory"));
  }

  g_security_status = security_status;
}