1//
2// HTTPCredentials.cpp
3//
4// Library: Net
5// Package: HTTP
6// Module: HTTPCredentials
7//
8// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru).
9// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
10// and Contributors.
11//
12// SPDX-License-Identifier: BSL-1.0
13//
14
15
16#include "Poco/Net/HTTPAuthenticationParams.h"
17#include "Poco/Net/HTTPBasicCredentials.h"
18#include "Poco/Net/HTTPCredentials.h"
19#include "Poco/Net/HTTPRequest.h"
20#include "Poco/Net/HTTPResponse.h"
21#include "Poco/Net/NetException.h"
22#include "Poco/String.h"
23#include "Poco/Ascii.h"
24#include "Poco/URI.h"
25
26
27using Poco::icompare;
28
29
30namespace Poco {
31namespace Net {
32
33
34HTTPCredentials::HTTPCredentials()
35{
36}
37
38
39HTTPCredentials::HTTPCredentials(const std::string& username, const std::string& password):
40 _digest(username, password)
41{
42}
43
44
45HTTPCredentials::~HTTPCredentials()
46{
47}
48
49
50void HTTPCredentials::fromUserInfo(const std::string& userInfo)
51{
52 std::string username;
53 std::string password;
54
55 extractCredentials(userInfo, username, password);
56 setUsername(username);
57 setPassword(password);
58 _digest.reset();
59}
60
61
62void HTTPCredentials::fromURI(const URI& uri)
63{
64 std::string username;
65 std::string password;
66
67 extractCredentials(uri, username, password);
68 setUsername(username);
69 setPassword(password);
70 setHost(uri.getHost());
71 _digest.reset();
72}
73
74
75void HTTPCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response)
76{
77 for (HTTPResponse::ConstIterator iter = response.find(HTTPAuthenticationParams::WWW_AUTHENTICATE); iter != response.end(); ++iter)
78 {
79 if (isBasicCredentials(iter->second))
80 {
81 HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request);
82 return;
83 }
84 else if (isDigestCredentials(iter->second))
85 {
86 _digest.authenticate(request, HTTPAuthenticationParams(iter->second.substr(7)));
87 return;
88 }
89 else if (isNTLMCredentials(iter->second))
90 {
91 _ntlm.setUsername(_digest.getUsername());
92 _ntlm.setPassword(_digest.getPassword());
93 if (_ntlm.getHost().empty())
94 {
95 _ntlm.setHost(request.getHost());
96 }
97 _ntlm.authenticate(request, iter->second.substr(5));
98 return;
99 }
100 }
101}
102
103
104void HTTPCredentials::updateAuthInfo(HTTPRequest& request)
105{
106 if (request.has(HTTPRequest::AUTHORIZATION))
107 {
108 const std::string& authorization = request.get(HTTPRequest::AUTHORIZATION);
109
110 if (isBasicCredentials(authorization))
111 {
112 HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request);
113 }
114 else if (isDigestCredentials(authorization))
115 {
116 _digest.updateAuthInfo(request);
117 }
118 else if (isNTLMCredentials(authorization))
119 {
120 _ntlm.updateAuthInfo(request);
121 }
122 }
123}
124
125
126void HTTPCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response)
127{
128 for (HTTPResponse::ConstIterator iter = response.find(HTTPAuthenticationParams::PROXY_AUTHENTICATE); iter != response.end(); ++iter)
129 {
130 if (isBasicCredentials(iter->second))
131 {
132 HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).proxyAuthenticate(request);
133 return;
134 }
135 else if (isDigestCredentials(iter->second))
136 {
137 _digest.proxyAuthenticate(request, HTTPAuthenticationParams(iter->second.substr(7)));
138 return;
139 }
140 else if (isNTLMCredentials(iter->second))
141 {
142 _ntlm.setUsername(_digest.getUsername());
143 _ntlm.setPassword(_digest.getPassword());
144 _ntlm.proxyAuthenticate(request, iter->second.substr(5));
145 return;
146 }
147 }
148}
149
150
151void HTTPCredentials::updateProxyAuthInfo(HTTPRequest& request)
152{
153 if (request.has(HTTPRequest::PROXY_AUTHORIZATION))
154 {
155 const std::string& authorization = request.get(HTTPRequest::PROXY_AUTHORIZATION);
156
157 if (isBasicCredentials(authorization))
158 {
159 HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).proxyAuthenticate(request);
160 }
161 else if (isDigestCredentials(authorization))
162 {
163 _digest.updateProxyAuthInfo(request);
164 }
165 else if (isNTLMCredentials(authorization))
166 {
167 _ntlm.updateProxyAuthInfo(request);
168 }
169 }
170}
171
172
173bool HTTPCredentials::isBasicCredentials(const std::string& header)
174{
175 return icompare(header, 0, 5, "Basic") == 0 && (header.size() > 5 ? Poco::Ascii::isSpace(header[5]) : true);
176}
177
178
179bool HTTPCredentials::isDigestCredentials(const std::string& header)
180{
181 return icompare(header, 0, 6, "Digest") == 0 && (header.size() > 6 ? Poco::Ascii::isSpace(header[6]) : true);
182}
183
184
185bool HTTPCredentials::isNTLMCredentials(const std::string& header)
186{
187 return icompare(header, 0, 4, "NTLM") == 0 && (header.size() > 5 ? Poco::Ascii::isSpace(header[5]) : true);
188}
189
190
191bool HTTPCredentials::hasBasicCredentials(const HTTPRequest& request)
192{
193 return request.has(HTTPRequest::AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::AUTHORIZATION));
194}
195
196
197bool HTTPCredentials::hasDigestCredentials(const HTTPRequest& request)
198{
199 return request.has(HTTPRequest::AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::AUTHORIZATION));
200}
201
202
203bool HTTPCredentials::hasNTLMCredentials(const HTTPRequest& request)
204{
205 return request.has(HTTPRequest::AUTHORIZATION) && isNTLMCredentials(request.get(HTTPRequest::AUTHORIZATION));
206}
207
208
209bool HTTPCredentials::hasProxyBasicCredentials(const HTTPRequest& request)
210{
211 return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION));
212}
213
214
215bool HTTPCredentials::hasProxyDigestCredentials(const HTTPRequest& request)
216{
217 return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION));
218}
219
220
221bool HTTPCredentials::hasProxyNTLMCredentials(const HTTPRequest& request)
222{
223 return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isNTLMCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION));
224}
225
226
227void HTTPCredentials::extractCredentials(const std::string& userInfo, std::string& username, std::string& password)
228{
229 const std::string::size_type p = userInfo.find(':');
230
231 if (p != std::string::npos)
232 {
233 username.assign(userInfo, 0, p);
234 password.assign(userInfo, p + 1, std::string::npos);
235 }
236 else
237 {
238 username.assign(userInfo);
239 password.clear();
240 }
241}
242
243
244void HTTPCredentials::extractCredentials(const Poco::URI& uri, std::string& username, std::string& password)
245{
246 if (!uri.getUserInfo().empty())
247 {
248 extractCredentials(uri.getUserInfo(), username, password);
249 }
250}
251
252
253} } // namespace Poco::Net
254