comparison Core/WebServiceParameters.cpp @ 2800:dc7330089736

"OrthancPeers" configuration option now allows to specify HTTP headers
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 23 Aug 2018 13:11:48 +0200
parents d67298eec14e
children 807169f85ba9
comparison
equal deleted inserted replaced
2799:6e3a60b85da6 2800:dc7330089736
35 #include "WebServiceParameters.h" 35 #include "WebServiceParameters.h"
36 36
37 #include "Logging.h" 37 #include "Logging.h"
38 #include "OrthancException.h" 38 #include "OrthancException.h"
39 #include "SerializationToolbox.h" 39 #include "SerializationToolbox.h"
40 #include "Toolbox.h"
40 41
41 #if ORTHANC_SANDBOXED == 0 42 #if ORTHANC_SANDBOXED == 0
42 # include "../Core/SystemToolbox.h" 43 # include "SystemToolbox.h"
43 #endif 44 #endif
44 45
45 #include <cassert> 46 #include <cassert>
46 47
47 namespace Orthanc 48 namespace Orthanc
48 { 49 {
50 static const char* KEY_CERTIFICATE_FILE = "CertificateFile";
51 static const char* KEY_CERTIFICATE_KEY_FILE = "CertificateKeyFile";
52 static const char* KEY_CERTIFICATE_KEY_PASSWORD = "CertificateKeyPassword";
53 static const char* KEY_HTTP_HEADERS = "HttpHeaders";
54 static const char* KEY_PASSWORD = "Password";
55 static const char* KEY_PKCS11 = "Pkcs11";
56 static const char* KEY_URL = "Url";
57 static const char* KEY_URL_2 = "URL";
58 static const char* KEY_USERNAME = "Username";
59
60
49 WebServiceParameters::WebServiceParameters() : 61 WebServiceParameters::WebServiceParameters() :
50 advancedFormat_(false),
51 url_("http://127.0.0.1:8042/"),
52 pkcs11Enabled_(false) 62 pkcs11Enabled_(false)
53 { 63 {
64 SetUrl("http://127.0.0.1:8042/");
54 } 65 }
55 66
56 67
57 void WebServiceParameters::ClearClientCertificate() 68 void WebServiceParameters::ClearClientCertificate()
58 { 69 {
60 certificateKeyFile_.clear(); 71 certificateKeyFile_.clear();
61 certificateKeyPassword_.clear(); 72 certificateKeyPassword_.clear();
62 } 73 }
63 74
64 75
65 #if ORTHANC_SANDBOXED == 0 76 void WebServiceParameters::SetUrl(const std::string& url)
77 {
78 if (!Toolbox::StartsWith(url, "http://") &&
79 !Toolbox::StartsWith(url, "https://"))
80 {
81 LOG(ERROR) << "Bad URL: " << url;
82 throw OrthancException(ErrorCode_BadFileFormat);
83 }
84
85 // Add trailing slash if needed
86 if (url[url.size() - 1] == '/')
87 {
88 url_ = url;
89 }
90 else
91 {
92 url_ = url + '/';
93 }
94 }
95
96
97 void WebServiceParameters::ClearCredentials()
98 {
99 username_.clear();
100 password_.clear();
101 }
102
103
104 void WebServiceParameters::SetCredentials(const std::string& username,
105 const std::string& password)
106 {
107 if (username.empty() &&
108 !password.empty())
109 {
110 throw OrthancException(ErrorCode_BadFileFormat);
111 }
112 else
113 {
114 username_ = username;
115 password_ = password;
116 }
117 }
118
119
66 void WebServiceParameters::SetClientCertificate(const std::string& certificateFile, 120 void WebServiceParameters::SetClientCertificate(const std::string& certificateFile,
67 const std::string& certificateKeyFile, 121 const std::string& certificateKeyFile,
68 const std::string& certificateKeyPassword) 122 const std::string& certificateKeyPassword)
69 { 123 {
70 if (certificateFile.empty()) 124 if (certificateFile.empty())
71 { 125 {
72 throw OrthancException(ErrorCode_ParameterOutOfRange); 126 throw OrthancException(ErrorCode_ParameterOutOfRange);
73 } 127 }
74 128
75 if (!SystemToolbox::IsRegularFile(certificateFile)) 129 if (certificateKeyPassword.empty())
76 { 130 {
77 LOG(ERROR) << "Cannot open certificate file: " << certificateFile; 131 LOG(ERROR) << "The password for the HTTPS certificate is not provided: " << certificateFile;
78 throw OrthancException(ErrorCode_InexistentFile); 132 throw OrthancException(ErrorCode_BadFileFormat);
79 } 133 }
80 134
81 if (!certificateKeyFile.empty() &&
82 !SystemToolbox::IsRegularFile(certificateKeyFile))
83 {
84 LOG(ERROR) << "Cannot open key file: " << certificateKeyFile;
85 throw OrthancException(ErrorCode_InexistentFile);
86 }
87
88 advancedFormat_ = true;
89 certificateFile_ = certificateFile; 135 certificateFile_ = certificateFile;
90 certificateKeyFile_ = certificateKeyFile; 136 certificateKeyFile_ = certificateKeyFile;
91 certificateKeyPassword_ = certificateKeyPassword; 137 certificateKeyPassword_ = certificateKeyPassword;
92 } 138 }
93 #endif 139
94 140
95 141 void WebServiceParameters::FromSimpleFormat(const Json::Value& peer)
96 static void AddTrailingSlash(std::string& url)
97 {
98 if (url.size() != 0 &&
99 url[url.size() - 1] != '/')
100 {
101 url += '/';
102 }
103 }
104
105
106 void WebServiceParameters::FromJsonArray(const Json::Value& peer)
107 { 142 {
108 assert(peer.isArray()); 143 assert(peer.isArray());
109 144
110 advancedFormat_ = false;
111 pkcs11Enabled_ = false; 145 pkcs11Enabled_ = false;
146 ClearClientCertificate();
112 147
113 if (peer.size() != 1 && 148 if (peer.size() != 1 &&
114 peer.size() != 3) 149 peer.size() != 3)
115 { 150 {
116 throw OrthancException(ErrorCode_BadFileFormat); 151 throw OrthancException(ErrorCode_BadFileFormat);
117 } 152 }
118 153
119 std::string url = peer.get(0u, "").asString(); 154 SetUrl(peer.get(0u, "").asString());
120 if (url.empty())
121 {
122 throw OrthancException(ErrorCode_BadFileFormat);
123 }
124
125 AddTrailingSlash(url);
126 SetUrl(url);
127 155
128 if (peer.size() == 1) 156 if (peer.size() == 1)
129 { 157 {
130 SetUsername(""); 158 ClearCredentials();
131 SetPassword("");
132 } 159 }
133 else if (peer.size() == 2) 160 else if (peer.size() == 2)
134 { 161 {
135 LOG(ERROR) << "The HTTP password is not provided"; 162 LOG(ERROR) << "The HTTP password is not provided";
136 throw OrthancException(ErrorCode_BadFileFormat); 163 throw OrthancException(ErrorCode_BadFileFormat);
137 } 164 }
138 else if (peer.size() == 3) 165 else if (peer.size() == 3)
139 { 166 {
140 SetUsername(peer.get(1u, "").asString()); 167 SetCredentials(peer.get(1u, "").asString(),
141 SetPassword(peer.get(2u, "").asString()); 168 peer.get(2u, "").asString());
142 } 169 }
143 else 170 else
144 { 171 {
145 throw OrthancException(ErrorCode_BadFileFormat); 172 throw OrthancException(ErrorCode_BadFileFormat);
146 } 173 }
164 return peer[key].asString(); 191 return peer[key].asString();
165 } 192 }
166 } 193 }
167 194
168 195
169 void WebServiceParameters::FromJsonObject(const Json::Value& peer) 196 void WebServiceParameters::FromAdvancedFormat(const Json::Value& peer)
170 { 197 {
171 assert(peer.isObject()); 198 assert(peer.isObject());
172 advancedFormat_ = true; 199
173 200 std::string url = GetStringMember(peer, KEY_URL, "");
174 std::string url = GetStringMember(peer, "Url", "");
175 if (url.empty()) 201 if (url.empty())
176 { 202 {
177 throw OrthancException(ErrorCode_BadFileFormat); 203 SetUrl(GetStringMember(peer, KEY_URL_2, ""));
178 } 204 }
179 205 else
180 AddTrailingSlash(url); 206 {
181 SetUrl(url); 207 SetUrl(url);
182 208 }
183 SetUsername(GetStringMember(peer, "Username", "")); 209
184 SetPassword(GetStringMember(peer, "Password", "")); 210 SetCredentials(GetStringMember(peer, KEY_USERNAME, ""),
185 211 GetStringMember(peer, KEY_PASSWORD, ""));
186 if (!username_.empty() && 212
187 !peer.isMember("Password")) 213 std::string file = GetStringMember(peer, KEY_CERTIFICATE_FILE, "");
188 { 214 if (!file.empty())
189 LOG(ERROR) << "The HTTP password is not provided"; 215 {
190 throw OrthancException(ErrorCode_BadFileFormat); 216 SetClientCertificate(file, GetStringMember(peer, KEY_CERTIFICATE_KEY_FILE, ""),
191 } 217 GetStringMember(peer, KEY_CERTIFICATE_KEY_PASSWORD, ""));
192 218 }
193 #if ORTHANC_SANDBOXED == 0 219 else
194 if (peer.isMember("CertificateFile")) 220 {
195 { 221 ClearClientCertificate();
196 SetClientCertificate(GetStringMember(peer, "CertificateFile", ""), 222 }
197 GetStringMember(peer, "CertificateKeyFile", ""), 223
198 GetStringMember(peer, "CertificateKeyPassword", "")); 224 if (peer.isMember(KEY_PKCS11))
199 225 {
200 if (!peer.isMember("CertificateKeyPassword")) 226 if (peer[KEY_PKCS11].type() == Json::booleanValue)
201 { 227 {
202 LOG(ERROR) << "The password for the HTTPS certificate is not provided"; 228 pkcs11Enabled_ = peer[KEY_PKCS11].asBool();
203 throw OrthancException(ErrorCode_BadFileFormat);
204 }
205 }
206 #endif
207
208 if (peer.isMember("Pkcs11"))
209 {
210 if (peer["Pkcs11"].type() == Json::booleanValue)
211 {
212 pkcs11Enabled_ = peer["Pkcs11"].asBool();
213 } 229 }
214 else 230 else
215 { 231 {
216 throw OrthancException(ErrorCode_BadFileFormat); 232 throw OrthancException(ErrorCode_BadFileFormat);
217 } 233 }
218 } 234 }
219 } 235 else
220 236 {
221 237 pkcs11Enabled_ = false;
222 void WebServiceParameters::FromJson(const Json::Value& peer) 238 }
239
240 headers_.clear();
241
242 if (peer.isMember(KEY_HTTP_HEADERS))
243 {
244 const Json::Value& h = peer[KEY_HTTP_HEADERS];
245 if (h.type() != Json::objectValue)
246 {
247 throw OrthancException(ErrorCode_BadFileFormat);
248 }
249 else
250 {
251 Json::Value::Members keys = h.getMemberNames();
252 for (size_t i = 0; i < keys.size(); i++)
253 {
254 const Json::Value& value = h[keys[i]];
255 if (value.type() != Json::stringValue)
256 {
257 throw OrthancException(ErrorCode_BadFileFormat);
258 }
259 else
260 {
261 headers_[keys[i]] = value.asString();
262 }
263 }
264 }
265 }
266 }
267
268
269 void WebServiceParameters::Unserialize(const Json::Value& peer)
223 { 270 {
224 try 271 try
225 { 272 {
226 if (peer.isArray()) 273 if (peer.isArray())
227 { 274 {
228 FromJsonArray(peer); 275 FromSimpleFormat(peer);
229 } 276 }
230 else if (peer.isObject()) 277 else if (peer.isObject())
231 { 278 {
232 FromJsonObject(peer); 279 FromAdvancedFormat(peer);
233 } 280 }
234 else 281 else
235 { 282 {
236 throw OrthancException(ErrorCode_BadFileFormat); 283 throw OrthancException(ErrorCode_BadFileFormat);
237 } 284 }
245 throw OrthancException(ErrorCode_BadFileFormat); 292 throw OrthancException(ErrorCode_BadFileFormat);
246 } 293 }
247 } 294 }
248 295
249 296
250 void WebServiceParameters::ToJson(Json::Value& value, 297 void WebServiceParameters::ListHttpHeaders(std::set<std::string>& target) const
251 bool includePasswords) const 298 {
252 { 299 target.clear();
253 if (advancedFormat_) 300
301 for (HttpHeaders::const_iterator it = headers_.begin();
302 it != headers_.end(); ++it)
303 {
304 target.insert(it->first);
305 }
306 }
307
308
309 bool WebServiceParameters::LookupHttpHeader(std::string& value,
310 const std::string& key) const
311 {
312 HttpHeaders::const_iterator found = headers_.find(key);
313
314 if (found == headers_.end())
315 {
316 return false;
317 }
318 else
319 {
320 value = found->second;
321 return true;
322 }
323 }
324
325
326 bool WebServiceParameters::IsAdvancedFormatNeeded() const
327 {
328 return (!certificateFile_.empty() ||
329 !certificateKeyFile_.empty() ||
330 !certificateKeyPassword_.empty() ||
331 pkcs11Enabled_ ||
332 !headers_.empty());
333 }
334
335
336 void WebServiceParameters::Serialize(Json::Value& value,
337 bool forceAdvancedFormat,
338 bool includePasswords) const
339 {
340 if (forceAdvancedFormat ||
341 IsAdvancedFormatNeeded())
254 { 342 {
255 value = Json::objectValue; 343 value = Json::objectValue;
256 value["Url"] = url_; 344 value[KEY_URL] = url_;
257 345
258 if (!username_.empty() || 346 if (!username_.empty() ||
259 !password_.empty()) 347 !password_.empty())
260 { 348 {
261 value["Username"] = username_; 349 value[KEY_USERNAME] = username_;
262 350
263 if (includePasswords) 351 if (includePasswords)
264 { 352 {
265 value["Password"] = password_; 353 value[KEY_PASSWORD] = password_;
266 } 354 }
267 } 355 }
268 356
269 if (!certificateFile_.empty()) 357 if (!certificateFile_.empty())
270 { 358 {
271 value["CertificateFile"] = certificateFile_; 359 value[KEY_CERTIFICATE_FILE] = certificateFile_;
272 } 360 }
273 361
274 if (!certificateKeyFile_.empty()) 362 if (!certificateKeyFile_.empty())
275 { 363 {
276 value["CertificateKeyFile"] = certificateKeyFile_; 364 value[KEY_CERTIFICATE_KEY_FILE] = certificateKeyFile_;
277 } 365 }
278 366
279 if (!certificateKeyPassword_.empty() && 367 if (!certificateKeyPassword_.empty() &&
280 includePasswords) 368 includePasswords)
281 { 369 {
282 value["CertificateKeyPassword"] = certificateKeyPassword_; 370 value[KEY_CERTIFICATE_KEY_PASSWORD] = certificateKeyPassword_;
371 }
372
373 value[KEY_PKCS11] = pkcs11Enabled_;
374
375 value[KEY_HTTP_HEADERS] = Json::objectValue;
376 for (HttpHeaders::const_iterator it = headers_.begin();
377 it != headers_.end(); ++it)
378 {
379 value[KEY_HTTP_HEADERS][it->first] = it->second;
283 } 380 }
284 } 381 }
285 else 382 else
286 { 383 {
287 value = Json::arrayValue; 384 value = Json::arrayValue;
289 386
290 if (!username_.empty() || 387 if (!username_.empty() ||
291 !password_.empty()) 388 !password_.empty())
292 { 389 {
293 value.append(username_); 390 value.append(username_);
294 391 value.append(includePasswords ? password_ : "");
295 if (includePasswords) 392 }
296 { 393 }
297 value.append(password_); 394 }
298 } 395
299 } 396
300 }
301 }
302
303
304 void WebServiceParameters::Serialize(Json::Value& target) const
305 {
306 target = Json::objectValue;
307 target["URL"] = url_;
308 target["Username"] = username_;
309 target["Password"] = password_;
310 target["CertificateFile"] = certificateFile_;
311 target["CertificateKeyFile"] = certificateKeyFile_;
312 target["CertificateKeyPassword"] = certificateKeyPassword_;
313 target["PKCS11"] = pkcs11Enabled_;
314 target["AdvancedFormat"] = advancedFormat_;
315 }
316
317
318 #if ORTHANC_SANDBOXED == 0 397 #if ORTHANC_SANDBOXED == 0
319 WebServiceParameters::WebServiceParameters(const Json::Value& serialized) : 398 void WebServiceParameters::CheckClientCertificate() const
320 advancedFormat_(true) 399 {
321 { 400 if (!certificateFile_.empty())
322 url_ = SerializationToolbox::ReadString(serialized, "URL"); 401 {
323 username_ = SerializationToolbox::ReadString(serialized, "Username"); 402 if (!SystemToolbox::IsRegularFile(certificateFile_))
324 password_ = SerializationToolbox::ReadString(serialized, "Password"); 403 {
325 404 LOG(ERROR) << "Cannot open certificate file: " << certificateFile_;
326 std::string a, b, c; 405 throw OrthancException(ErrorCode_InexistentFile);
327 a = SerializationToolbox::ReadString(serialized, "CertificateFile"); 406 }
328 b = SerializationToolbox::ReadString(serialized, "CertificateKeyFile"); 407
329 c = SerializationToolbox::ReadString(serialized, "CertificateKeyPassword"); 408 if (!certificateKeyFile_.empty() &&
330 409 !SystemToolbox::IsRegularFile(certificateKeyFile_))
331 if (!a.empty()) 410 {
332 { 411 LOG(ERROR) << "Cannot open key file: " << certificateKeyFile_;
333 SetClientCertificate(a, b, c); 412 throw OrthancException(ErrorCode_InexistentFile);
334 } 413 }
335 414 }
336 pkcs11Enabled_ = SerializationToolbox::ReadBoolean(serialized, "PKCS11");
337 advancedFormat_ = SerializationToolbox::ReadBoolean(serialized, "AdvancedFormat");
338 } 415 }
339 #endif 416 #endif
340 } 417 }