Coverage Report

Created: 2026-04-06 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pdns/pdns/dnsdistdist/credentials.hh
Line
Count
Source
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#pragma once
23
24
#include <cstdint>
25
#include <string>
26
27
class SensitiveData
28
{
29
public:
30
  SensitiveData(const SensitiveData&) = delete;
31
  SensitiveData(SensitiveData&&) = delete;
32
  SensitiveData& operator=(const SensitiveData&) = delete;
33
  SensitiveData(size_t bytes);
34
  SensitiveData(std::string&& data);
35
  SensitiveData& operator=(SensitiveData&&) noexcept;
36
37
  ~SensitiveData();
38
  void clear();
39
  [[nodiscard]] const std::string& getString() const
40
0
  {
41
0
    return d_data;
42
0
  }
43
  std::string& getString()
44
0
  {
45
0
    return d_data;
46
0
  }
47
48
private:
49
  std::string d_data;
50
};
51
52
std::string hashPassword(const std::string& password);
53
std::string hashPassword(const std::string& password, uint64_t workFactor, uint64_t parallelFactor, uint64_t blockSize);
54
bool verifyPassword(const std::string& hash, const std::string& password);
55
bool verifyPassword(const std::string& binaryHash, const std::string& salt, uint64_t workFactor, uint64_t parallelFactor, uint64_t blockSize, const std::string& binaryPassword);
56
bool isPasswordHashed(const std::string& password);
57
58
class CredentialsHolder
59
{
60
public:
61
  CredentialsHolder(CredentialsHolder&&) = delete;
62
  CredentialsHolder& operator=(CredentialsHolder&&) = delete;
63
  /* if hashPlaintext is true, the password is in cleartext and hashing is available,
64
     the hashed form will be kept in memory.
65
     Note that accepting hashed password from an untrusted source might open
66
     us to a denial of service, since we currently don't cap the parameters,
67
     including the work factor */
68
  CredentialsHolder(std::string&& password, bool hashPlaintext);
69
  ~CredentialsHolder();
70
71
  CredentialsHolder(const CredentialsHolder&) = delete;
72
  CredentialsHolder& operator=(const CredentialsHolder&) = delete;
73
74
  [[nodiscard]] bool matches(const std::string& password) const;
75
  /* whether it was constructed from a hashed and salted string */
76
  [[nodiscard]] bool wasHashed() const
77
0
  {
78
0
    return d_wasHashed;
79
0
  }
80
  /* whether it is hashed in memory */
81
  [[nodiscard]] bool isHashed() const
82
0
  {
83
0
    return d_isHashed;
84
0
  }
85
86
  static bool isHashingAvailable();
87
  static SensitiveData readFromTerminal();
88
89
  static uint64_t constexpr s_defaultWorkFactor{1024U}; /* N */
90
  static uint64_t constexpr s_defaultParallelFactor{1U}; /* p */
91
  static uint64_t constexpr s_defaultBlockSize{8U}; /* r */
92
93
private:
94
  SensitiveData d_credentials;
95
  /* if the password is hashed, we only extract
96
     the salt and parameters once */
97
  std::string d_salt;
98
  uint64_t d_workFactor{0};
99
  uint64_t d_parallelFactor{0};
100
  uint64_t d_blockSize{0};
101
  /* seed our hash so it's not predictable */
102
  uint32_t d_fallbackHashPerturb{0};
103
  uint32_t d_fallbackHash{0};
104
  /* whether it was constructed from a hashed and salted string */
105
  bool d_wasHashed{false};
106
  /* whether it is hashed in memory */
107
  bool d_isHashed{false};
108
};