• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 9498012098

13 Jun 2024 10:27AM UTC coverage: 61.22% (-3.4%) from 64.615%
9498012098

Pull #14325

github

web-flow
Merge e3409d021 into 57ab0fbc9
Pull Request #14325: Set nsec3param: first increase the serial and then rectify

34064 of 88172 branches covered (38.63%)

Branch coverage included in aggregate %.

5 of 7 new or added lines in 1 file covered. (71.43%)

5415 existing lines in 81 files now uncovered.

118803 of 161528 relevant lines covered (73.55%)

4993315.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.16
/pdns/webserver.hh
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
#include <map>
24
#include <string>
25
#include <list>
26
#include <boost/utility.hpp>
27
#pragma GCC diagnostic push
28
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
29
#include <yahttp/yahttp.hpp>
30
#pragma GCC diagnostic pop
31

32
#include "json11.hpp"
33

34
#include "credentials.hh"
35
#include "namespaces.hh"
36
#include "sstuff.hh"
37
#include "logging.hh"
38

39
class HttpRequest : public YaHTTP::Request {
40
public:
41
  HttpRequest(const string& logprefix_="") : YaHTTP::Request(), logprefix(logprefix_) { };
1,514✔
42

43
  string logprefix;
44
  bool accept_yaml{false};
45
  bool accept_json{false};
46
  bool accept_html{false};
47
  bool complete{false};
48

49
  json11::Json json();
50

51
  // checks password _only_.
52
  bool compareAuthorization(const CredentialsHolder& expectedCredentials) const;
53
  bool compareHeader(const string &header_name, const CredentialsHolder& expectedCredentials) const;
54
  bool compareHeader(const string &header_name, const string &expected_value) const;
55

56
#ifdef RECURSOR
57
  void setSLog(Logr::log_t log)
58
  {
48✔
59
    d_slog = log;
48✔
60
  }
48✔
61
  std::shared_ptr<Logr::Logger> d_slog;
62
#endif
63
};
64

65
class HttpResponse: public YaHTTP::Response {
66
public:
67
  HttpResponse() : YaHTTP::Response() { };
1,577✔
68
  HttpResponse(const YaHTTP::Response &resp) : YaHTTP::Response(resp) { };
×
69

70
  void setPlainBody(const string& document);
71
  void setYamlBody(const string& document);
72
  void setJsonBody(const string& document);
73
  void setJsonBody(const json11::Json& document);
74
  void setErrorResult(const std::string& message, const int status);
75
  void setSuccessResult(const std::string& message, const int status = 200);
76

77
#ifdef RECURSOR
78
  void setSLog(Logr::log_t log)
79
  {
51✔
80
    d_slog = log;
51✔
81
  }
51✔
82
  std::shared_ptr<Logr::Logger> d_slog;
83
#endif
84
};
85

86

87
class HttpException
88
{
89
public:
90
  HttpException(int status) : d_response()
91
  {
43✔
92
    d_response.status = status;
43✔
93
  };
43✔
94

95
  HttpException(int status, const string& msg) : d_response()
96
  {
20✔
97
    d_response.setErrorResult(msg, status);
20✔
98
  };
20✔
99

100
  HttpResponse response()
101
  {
63✔
102
    return d_response;
63✔
103
  }
63✔
104

105
protected:
106
  HttpResponse d_response;
107
};
108

109
class HttpBadRequestException : public HttpException {
110
public:
UNCOV
111
  HttpBadRequestException() : HttpException(400) { };
×
112
  HttpBadRequestException(const string& msg) : HttpException(400, msg) { };
4✔
113
};
114

115
class HttpUnauthorizedException : public HttpException {
116
public:
117
  HttpUnauthorizedException(string const &scheme) : HttpException(401)
118
  {
15✔
119
    d_response.headers["WWW-Authenticate"] = scheme + " realm=\"PowerDNS\"";
15✔
120
  }
15✔
121
};
122

123
class HttpForbiddenException : public HttpException {
124
public:
125
  HttpForbiddenException() : HttpException(403) { };
×
126
  HttpForbiddenException(const string& msg) : HttpException(403, msg) { };
×
127
};
128

129
class HttpNotFoundException : public HttpException {
130
public:
131
  HttpNotFoundException() : HttpException(404) { };
24✔
132
  HttpNotFoundException(const string& msg) : HttpException(404, msg) { };
12✔
133
};
134

135
class HttpMethodNotAllowedException : public HttpException {
136
public:
137
  HttpMethodNotAllowedException() : HttpException(405) { };
×
138
  HttpMethodNotAllowedException(const string& msg) : HttpException(405, msg) { };
×
139
};
140

141
class HttpConflictException : public HttpException {
142
public:
143
  HttpConflictException() : HttpException(409) { };
4✔
144
  HttpConflictException(const string& msg) : HttpException(409, msg) { };
4✔
145
};
146

147
class HttpInternalServerErrorException : public HttpException {
148
public:
149
  HttpInternalServerErrorException() : HttpException(500) { };
×
150
  HttpInternalServerErrorException(const string& msg) : HttpException(500, msg) { };
×
151
};
152

153
class ApiException : public runtime_error
154
{
155
public:
156
  ApiException(const string& what_arg) : runtime_error(what_arg) {
247✔
157
  }
247✔
158
};
159

