Mercurial > hg > orthanc
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 } |