31 PT(HTTPClient) HTTPClient::_global_ptr;
37 trim_blanks(
const string &str) {
39 while (start < str.length() && isspace(str[start])) {
43 size_t end = str.length();
44 while (end > start && isspace(str[end - 1])) {
48 return str.substr(start, end - start);
61 tokenize(
const string &str, vector_string &words,
const string &delimiters) {
63 while (p < str.length()) {
64 size_t q = str.find_first_of(delimiters, p);
65 if (q == string::npos) {
66 words.push_back(str.substr(p));
69 words.push_back(str.substr(p, q - p));
72 words.push_back(
string());
81 ssl_msg_callback(
int write_p,
int version,
int content_type,
82 const void *,
size_t len, SSL *,
void *) {
83 std::ostringstream describe;
87 describe <<
"received ";
91 describe <<
"SSL 2.0 ";
95 describe <<
"SSL 3.0 ";
99 describe <<
"TLS 1.0 ";
103 describe <<
"unknown protocol ";
106 describe <<
"message: ";
108 if (version != SSL2_VERSION) {
109 switch (content_type) {
111 describe <<
"change cipher spec, ";
115 describe <<
"alert, ";
119 describe <<
"handshake, ";
123 describe <<
"application data, ";
127 describe <<
"unknown content type, ";
131 describe << len <<
" bytes.\n";
133 downloader_cat.debug() << describe.str();
135 #endif // !defined(NDEBUG)
144 PRC_DESC(
"Configure this true (the default) to insist on verifying all SSL "
145 "(e.g. https) servers against a known certificate, or false to allow "
146 "an unverified connection. This controls the default behavior; the "
147 "specific behavior for a particular HTTPClient can be adjusted at "
148 "runtime with set_verify_ssl()."));
151 (
"ssl-cipher-list",
"DEFAULT",
152 PRC_DESC(
"This is the default value for HTTPClient::set_cipher_list()."));
156 PRC_DESC(
"This specifies the default value for HTTPClient::set_proxy_spec(). "
157 "It is a semicolon-delimited list of proxies that we use to contact "
158 "all HTTP hosts that don't specify otherwise. See "
159 "set_proxy_spec() for more information."));
162 (
"http-direct-hosts",
"",
163 PRC_DESC(
"This specifies the default value for HTTPClient::set_direct_host_spec(). "
164 "It is a semicolon-delimited list of host names that do not require a "
165 "proxy. See set_direct_host_spec() for more information."));
168 (
"http-try-all-direct",
true,
169 PRC_DESC(
"This specifies the default value for HTTPClient::set_try_all_direct(). "
170 "If this is true, a direct connection will always be attempted after an "
171 "attempt to connect through a proxy fails."));
174 (
"http-proxy-username",
"",
175 PRC_DESC(
"This specifies a default username:password to pass to the proxy."));
179 PRC_DESC(
"Adds one or more username/password pairs to all HTTP clients. The client "
180 "will present this username/password when asked to authenticate a request "
181 "for a particular server and/or realm. The username is of the form "
182 "server:realm:username:password, where either or both of server and "
183 "realm may be empty, or just realm:username:password or username:password. "
184 "If the server or realm is empty, they will match anything."));
187 (
"http-client-certificate-filename",
"",
188 PRC_DESC(
"This provides a default client certificate to offer up should an "
189 "SSL server demand one. The file names a PEM-formatted file "
190 "that includes a public and private key specification. A "
191 "connection-specific certificate may also be specified at runtime on "
192 "the HTTPClient object, but this will require having a different "
193 "HTTPClient object for each differently-certificated connection."));
196 (
"http-client-certificate-passphrase",
"",
197 PRC_DESC(
"This specifies the passphrase to use to decode the certificate named "
198 "by http-client-certificate-filename."));
202 (
"http-preapproved-server-certificate-filename",
203 PRC_DESC(
"This specifies a server hostname:port combination, followed by "
204 "at least one space, and the name of a PEM file that contains "
205 "an SSL certificate that we expect this server to offer. If "
206 "it does, we will accept the cert without further question, "
207 "even if the cert does not match any known certificate "
208 "authorities. This option may appear multiple times."));
211 (
"http-preapproved-server-certificate-name",
212 PRC_DESC(
"This specifies a server hostname:port combination, followed by "
213 "at least one space, and a string describing the subject name "
214 "of an SSL certificate we expect this server to offer. If it "
215 "it does, we will accept the cert, but only if it also matches "
216 "a known certificate authority. This option may appear "
219 _http_version = HTTPEnum::HV_11;
220 _verify_ssl = verify_ssl ? VS_normal : VS_no_verify;
223 set_proxy_spec(http_proxy);
224 set_direct_host_spec(http_direct_hosts);
225 _try_all_direct = http_try_all_direct;
227 if (!http_proxy_username.empty()) {
228 set_username(
"*proxy",
"", http_proxy_username);
231 set_cipher_list(ssl_cipher_list);
235 int num_unique_values = http_username.get_num_unique_values();
236 for (
int i = 0; i < num_unique_values; i++) {
237 string username = http_username.get_unique_value(i);
238 add_http_username(username);
242 _client_certificate_filename = http_client_certificate_filename;
243 _client_certificate_passphrase = http_client_certificate_passphrase;
245 _client_certificate_loaded =
false;
246 _client_certificate_pub =
nullptr;
247 _client_certificate_priv =
nullptr;
249 int num_server_certs = http_preapproved_server_certificate_filename.get_num_unique_values();
251 for (si = 0; si < num_server_certs; si++) {
252 string cert_line = http_preapproved_server_certificate_filename.get_unique_value(si);
254 split_whitespace(a, b, cert_line);
255 add_preapproved_server_certificate_filename(
URLSpec(a,
true), b);
258 num_server_certs = http_preapproved_server_certificate_name.get_num_unique_values();
259 for (si = 0; si < num_server_certs; si++) {
260 string cert_line = http_preapproved_server_certificate_name.get_unique_value(si);
262 split_whitespace(a, b, cert_line);
263 add_preapproved_server_certificate_name(
URLSpec(a,
true), b);
268 OpenSSLWrapper::get_global_ptr();
275 HTTPClient(
const HTTPClient ©) {
285 operator = (
const HTTPClient ©) {
286 _proxies_by_scheme = copy._proxies_by_scheme;
287 _direct_hosts = copy._direct_hosts;
288 _try_all_direct = copy._try_all_direct;
289 _http_version = copy._http_version;
290 _verify_ssl = copy._verify_ssl;
291 _usernames = copy._usernames;
292 _cookies = copy._cookies;
300 if (_ssl_ctx !=
nullptr) {
301 #if OPENSSL_VERSION_NUMBER < 0x10100000
305 _ssl_ctx->cert_store =
nullptr;
307 SSL_CTX_free(_ssl_ctx);
310 unload_client_certificate();
328 OpenSSLWrapper::get_global_ptr();
341 set_proxy_spec(
const string &proxy_spec) {
344 string trim_proxy_spec = trim_blanks(proxy_spec);
347 if (!trim_proxy_spec.empty()) {
348 vector_string proxies;
349 tokenize(trim_proxy_spec, proxies,
";");
351 for (vector_string::const_iterator pi = proxies.begin();
354 const string &spec = (*pi);
359 size_t equals = spec.find(
'=');
360 if (equals == string::npos) {
362 proxy = trim_blanks(spec);
364 scheme = trim_blanks(spec.substr(0, equals));
365 proxy = trim_blanks(spec.substr(equals + 1));
368 if (proxy ==
"DIRECT" || proxy.empty()) {
371 add_proxy(scheme,
URLSpec(proxy,
true));
385 get_proxy_spec()
const {
388 ProxiesByScheme::const_iterator si;
389 for (si = _proxies_by_scheme.begin(); si != _proxies_by_scheme.end(); ++si) {
390 const string &scheme = (*si).first;
391 const Proxies &proxies = (*si).second;
392 Proxies::const_iterator pi;
393 for (pi = proxies.begin(); pi != proxies.end(); ++pi) {
395 if (!result.empty()) {
398 if (!scheme.empty()) {
419 set_direct_host_spec(
const string &direct_host_spec) {
424 tokenize(direct_host_spec, hosts,
";");
426 for (vector_string::const_iterator hi = hosts.begin();
429 string spec = trim_blanks(*hi);
435 add_direct_host(spec);
446 get_direct_host_spec()
const {
449 DirectHosts::const_iterator si;
450 for (si = _direct_hosts.begin(); si != _direct_hosts.end(); ++si) {
453 if (!result.empty()) {
468 _proxies_by_scheme.clear();
478 add_proxy(
const string &scheme,
const URLSpec &proxy) {
483 lc_scheme.reserve(scheme.length());
484 string::const_iterator si;
485 for (si = scheme.begin(); si != scheme.end(); ++si) {
486 lc_scheme += tolower(*si);
490 if (!lc_scheme.empty() && lc_scheme[lc_scheme.length() - 1] ==
':') {
491 lc_scheme = lc_scheme.substr(0, lc_scheme.length() - 1);
494 if (!proxy_url.empty()) {
500 if (lc_scheme ==
"socks") {
503 proxy_url.set_scheme(
"socks");
505 }
else if (!proxy_url.has_scheme()) {
508 proxy_url.set_scheme(
"http");
512 _proxies_by_scheme[lc_scheme].push_back(proxy_url);
521 clear_direct_host() {
522 _direct_hosts.clear();
531 add_direct_host(
const string &hostname) {
534 lc_hostname.reserve(hostname.length());
535 for (string::const_iterator si = hostname.begin();
536 si != hostname.end();
538 lc_hostname += tolower(*si);
560 if (!hostname.empty()) {
561 DirectHosts::const_iterator si;
562 for (si = _direct_hosts.begin(); si != _direct_hosts.end(); ++si) {
563 if ((*si).matches(hostname)) {
577 bool got_any =
false;
579 if (!scheme.empty()) {
581 if (get_proxies_for_scheme(scheme, temp_list)) {
586 if (!got_any && (scheme.empty() || url.
is_ssl())) {
591 if (get_proxies_for_scheme(
"socks", temp_list)) {
594 if (get_proxies_for_scheme(
"https", temp_list)) {
602 if (get_proxies_for_scheme(
"", temp_list)) {
607 if (_try_all_direct) {
609 temp_list.push_back(
URLSpec());
614 get_proxies_for_scheme(
"http", temp_list);
620 for (pi = temp_list.begin(); pi != temp_list.end(); ++pi) {
621 if (used.insert(*pi).second) {
623 proxies.push_back(*pi);
634 get_proxies_for_url(
const URLSpec &url)
const {
636 get_proxies_for_url(url, proxies);
639 if (!proxies.empty()) {
641 if ((*pi).get_url().empty()) {
644 result += (*pi).get_url();
648 while (pi != proxies.end()) {
650 if ((*pi).get_url().empty()) {
653 result += (*pi).get_url();
672 set_username(
const string &server,
const string &realm,
const string &username) {
673 string key = server +
":" + realm;
674 if (username.empty()) {
675 _usernames.erase(key);
677 _usernames[key] = username;
686 get_username(
const string &server,
const string &realm)
const {
687 string key = server +
":" + realm;
688 Usernames::const_iterator ui;
689 ui = _usernames.find(key);
690 if (ui != _usernames.end()) {
701 set_cookie(
const HTTPCookie &cookie) {
702 if (cookie.is_expired()) {
703 clear_cookie(cookie);
706 std::pair<Cookies::iterator, bool> result = _cookies.insert(cookie);
707 if (!result.second) {
710 const HTTPCookie &orig_cookie = *result.first;
711 ((HTTPCookie &)orig_cookie).update_from(cookie);
722 clear_cookie(
const HTTPCookie &cookie) {
723 Cookies::iterator ci = _cookies.find(cookie);
724 if (ci != _cookies.end()) {
736 clear_all_cookies() {
745 has_cookie(
const HTTPCookie &cookie)
const {
746 Cookies::const_iterator ci = _cookies.find(cookie);
747 return (ci != _cookies.end());
754 HTTPCookie HTTPClient::
755 get_cookie(
const HTTPCookie &cookie)
const {
756 Cookies::const_iterator ci = _cookies.find(cookie);
757 if (ci != _cookies.end()) {
770 copy_cookies_from(
const HTTPClient &other) {
771 Cookies::const_iterator ci;
772 for (ci = other._cookies.begin(); ci != other._cookies.end(); ++ci) {
783 write_cookies(std::ostream &out)
const {
784 Cookies::const_iterator ci;
785 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) {
796 send_cookies(std::ostream &out,
const URLSpec &url) {
798 bool any_expired =
false;
799 bool first_cookie =
true;
801 Cookies::const_iterator ci;
802 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) {
803 const HTTPCookie &cookie = (*ci);
804 if (cookie.is_expired(now)) {
807 }
else if (cookie.matches_url(url)) {
810 first_cookie =
false;
814 out << cookie.get_name() <<
"=" << cookie.get_value();
824 Cookies::const_iterator ci;
825 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) {
826 const HTTPCookie &cookie = (*ci);
827 if (!cookie.is_expired(now)) {
828 new_cookies.insert(new_cookies.end(), cookie);
831 _cookies.swap(new_cookies);
844 load_client_certificate() {
845 if (!_client_certificate_loaded) {
846 _client_certificate_loaded =
true;
848 if (!_client_certificate_filename.empty()) {
849 _client_certificate_filename.set_text();
854 if (!vfs->read_file(_client_certificate_filename,
855 _client_certificate_pem,
true)) {
857 downloader_cat.warning()
858 <<
"Could not read " << _client_certificate_filename <<
".\n";
863 if (!_client_certificate_pem.empty()) {
866 BIO *mbio = BIO_new_mem_buf((
void *)_client_certificate_pem.data(),
867 _client_certificate_pem.length());
870 _client_certificate_priv =
871 PEM_read_bio_PrivateKey(mbio,
nullptr,
nullptr,
872 (
char *)_client_certificate_passphrase.c_str());
876 (void)BIO_reset(mbio);
879 _client_certificate_pub =
880 PEM_read_bio_X509(mbio,
nullptr,
nullptr,
nullptr);
885 NotifySeverity sev = NS_debug;
886 string source =
"memory";
887 if (!_client_certificate_filename.empty()) {
892 source = _client_certificate_filename;
895 if (downloader_cat.is_on(sev)) {
896 if (_client_certificate_priv !=
nullptr &&
897 _client_certificate_pub !=
nullptr) {
898 downloader_cat.out(sev)
899 <<
"Read client certificate from " << source <<
"\n";
902 if (_client_certificate_priv ==
nullptr) {
903 downloader_cat.out(sev)
904 <<
"Could not read private key from " << source <<
"\n";
907 if (_client_certificate_pub ==
nullptr) {
908 downloader_cat.out(sev)
909 <<
"Could not read public key from " << source <<
"\n";
916 return (_client_certificate_priv !=
nullptr &&
917 _client_certificate_pub !=
nullptr);
933 add_preapproved_server_certificate_filename(
const URLSpec &url,
const Filename &filename) {
937 if (!vfs->read_file(filename, pem,
true)) {
939 downloader_cat.warning()
940 <<
"Could not read " << filename <<
".\n";
944 return add_preapproved_server_certificate_pem(url, pem);
960 add_preapproved_server_certificate_pem(
const URLSpec &url,
const string &pem) {
963 BIO *mbio = BIO_new_mem_buf((
void *)pem.data(), pem.length());
966 X509 *cert = PEM_read_bio_X509(mbio,
nullptr,
nullptr,
nullptr);
969 if (cert ==
nullptr) {
970 downloader_cat.warning()
971 <<
"Could not parse PEM data\n";
976 PreapprovedServerCerts::iterator psci =
977 _preapproved_server_certs.insert(PreapprovedServerCerts::value_type(server_and_port, PreapprovedServerCert())).first;
979 PreapprovedServerCert &psc = (*psci).second;
980 psc._certs.push_back(cert);
1006 add_preapproved_server_certificate_name(
const URLSpec &url,
const string &name) {
1007 X509_NAME *cert_name = parse_x509_name(name);
1008 if (cert_name ==
nullptr) {
1009 downloader_cat.warning()
1010 <<
"Could not parse certificate name " << name <<
"\n";
1015 PreapprovedServerCerts::iterator psci =
1016 _preapproved_server_certs.insert(PreapprovedServerCerts::value_type(server_and_port, PreapprovedServerCert())).first;
1018 PreapprovedServerCert &psc = (*psci).second;
1019 psc._cert_names.push_back(cert_name);
1029 clear_preapproved_server_certificates(
const URLSpec &url) {
1031 _preapproved_server_certs.erase(server_and_port);
1038 clear_all_preapproved_server_certificates() {
1039 _preapproved_server_certs.clear();
1047 get_http_version_string()
const {
1048 switch (_http_version) {
1049 case HTTPEnum::HV_09:
1052 case HTTPEnum::HV_10:
1055 case HTTPEnum::HV_11:
1058 case HTTPEnum::HV_other:
1071 HTTPEnum::HTTPVersion HTTPClient::
1072 parse_http_version_string(
const string &version) {
1073 if (version ==
"HTTP/1.0") {
1074 return HTTPEnum::HV_10;
1075 }
else if (version ==
"HTTP/1.1") {
1076 return HTTPEnum::HV_11;
1077 }
else if (version.substr(0, 6) ==
"HTTP/0") {
1078 return HTTPEnum::HV_09;
1080 return HTTPEnum::HV_other;
1091 load_certificates(
const Filename &filename) {
1092 OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr();
1093 return (sslw->load_certificates(filename) != 0);
1111 PT(HTTPChannel) HTTPClient::
1112 make_channel(
bool persistent_connection) {
1113 PT(HTTPChannel) doc =
new HTTPChannel(
this);
1114 doc->set_persistent_connection(persistent_connection);
1124 PT(HTTPChannel) HTTPClient::
1125 post_form(
const URLSpec &url,
const string &body) {
1126 PT(HTTPChannel) doc =
new HTTPChannel(
this);
1127 doc->post_form(url, body);
1136 PT(HTTPChannel) HTTPClient::
1137 get_document(
const URLSpec &url) {
1138 PT(HTTPChannel) doc =
new HTTPChannel(
this);
1139 doc->get_document(url);
1149 PT(HTTPChannel) HTTPClient::
1150 get_header(
const URLSpec &url) {
1151 PT(HTTPChannel) doc =
new HTTPChannel(
this);
1152 doc->get_header(url);
1159 HTTPClient *HTTPClient::
1161 if (_global_ptr ==
nullptr) {
1162 _global_ptr =
new HTTPClient;
1171 SSL_CTX *HTTPClient::
1173 if (_ssl_ctx !=
nullptr) {
1179 _ssl_ctx = SSL_CTX_new(SSLv23_client_method());
1184 if (downloader_cat.is_debug()) {
1185 SSL_CTX_set_msg_callback(_ssl_ctx, ssl_msg_callback);
1190 OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr();
1191 sslw->notify_ssl_errors();
1193 X509_STORE *store = sslw->get_x509_store();
1194 #if OPENSSL_VERSION_NUMBER >= 0x10100000
1195 if (store !=
nullptr) {
1196 X509_STORE_up_ref(store);
1199 SSL_CTX_set_cert_store(_ssl_ctx, store);
1220 check_preapproved_server_certificate(
const URLSpec &url, X509 *cert,
1221 bool &cert_preapproved,
bool &cert_name_preapproved)
const {
1222 cert_preapproved =
false;
1223 cert_name_preapproved =
false;
1226 PreapprovedServerCerts::const_iterator psci =
1227 _preapproved_server_certs.find(server_and_port);
1229 if (psci == _preapproved_server_certs.end()) {
1234 const PreapprovedServerCert &psc = (*psci).second;
1237 ServerCerts::const_iterator sci;
1238 for (sci = psc._certs.begin(); sci != psc._certs.end(); ++sci) {
1239 if (X509_cmp(cert, *sci) == 0) {
1240 cert_preapproved =
true;
1241 cert_name_preapproved =
true;
1242 downloader_cat.info()
1243 <<
"Server certificate is pre-approved.\n";
1249 X509_NAME *subject = X509_get_subject_name(cert);
1250 ServerCertNames::const_iterator scni;
1251 for (scni = psc._cert_names.begin(); scni != psc._cert_names.end(); ++scni) {
1252 X509_NAME *cert_name = (*scni);
1253 if (x509_name_subset(cert_name, subject)) {
1254 downloader_cat.info()
1255 <<
"Server certificate name is pre-approved.\n";
1256 cert_name_preapproved =
true;
1270 get_proxies_for_scheme(
const string &scheme,
pvector<URLSpec> &proxies)
const {
1271 ProxiesByScheme::const_iterator si = _proxies_by_scheme.find(scheme);
1272 if (si == _proxies_by_scheme.end()) {
1275 const Proxies &scheme_proxies = (*si).second;
1276 if (scheme_proxies.empty()) {
1280 Proxies::const_iterator pi;
1281 for (pi = scheme_proxies.begin(); pi != scheme_proxies.end(); ++pi) {
1282 proxies.push_back(*pi);
1294 add_http_username(
const string &http_username) {
1295 size_t c1 = http_username.find(
':');
1296 if (c1 != string::npos) {
1297 size_t c2 = http_username.find(
':', c1 + 1);
1298 if (c2 != string::npos) {
1299 size_t c3 = http_username.find(
':', c2 + 1);
1300 if (c3 != string::npos) {
1301 size_t c4 = http_username.find(
':', c3 + 1);
1302 if (c4 != string::npos) {
1304 downloader_cat.error()
1305 <<
"Invalid http-username " << http_username <<
"\n";
1309 set_username(http_username.substr(0, c1),
1310 http_username.substr(c1 + 1, c2 - (c1 + 1)),
1311 http_username.substr(c2 + 1));
1316 set_username(
string(),
1317 http_username.substr(0, c1),
1318 http_username.substr(c1 + 1));
1322 set_username(
string(),
string(), http_username);
1326 downloader_cat.error()
1327 <<
"Invalid http-username " << http_username <<
"\n";
1335 select_username(
const URLSpec &url,
bool is_proxy,
const string &realm)
const {
1348 if (username.empty()) {
1350 username = get_username(
"*proxy", realm);
1352 if (username.empty()) {
1354 username = get_username(
"*proxy",
string());
1357 if (username.empty()) {
1359 username = get_username(url.
get_server(), realm);
1361 if (username.empty()) {
1363 username = get_username(url.
get_server(),
string());
1365 if (username.empty()) {
1367 username = get_username(
string(), realm);
1369 if (username.empty()) {
1371 username = get_username(
string(),
string());
1381 HTTPAuthorization *HTTPClient::
1382 select_auth(
const URLSpec &url,
bool is_proxy,
const string &last_realm) {
1383 Domains &domains = is_proxy ? _proxy_domains : _www_domains;
1384 string canon = HTTPAuthorization::get_canonical_url(url).get_url();
1388 Domains::const_iterator best_di = domains.end();
1389 size_t longest_length = 0;
1390 Domains::const_iterator di;
1391 for (di = domains.begin(); di != domains.end(); ++di) {
1392 const string &domain = (*di).first;
1393 size_t length = domain.length();
1394 if (domain == canon.substr(0, length)) {
1396 if (length > longest_length) {
1398 longest_length = length;
1403 if (best_di != domains.end()) {
1405 if (downloader_cat.is_spam()) {
1406 downloader_cat.spam()
1407 <<
"Choosing domain " << (*best_di).first <<
" for " << url <<
"\n";
1409 const Realms &realms = (*best_di).second._realms;
1411 Realms::const_iterator ri;
1412 ri = realms.find(last_realm);
1413 if (ri != realms.end()) {
1414 return (*ri).second;
1417 if (!realms.empty()) {
1419 return (*realms.begin()).second;
1433 PT(HTTPAuthorization) HTTPClient::
1434 generate_auth(
const URLSpec &url,
bool is_proxy,
const string &challenge) {
1435 HTTPAuthorization::AuthenticationSchemes schemes;
1436 HTTPAuthorization::parse_authentication_schemes(schemes, challenge);
1438 PT(HTTPAuthorization) auth;
1439 HTTPAuthorization::AuthenticationSchemes::iterator si;
1441 si = schemes.find(
"digest");
1442 if (si != schemes.end()) {
1443 auth =
new HTTPDigestAuthorization((*si).second, url, is_proxy);
1446 if (auth ==
nullptr || !auth->is_valid()) {
1447 si = schemes.find(
"basic");
1448 if (si != schemes.end()) {
1449 auth =
new HTTPBasicAuthorization((*si).second, url, is_proxy);
1453 if (auth ==
nullptr || !auth->is_valid()) {
1454 downloader_cat.warning()
1455 <<
"Don't know how to use any of the server's available authorization schemes:\n";
1456 for (si = schemes.begin(); si != schemes.end(); ++si) {
1457 downloader_cat.warning() << (*si).first <<
"\n";
1463 Domains &domains = is_proxy ? _proxy_domains : _www_domains;
1464 const vector_string &domain = auth->get_domain();
1465 vector_string::const_iterator si;
1466 for (si = domain.begin(); si != domain.end(); ++si) {
1467 domains[(*si)]._realms[auth->get_realm()] = auth;
1479 unload_client_certificate() {
1480 if (_client_certificate_priv !=
nullptr) {
1481 EVP_PKEY_free(_client_certificate_priv);
1482 _client_certificate_priv =
nullptr;
1485 if (_client_certificate_pub !=
nullptr) {
1486 X509_free(_client_certificate_pub);
1487 _client_certificate_pub =
nullptr;
1490 _client_certificate_loaded =
false;
1497 X509_NAME *HTTPClient::
1498 parse_x509_name(
const string &source) {
1499 X509_NAME *result =
nullptr;
1501 result = X509_NAME_new();
1502 bool added_any =
false;
1504 string::const_iterator si;
1505 si = source.begin();
1506 while (si != source.end()) {
1512 while (si != source.end() && (*si) !=
'=' && (*si) !=
'/') {
1513 if ((*si) ==
'\\') {
1515 if (si != source.end()) {
1525 int nid = OBJ_txt2nid((
char *)type.c_str());
1526 if (nid == NID_undef) {
1527 downloader_cat.info()
1528 <<
"Unknown type " << type <<
" in X509 name: " << source
1530 X509_NAME_free(result);
1536 if (si != source.end() && (*si) ==
'=') {
1538 while (si != source.end() && (*si) !=
'/') {
1539 if ((*si) ==
'\\') {
1541 if (si != source.end()) {
1552 if (!value.empty()) {
1554 X509_NAME_add_entry_by_NID(result, nid, V_ASN1_APP_CHOOSE,
1555 (
unsigned char *)value.c_str(), -1, -1, 0);
1557 downloader_cat.info()
1558 <<
"Unable to add " << type <<
"=" << value <<
" in X509 name: "
1560 X509_NAME_free(result);
1569 downloader_cat.info()
1570 <<
"Invalid empty X509 name: " << source <<
"\n";
1571 X509_NAME_free(result);
1583 x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) {
1584 int count_a = X509_NAME_entry_count(name_a);
1585 for (
int ai = 0; ai < count_a; ai++) {
1586 X509_NAME_ENTRY *na = X509_NAME_get_entry(name_a, ai);
1588 int bi = X509_NAME_get_index_by_OBJ(name_b, X509_NAME_ENTRY_get_object(na), -1);
1594 X509_NAME_ENTRY *nb = X509_NAME_get_entry(name_b, bi);
1595 ASN1_STRING *na_value = X509_NAME_ENTRY_get_data(na);
1596 ASN1_STRING *nb_value = X509_NAME_ENTRY_get_data(nb);
1597 if (na_value->length != nb_value->length ||
1598 memcmp(na_value->data, nb_value->data, na_value->length) != 0) {
1610 split_whitespace(
string &a,
string &b,
const string &c) {
1614 while (p < c.length() && isspace(c[p])) {
1620 while (p < c.length() && !isspace(c[p])) {
1624 a = c.substr(q, p - q);
1627 while (p < c.length() && isspace(c[p])) {
1636 HTTPClient::PreapprovedServerCert::
1637 ~PreapprovedServerCert() {
1638 ServerCerts::const_iterator sci;
1639 for (sci = _certs.begin(); sci != _certs.end(); ++sci) {
1643 ServerCertNames::const_iterator scni;
1644 for (scni = _cert_names.begin(); scni != _cert_names.end(); ++scni) {
1645 X509_NAME_free(*scni);
1649 #endif // HAVE_OPENSSL