160
class Server
161
{
162
public:
163
  Server(const string &localaddress, int port) : d_local(localaddress.empty() ? "0.0.0.0" : localaddress, port), d_server_socket(d_local.sin4.sin_family, SOCK_STREAM, 0) {
15✔
164
    d_server_socket.setReuseAddr();
15✔
165
    d_server_socket.bind(d_local);
15✔
166
    d_server_socket.listen();
15✔
167
  }
15✔
168
  virtual ~Server() = default;
×
169

170
  ComboAddress d_local;
171

172
  std::shared_ptr<Socket> accept() {
1,528✔
173
    return std::shared_ptr<Socket>(d_server_socket.accept());
1,528✔
174
  }
1,528✔
175

176
protected:
177
  Socket d_server_socket;
178
};
179

180
class WebServer : public boost::noncopyable
181
{
182
public:
183
  WebServer(string listenaddress, int port);
184
  virtual ~WebServer() = default;
×
185

186
#ifdef RECURSOR
187
  void setSLog(Logr::log_t log)
188
  {
1✔
189
    d_slog = log;
1✔
190
  }
1✔
191
#endif
192

193
  void setApiKey(const string &apikey, bool hashPlaintext) {
13✔
194
    if (!apikey.empty()) {
13!
195
      d_apikey = make_unique<CredentialsHolder>(std::string(apikey), hashPlaintext);
13✔
196
    }
13✔
197
    else {
×
198
      d_apikey.reset();
×
199
    }
×
200
  }
13✔
201

202
  void setPassword(const string &password, bool hashPlaintext) {
13✔
203
    if (!password.empty()) {
13✔
204
      d_webserverPassword = make_unique<CredentialsHolder>(std::string(password), hashPlaintext);
5✔
205
    }
5✔
206
    else {
8✔
207
      d_webserverPassword.reset();
8✔
208
    }
8✔
209
  }
13✔
210

211
  void setMaxBodySize(ssize_t s) { // in megabytes
12✔
212
    d_maxbodysize = s * 1024 * 1024;
12✔
213
  }
12✔
214

215
  void setConnectionTimeout(int t) { // in seconds
12✔
216
    d_connectiontimeout = t;
12✔
217
  }
12✔
218

219
  void setACL(const NetmaskGroup &nmg) {
15✔
220
    d_acl = nmg;
15✔
221
  }
15✔
222

223
  static bool validURL(const YaHTTP::URL& url);
224

225
  void bind();
226
  void go();
227

228
  void serveConnection(const std::shared_ptr<Socket>& client) const;
229
  void handleRequest(HttpRequest& request, HttpResponse& resp) const;
230

231
  typedef std::function<void(HttpRequest* req, HttpResponse* resp)> HandlerFunction;
232
  void registerApiHandler(const string& url, const HandlerFunction& handler, const std::string& method = "", bool allowPassword=false);
233
  void registerWebHandler(const string& url, const HandlerFunction& handler, const std::string& method = "");
234

235
  enum class LogLevel : uint8_t {
236
    None = 0,                // No logs from requests at all
237
    Normal = 10,             // A "common log format"-like line e.g. '127.0.0.1 "GET /apache_pb.gif HTTP/1.0" 200 2326'
238
    Detailed = 20,           // The full request headers and body, and the full response headers and body
239
  };
240

241
  void setLogLevel(const string& level) {
15✔
242
    if (level == "none") {
15!
243
      d_loglevel = LogLevel::None;
×
244
      return;
×
245
    }
×
246

247
    if (level == "normal") {
15!
248
      d_loglevel = LogLevel::Normal;
15✔
249
      return;
15✔
250
    }
15✔
251

252
    if (level == "detailed") {
×
253
      d_loglevel = LogLevel::Detailed;
×
254
      return;
×
255
    }
×
256

257
    throw PDNSException("Unknown webserver log level: " + level);
×
258
  }
×
259

260
  void setLogLevel(const LogLevel level) {
×
261
    d_loglevel = level;
×
262
  };
×
263

264
  LogLevel getLogLevel() {
×
265
    return d_loglevel;
×
266
  };
×
267

268
#ifdef RECURSOR
269
  std::shared_ptr<Logr::Logger> d_slog;
270
#endif
271

272
protected:
273
  static void registerBareHandler(const string& url, const HandlerFunction& handler, const std::string& method);
274
  void logRequest(const HttpRequest& req, const ComboAddress& remote) const;
275
  void logResponse(const HttpResponse& resp, const ComboAddress& remote, const string& logprefix) const;
276

277
  virtual std::shared_ptr<Server> createServer() {
14✔
278
    return std::make_shared<Server>(d_listenaddress, d_port);
14✔
279
  }
14✔
280

281
  void apiWrapper(const WebServer::HandlerFunction& handler, HttpRequest* req, HttpResponse* resp, bool allowPassword);
282
  void webWrapper(const WebServer::HandlerFunction& handler, HttpRequest* req, HttpResponse* resp);
283

284
  string d_listenaddress;
285
  int d_port;
286
  std::shared_ptr<Server> d_server;
287

288
  std::unique_ptr<CredentialsHolder> d_apikey{nullptr};
289
  std::unique_ptr<CredentialsHolder> d_webserverPassword{nullptr};
290

291
  ssize_t d_maxbodysize; // in bytes
292
  int d_connectiontimeout; // in seconds
293

294
  NetmaskGroup d_acl;
295

296
  const string d_logprefix = "[webserver] ";
297

298
  // Describes the amount of logging the webserver does
299
  WebServer::LogLevel d_loglevel{WebServer::LogLevel::Detailed};
300
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc