Panda3D
|
00001 // Filename: httpClient.cxx 00002 // Created by: drose (24Sep02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "httpClient.h" 00016 #include "httpChannel.h" 00017 #include "config_downloader.h" 00018 #include "filename.h" 00019 #include "config_express.h" 00020 #include "virtualFileSystem.h" 00021 #include "executionEnvironment.h" 00022 #include "httpBasicAuthorization.h" 00023 #include "httpDigestAuthorization.h" 00024 #include "globPattern.h" 00025 00026 #ifdef HAVE_OPENSSL 00027 00028 PT(HTTPClient) HTTPClient::_global_ptr; 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Function: trim_blanks 00032 // Description: 00033 //////////////////////////////////////////////////////////////////// 00034 static string 00035 trim_blanks(const string &str) { 00036 size_t start = 0; 00037 while (start < str.length() && isspace(str[start])) { 00038 start++; 00039 } 00040 00041 size_t end = str.length(); 00042 while (end > start && isspace(str[end - 1])) { 00043 end--; 00044 } 00045 00046 return str.substr(start, end - start); 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: tokenize 00051 // Description: Chops the source string up into pieces delimited by 00052 // any of the characters specified in delimiters. 00053 // Repeated delimiter characters represent zero-length 00054 // tokens. 00055 // 00056 // It is the user's responsibility to ensure the output 00057 // vector is cleared before calling this function; the 00058 // results will simply be appended to the end of the 00059 // vector. 00060 //////////////////////////////////////////////////////////////////// 00061 static void 00062 tokenize(const string &str, vector_string &words, const string &delimiters) { 00063 size_t p = 0; 00064 while (p < str.length()) { 00065 size_t q = str.find_first_of(delimiters, p); 00066 if (q == string::npos) { 00067 words.push_back(str.substr(p)); 00068 return; 00069 } 00070 words.push_back(str.substr(p, q - p)); 00071 p = q + 1; 00072 } 00073 words.push_back(string()); 00074 } 00075 00076 //////////////////////////////////////////////////////////////////// 00077 // Function: HTTPClient::Constructor 00078 // Access: Published 00079 // Description: 00080 //////////////////////////////////////////////////////////////////// 00081 HTTPClient:: 00082 HTTPClient() { 00083 ConfigVariableBool verify_ssl 00084 ("verify-ssl", true, 00085 PRC_DESC("Configure this true (the default) to insist on verifying all SSL " 00086 "(e.g. https) servers against a known certificate, or false to allow " 00087 "an unverified connection. This controls the default behavior; the " 00088 "specific behavior for a particular HTTPClient can be adjusted at " 00089 "runtime with set_verify_ssl().")); 00090 00091 ConfigVariableString ssl_cipher_list 00092 ("ssl-cipher-list", "DEFAULT", 00093 PRC_DESC("This is the default value for HTTPClient::set_cipher_list().")); 00094 00095 ConfigVariableString http_proxy 00096 ("http-proxy", "", 00097 PRC_DESC("This specifies the default value for HTTPClient::set_proxy_spec(). " 00098 "It is a semicolon-delimited list of proxies that we use to contact " 00099 "all HTTP hosts that don't specify otherwise. See " 00100 "set_proxy_spec() for more information.")); 00101 00102 ConfigVariableString http_direct_hosts 00103 ("http-direct-hosts", "", 00104 PRC_DESC("This specifies the default value for HTTPClient::set_direct_host_spec(). " 00105 "It is a semicolon-delimited list of host names that do not require a " 00106 "proxy. See set_direct_host_spec() for more information.")); 00107 00108 ConfigVariableBool http_try_all_direct 00109 ("http-try-all-direct", true, 00110 PRC_DESC("This specifies the default value for HTTPClient::set_try_all_direct(). " 00111 "If this is true, a direct connection will always be attempted after an " 00112 "attempt to connect through a proxy fails.")); 00113 00114 ConfigVariableString http_proxy_username 00115 ("http-proxy-username", "", 00116 PRC_DESC("This specifies a default username:password to pass to the proxy.")); 00117 00118 ConfigVariableList http_username 00119 ("http-username", 00120 PRC_DESC("Adds one or more username/password pairs to all HTTP clients. The client " 00121 "will present this username/password when asked to authenticate a request " 00122 "for a particular server and/or realm. The username is of the form " 00123 "server:realm:username:password, where either or both of server and " 00124 "realm may be empty, or just realm:username:password or username:password. " 00125 "If the server or realm is empty, they will match anything.")); 00126 00127 ConfigVariableFilename http_client_certificate_filename 00128 ("http-client-certificate-filename", "", 00129 PRC_DESC("This provides a default client certificate to offer up should an " 00130 "SSL server demand one. The file names a PEM-formatted file " 00131 "that includes a public and private key specification. A " 00132 "connection-specific certificate may also be specified at runtime on " 00133 "the HTTPClient object, but this will require having a different " 00134 "HTTPClient object for each differently-certificated connection.")); 00135 00136 ConfigVariableString http_client_certificate_passphrase 00137 ("http-client-certificate-passphrase", "", 00138 PRC_DESC("This specifies the passphrase to use to decode the certificate named " 00139 "by http-client-certificate-filename.")); 00140 00141 00142 ConfigVariableList http_preapproved_server_certificate_filename 00143 ("http-preapproved-server-certificate-filename", 00144 PRC_DESC("This specifies a server hostname:port combination, followed by " 00145 "at least one space, and the name of a PEM file that contains " 00146 "an SSL certificate that we expect this server to offer. If " 00147 "it does, we will accept the cert without further question, " 00148 "even if the cert does not match any known certificate " 00149 "authorities. This option may appear multiple times.")); 00150 00151 ConfigVariableList http_preapproved_server_certificate_name 00152 ("http-preapproved-server-certificate-name", 00153 PRC_DESC("This specifies a server hostname:port combination, followed by " 00154 "at least one space, and a string describing the subject name " 00155 "of an SSL certificate we expect this server to offer. If it " 00156 "it does, we will accept the cert, but only if it also matches " 00157 "a known certificate authority. This option may appear " 00158 "multiple times.")); 00159 00160 _http_version = HTTPEnum::HV_11; 00161 _verify_ssl = verify_ssl ? VS_normal : VS_no_verify; 00162 _ssl_ctx = (SSL_CTX *)NULL; 00163 00164 set_proxy_spec(http_proxy); 00165 set_direct_host_spec(http_direct_hosts); 00166 _try_all_direct = http_try_all_direct; 00167 00168 if (!http_proxy_username.empty()) { 00169 set_username("*proxy", "", http_proxy_username); 00170 } 00171 00172 set_cipher_list(ssl_cipher_list); 00173 00174 { 00175 // Also load in the general usernames. 00176 int num_unique_values = http_username.get_num_unique_values(); 00177 for (int i = 0; i < num_unique_values; i++) { 00178 string username = http_username.get_unique_value(i); 00179 add_http_username(username); 00180 } 00181 } 00182 00183 _client_certificate_filename = http_client_certificate_filename; 00184 _client_certificate_passphrase = http_client_certificate_passphrase; 00185 00186 _client_certificate_loaded = false; 00187 _client_certificate_pub = NULL; 00188 _client_certificate_priv = NULL; 00189 00190 int num_server_certs = http_preapproved_server_certificate_filename.get_num_unique_values(); 00191 int si; 00192 for (si = 0; si < num_server_certs; si++) { 00193 string cert_line = http_preapproved_server_certificate_filename.get_unique_value(si); 00194 string a, b; 00195 split_whitespace(a, b, cert_line); 00196 add_preapproved_server_certificate_filename(URLSpec(a, true), b); 00197 } 00198 00199 num_server_certs = http_preapproved_server_certificate_name.get_num_unique_values(); 00200 for (si = 0; si < num_server_certs; si++) { 00201 string cert_line = http_preapproved_server_certificate_name.get_unique_value(si); 00202 string a, b; 00203 split_whitespace(a, b, cert_line); 00204 add_preapproved_server_certificate_name(URLSpec(a, true), b); 00205 } 00206 00207 // The first time we create an HTTPClient, we must initialize the 00208 // OpenSSL library. The OpenSSLWrapper object does that. 00209 OpenSSLWrapper::get_global_ptr(); 00210 } 00211 00212 //////////////////////////////////////////////////////////////////// 00213 // Function: HTTPClient::Copy Constructor 00214 // Access: Published 00215 // Description: 00216 //////////////////////////////////////////////////////////////////// 00217 HTTPClient:: 00218 HTTPClient(const HTTPClient ©) { 00219 _ssl_ctx = (SSL_CTX *)NULL; 00220 00221 (*this) = copy; 00222 } 00223 00224 //////////////////////////////////////////////////////////////////// 00225 // Function: HTTPClient::Copy Assignment Operator 00226 // Access: Published 00227 // Description: 00228 //////////////////////////////////////////////////////////////////// 00229 void HTTPClient:: 00230 operator = (const HTTPClient ©) { 00231 _proxies_by_scheme = copy._proxies_by_scheme; 00232 _direct_hosts = copy._direct_hosts; 00233 _try_all_direct = copy._try_all_direct; 00234 _http_version = copy._http_version; 00235 _verify_ssl = copy._verify_ssl; 00236 _usernames = copy._usernames; 00237 _cookies = copy._cookies; 00238 } 00239 00240 //////////////////////////////////////////////////////////////////// 00241 // Function: HTTPClient::Destructor 00242 // Access: Published 00243 // Description: 00244 //////////////////////////////////////////////////////////////////// 00245 HTTPClient:: 00246 ~HTTPClient() { 00247 // Before we can free the context, we must remove the X509_STORE 00248 // pointer from it, so it won't be destroyed along with it (this 00249 // object is shared among all contexts). 00250 if (_ssl_ctx != (SSL_CTX *)NULL) { 00251 _ssl_ctx->cert_store = NULL; 00252 SSL_CTX_free(_ssl_ctx); 00253 } 00254 00255 unload_client_certificate(); 00256 } 00257 00258 //////////////////////////////////////////////////////////////////// 00259 // Function: HTTPClient::init_random_seed 00260 // Access: Published, Static 00261 // Description: This may be called once, presumably at the beginning 00262 // of an application, to initialize OpenSSL's random 00263 // seed. On Windows, it is particularly important to 00264 // call this at startup if you are going to be performing 00265 // any https operations or otherwise use encryption, 00266 // since the Windows algorithm for getting a random seed 00267 // takes 2-3 seconds at startup, but can take 30 seconds 00268 // or more after you have opened a 3-D graphics window 00269 // and started rendering. 00270 // 00271 // There is no harm in calling this method multiple 00272 // times, or in not calling it at all. 00273 //////////////////////////////////////////////////////////////////// 00274 void HTTPClient:: 00275 init_random_seed() { 00276 // Creating the global OpenSSLWrapper object is nowadays sufficient 00277 // to ensure that OpenSSL and its random seed have been initialized. 00278 OpenSSLWrapper::get_global_ptr(); 00279 } 00280 00281 //////////////////////////////////////////////////////////////////// 00282 // Function: HTTPClient::set_proxy_spec 00283 // Access: Published 00284 // Description: Specifies the complete set of proxies to use for all 00285 // schemes. This is either a semicolon-delimited set of 00286 // hostname:ports, or a semicolon-delimited set of pairs 00287 // of the form "scheme=hostname:port", or a combination. 00288 // Use the keyword DIRECT, or an empty string, to 00289 // represent a direct connection. A particular scheme 00290 // and/or proxy host may be listed more than once. This 00291 // is a convenience function that can be used in place 00292 // of explicit calls to add_proxy() for each 00293 // scheme/proxy pair. 00294 //////////////////////////////////////////////////////////////////// 00295 void HTTPClient:: 00296 set_proxy_spec(const string &proxy_spec) { 00297 clear_proxy(); 00298 00299 string trim_proxy_spec = trim_blanks(proxy_spec); 00300 00301 // Tokenize the string based on the semicolons. 00302 if (!trim_proxy_spec.empty()) { 00303 vector_string proxies; 00304 tokenize(trim_proxy_spec, proxies, ";"); 00305 00306 for (vector_string::const_iterator pi = proxies.begin(); 00307 pi != proxies.end(); 00308 ++pi) { 00309 const string &spec = (*pi); 00310 00311 // Divide out the scheme and the hostname. 00312 string scheme; 00313 string proxy; 00314 size_t equals = spec.find('='); 00315 if (equals == string::npos) { 00316 scheme = ""; 00317 proxy = trim_blanks(spec); 00318 } else { 00319 scheme = trim_blanks(spec.substr(0, equals)); 00320 proxy = trim_blanks(spec.substr(equals + 1)); 00321 } 00322 00323 if (proxy == "DIRECT" || proxy.empty()) { 00324 add_proxy(scheme, URLSpec()); 00325 } else { 00326 add_proxy(scheme, URLSpec(proxy, true)); 00327 } 00328 } 00329 } 00330 } 00331 00332 //////////////////////////////////////////////////////////////////// 00333 // Function: HTTPClient::get_proxy_spec 00334 // Access: Published 00335 // Description: Returns the complete set of proxies to use for all 00336 // schemes. This is a string of the form specified by 00337 // set_proxy_spec(), above. Note that the string 00338 // returned by this function may not be exactly the same 00339 // as the string passed into set_proxy_spec(), since the 00340 // string is regenerated from the internal storage 00341 // structures and may therefore be reordered. 00342 //////////////////////////////////////////////////////////////////// 00343 string HTTPClient:: 00344 get_proxy_spec() const { 00345 string result; 00346 00347 ProxiesByScheme::const_iterator si; 00348 for (si = _proxies_by_scheme.begin(); si != _proxies_by_scheme.end(); ++si) { 00349 const string &scheme = (*si).first; 00350 const Proxies &proxies = (*si).second; 00351 Proxies::const_iterator pi; 00352 for (pi = proxies.begin(); pi != proxies.end(); ++pi) { 00353 const URLSpec &url = (*pi); 00354 if (!result.empty()) { 00355 result += ";"; 00356 } 00357 if (!scheme.empty()) { 00358 result += scheme; 00359 result += "="; 00360 } 00361 if (url.empty()) { 00362 result += "DIRECT"; 00363 } else { 00364 result += url.get_url(); 00365 } 00366 } 00367 } 00368 00369 return result; 00370 } 00371 00372 //////////////////////////////////////////////////////////////////// 00373 // Function: HTTPClient::set_direct_host_spec 00374 // Access: Published 00375 // Description: Specifies the set of hosts that should be connected 00376 // to directly, without using a proxy. This is a 00377 // semicolon-separated list of hostnames that may 00378 // contain wildcard characters ("*"). 00379 //////////////////////////////////////////////////////////////////// 00380 void HTTPClient:: 00381 set_direct_host_spec(const string &direct_host_spec) { 00382 clear_direct_host(); 00383 00384 // Tokenize the string based on the semicolons. 00385 vector_string hosts; 00386 tokenize(direct_host_spec, hosts, ";"); 00387 00388 for (vector_string::const_iterator hi = hosts.begin(); 00389 hi != hosts.end(); 00390 ++hi) { 00391 string spec = trim_blanks(*hi); 00392 00393 // We should be careful to avoid adding any empty hostnames to the 00394 // list. In particular, we will get one empty hostname if the 00395 // direct_host_spec is empty. 00396 if (!spec.empty()) { 00397 add_direct_host(spec); 00398 } 00399 } 00400 } 00401 00402 //////////////////////////////////////////////////////////////////// 00403 // Function: HTTPClient::get_direct_host_spec 00404 // Access: Published 00405 // Description: Returns the set of hosts that should be connected 00406 // to directly, without using a proxy, as a 00407 // semicolon-separated list of hostnames that may 00408 // contain wildcard characters ("*"). 00409 //////////////////////////////////////////////////////////////////// 00410 string HTTPClient:: 00411 get_direct_host_spec() const { 00412 string result; 00413 00414 DirectHosts::const_iterator si; 00415 for (si = _direct_hosts.begin(); si != _direct_hosts.end(); ++si) { 00416 const GlobPattern &host = (*si); 00417 00418 if (!result.empty()) { 00419 result += ";"; 00420 } 00421 result += host.get_pattern(); 00422 } 00423 00424 return result; 00425 } 00426 00427 //////////////////////////////////////////////////////////////////// 00428 // Function: HTTPClient::clear_proxy 00429 // Access: Published 00430 // Description: Resets the proxy spec to empty. Subsequent calls to 00431 // add_proxy() may be made to build up the set of proxy 00432 // servers. 00433 //////////////////////////////////////////////////////////////////// 00434 void HTTPClient:: 00435 clear_proxy() { 00436 _proxies_by_scheme.clear(); 00437 } 00438 00439 //////////////////////////////////////////////////////////////////// 00440 // Function: HTTPClient::add_proxy 00441 // Access: Published 00442 // Description: Adds the indicated proxy host as a proxy for 00443 // communications on the given scheme. Usually the 00444 // scheme is "http" or "https". It may be the empty 00445 // string to indicate a general proxy. The proxy string 00446 // may be the empty URL to indicate a direct connection. 00447 //////////////////////////////////////////////////////////////////// 00448 void HTTPClient:: 00449 add_proxy(const string &scheme, const URLSpec &proxy) { 00450 URLSpec proxy_url(proxy); 00451 00452 // The scheme is always converted to lowercase. 00453 string lc_scheme; 00454 lc_scheme.reserve(scheme.length()); 00455 string::const_iterator si; 00456 for (si = scheme.begin(); si != scheme.end(); ++si) { 00457 lc_scheme += tolower(*si); 00458 } 00459 00460 // Remove the trailing colon, if there is one. 00461 if (!lc_scheme.empty() && lc_scheme[lc_scheme.length() - 1] == ':') { 00462 lc_scheme = lc_scheme.substr(0, lc_scheme.length() - 1); 00463 } 00464 00465 if (!proxy_url.empty()) { 00466 // Enforce the scheme that we use to communicate to the proxy 00467 // itself. This is not the same as lc_scheme, which is the scheme 00468 // of the requested connection. Generally, all proxies speak 00469 // HTTP, except for Socks proxies. 00470 00471 if (lc_scheme == "socks") { 00472 // Scheme "socks" implies we talk to the proxy via the "socks" 00473 // scheme, no matter what scheme the user actually specified. 00474 proxy_url.set_scheme("socks"); 00475 00476 } else if (!proxy_url.has_scheme()) { 00477 // Otherwise, if the user didn't specify a scheme to talk to the 00478 // proxy, the default is "http". 00479 proxy_url.set_scheme("http"); 00480 } 00481 } 00482 00483 _proxies_by_scheme[lc_scheme].push_back(proxy_url); 00484 } 00485 00486 //////////////////////////////////////////////////////////////////// 00487 // Function: HTTPClient::clear_direct_host 00488 // Access: Published 00489 // Description: Resets the set of direct hosts to empty. Subsequent 00490 // calls to add_direct_host() may be made to build up 00491 // the list of hosts that do not require a proxy 00492 // connection. 00493 //////////////////////////////////////////////////////////////////// 00494 void HTTPClient:: 00495 clear_direct_host() { 00496 _direct_hosts.clear(); 00497 } 00498 00499 //////////////////////////////////////////////////////////////////// 00500 // Function: HTTPClient::add_direct_host 00501 // Access: Published 00502 // Description: Adds the indicated name to the set of hostnames that 00503 // are connected to directly, without using a proxy. 00504 // This name may be either a DNS name or an IP address, 00505 // and it may include the * as a wildcard character. 00506 //////////////////////////////////////////////////////////////////// 00507 void HTTPClient:: 00508 add_direct_host(const string &hostname) { 00509 // The hostname is always converted to lowercase. 00510 string lc_hostname; 00511 lc_hostname.reserve(hostname.length()); 00512 for (string::const_iterator si = hostname.begin(); 00513 si != hostname.end(); 00514 ++si) { 00515 lc_hostname += tolower(*si); 00516 } 00517 00518 _direct_hosts.push_back(GlobPattern(lc_hostname)); 00519 } 00520 00521 //////////////////////////////////////////////////////////////////// 00522 // Function: HTTPClient::get_proxies_for_url 00523 // Access: Published 00524 // Description: Fills up the indicated vector with the list of 00525 // URLSpec objects, in the order in which they should be 00526 // tried, that are appropriate proxies to try for the 00527 // indicated URL. The empty URL is returned for a 00528 // direct connection. 00529 // 00530 // It is the user's responsibility to empty this vector 00531 // before calling this method; otherwise, the proxy 00532 // URL's will simply be appended to the existing list. 00533 //////////////////////////////////////////////////////////////////// 00534 void HTTPClient:: 00535 get_proxies_for_url(const URLSpec &url, pvector<URLSpec> &proxies) const { 00536 // First, check if the hostname matches any listed in direct_hosts. 00537 string hostname = url.get_server(); 00538 00539 // If the hostname is empty, treat it as a special case: we don't 00540 // match any of the hostnames listed in direct_hosts (even "*"). 00541 if (!hostname.empty()) { 00542 DirectHosts::const_iterator si; 00543 for (si = _direct_hosts.begin(); si != _direct_hosts.end(); ++si) { 00544 if ((*si).matches(hostname)) { 00545 // It matches, so don't use any proxies. 00546 proxies.push_back(URLSpec()); 00547 return; 00548 } 00549 } 00550 } 00551 00552 // Build our list of proxies into a temporary vector, so we can pull 00553 // out duplicates later. 00554 pvector<URLSpec> temp_list; 00555 00556 // Now choose the appropriate proxy based on the scheme. 00557 string scheme = url.get_scheme(); 00558 bool got_any = false; 00559 00560 if (!scheme.empty()) { 00561 // If we have a scheme, try to match it. 00562 if (get_proxies_for_scheme(scheme, temp_list)) { 00563 got_any = true; 00564 } 00565 } 00566 00567 if (!got_any && (scheme.empty() || url.is_ssl())) { 00568 // An empty scheme (or an ssl-style scheme) implies we will need 00569 // to make a direct connection, so fallback to a socks-style 00570 // and/or https-style scheme. 00571 00572 if (get_proxies_for_scheme("socks", temp_list)) { 00573 got_any = true; 00574 } 00575 if (get_proxies_for_scheme("https", temp_list)) { 00576 got_any = true; 00577 } 00578 } 00579 00580 if (!got_any) { 00581 // If we didn't find our scheme of choice, fall back to the default 00582 // proxy type, if we've got one. 00583 if (get_proxies_for_scheme("", temp_list)) { 00584 got_any = true; 00585 } 00586 } 00587 00588 if (_try_all_direct) { 00589 // We may try a direct connection if all else fails. 00590 temp_list.push_back(URLSpec()); 00591 } 00592 00593 // Finally, as a very last resort, fall back to the HTTP proxy. 00594 if (!got_any) { 00595 get_proxies_for_scheme("http", temp_list); 00596 } 00597 00598 // Now remove duplicate entries as we copy the resulting list out. 00599 pvector<URLSpec>::iterator pi; 00600 pset<URLSpec> used; 00601 for (pi = temp_list.begin(); pi != temp_list.end(); ++pi) { 00602 if (used.insert(*pi).second) { 00603 // This is a unique one. 00604 proxies.push_back(*pi); 00605 } 00606 } 00607 } 00608 00609 //////////////////////////////////////////////////////////////////// 00610 // Function: HTTPClient::get_proxies_for_url 00611 // Access: Published 00612 // Description: Returns a semicolon-delimited list of proxies, in the 00613 // order in which they should be tried, that are 00614 // appropriate for the indicated URL. The keyword 00615 // DIRECT indicates a direct connection should be tried. 00616 //////////////////////////////////////////////////////////////////// 00617 string HTTPClient:: 00618 get_proxies_for_url(const URLSpec &url) const { 00619 pvector<URLSpec> proxies; 00620 get_proxies_for_url(url, proxies); 00621 00622 string result; 00623 if (!proxies.empty()) { 00624 pvector<URLSpec>::const_iterator pi = proxies.begin(); 00625 if ((*pi).get_url().empty()) { 00626 result += "DIRECT"; 00627 } else { 00628 result += (*pi).get_url(); 00629 } 00630 ++pi; 00631 00632 while (pi != proxies.end()) { 00633 result += ";"; 00634 if ((*pi).get_url().empty()) { 00635 result += "DIRECT"; 00636 } else { 00637 result += (*pi).get_url(); 00638 } 00639 ++pi; 00640 } 00641 } 00642 00643 return result; 00644 } 00645 00646 //////////////////////////////////////////////////////////////////// 00647 // Function: HTTPClient::set_username 00648 // Access: Published 00649 // Description: Specifies the username:password string corresponding 00650 // to a particular server and/or realm, when demanded by 00651 // the server. Either or both of the server or realm 00652 // may be empty; if so, they match anything. Also, the 00653 // server may be set to the special string "*proxy", 00654 // which will match any proxy server. 00655 // 00656 // If the username is set to the empty string, this 00657 // clears the password for the particular server/realm 00658 // pair. 00659 //////////////////////////////////////////////////////////////////// 00660 void HTTPClient:: 00661 set_username(const string &server, const string &realm, const string &username) { 00662 string key = server + ":" + realm; 00663 if (username.empty()) { 00664 _usernames.erase(key); 00665 } else { 00666 _usernames[key] = username; 00667 } 00668 } 00669 00670 //////////////////////////////////////////////////////////////////// 00671 // Function: HTTPClient::get_username 00672 // Access: Published 00673 // Description: Returns the username:password string set for this 00674 // server/realm pair, or empty string if nothing has 00675 // been set. See set_username(). 00676 //////////////////////////////////////////////////////////////////// 00677 string HTTPClient:: 00678 get_username(const string &server, const string &realm) const { 00679 string key = server + ":" + realm; 00680 Usernames::const_iterator ui; 00681 ui = _usernames.find(key); 00682 if (ui != _usernames.end()) { 00683 return (*ui).second; 00684 } 00685 return string(); 00686 } 00687 00688 //////////////////////////////////////////////////////////////////// 00689 // Function: HTTPClient::set_cookie 00690 // Access: Published 00691 // Description: Stores the indicated cookie in the client's list of 00692 // cookies, as if it had been received from a server. 00693 //////////////////////////////////////////////////////////////////// 00694 void HTTPClient:: 00695 set_cookie(const HTTPCookie &cookie) { 00696 if (cookie.is_expired()) { 00697 clear_cookie(cookie); 00698 00699 } else { 00700 pair<Cookies::iterator, bool> result = _cookies.insert(cookie); 00701 if (!result.second) { 00702 // We already had a cookie matching the supplied domain/path/name, 00703 // so replace it. 00704 const HTTPCookie &orig_cookie = *result.first; 00705 ((HTTPCookie &)orig_cookie).update_from(cookie); 00706 } 00707 } 00708 } 00709 00710 //////////////////////////////////////////////////////////////////// 00711 // Function: HTTPClient::clear_cookie 00712 // Access: Published 00713 // Description: Removes the cookie with the matching domain/path/name 00714 // from the client's list of cookies. Returns true if 00715 // it was removed, false if the cookie was not matched. 00716 //////////////////////////////////////////////////////////////////// 00717 bool HTTPClient:: 00718 clear_cookie(const HTTPCookie &cookie) { 00719 Cookies::iterator ci = _cookies.find(cookie); 00720 if (ci != _cookies.end()) { 00721 _cookies.erase(ci); 00722 return true; 00723 } 00724 00725 return false; 00726 } 00727 00728 //////////////////////////////////////////////////////////////////// 00729 // Function: HTTPClient::clear_all_cookies 00730 // Access: Published 00731 // Description: Removes the all stored cookies from the client. 00732 //////////////////////////////////////////////////////////////////// 00733 void HTTPClient:: 00734 clear_all_cookies() { 00735 _cookies.clear(); 00736 } 00737 00738 //////////////////////////////////////////////////////////////////// 00739 // Function: HTTPClient::has_cookie 00740 // Access: Published 00741 // Description: Returns true if there is a cookie in the client 00742 // matching the given cookie's domain/path/name, false 00743 // otherwise. 00744 //////////////////////////////////////////////////////////////////// 00745 bool HTTPClient:: 00746 has_cookie(const HTTPCookie &cookie) const { 00747 Cookies::const_iterator ci = _cookies.find(cookie); 00748 return (ci != _cookies.end()); 00749 } 00750 00751 //////////////////////////////////////////////////////////////////// 00752 // Function: HTTPClient::get_cookie 00753 // Access: Published 00754 // Description: Looks up and returns the cookie in the client 00755 // matching the given cookie's domain/path/name. If 00756 // there is no matching cookie, returns an empty cookie. 00757 //////////////////////////////////////////////////////////////////// 00758 HTTPCookie HTTPClient:: 00759 get_cookie(const HTTPCookie &cookie) const { 00760 Cookies::const_iterator ci = _cookies.find(cookie); 00761 if (ci != _cookies.end()) { 00762 return (*ci); 00763 } 00764 00765 return HTTPCookie(); 00766 } 00767 00768 //////////////////////////////////////////////////////////////////// 00769 // Function: HTTPClient::copy_cookies_from 00770 // Access: Published 00771 // Description: Copies all the cookies from the indicated HTTPClient 00772 // into this one. Existing cookies in this client are 00773 // not affected, unless they are shadowed by the new 00774 // cookies. 00775 //////////////////////////////////////////////////////////////////// 00776 void HTTPClient:: 00777 copy_cookies_from(const HTTPClient &other) { 00778 Cookies::const_iterator ci; 00779 for (ci = other._cookies.begin(); ci != other._cookies.end(); ++ci) { 00780 set_cookie(*ci); 00781 } 00782 } 00783 00784 //////////////////////////////////////////////////////////////////// 00785 // Function: HTTPClient::write_cookies 00786 // Access: Published 00787 // Description: Outputs the complete list of cookies stored on the 00788 // client, for all domains, including the expired 00789 // cookies (which will normally not be sent back to a 00790 // host). 00791 //////////////////////////////////////////////////////////////////// 00792 void HTTPClient:: 00793 write_cookies(ostream &out) const { 00794 Cookies::const_iterator ci; 00795 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) { 00796 out << *ci << "\n"; 00797 } 00798 } 00799 00800 //////////////////////////////////////////////////////////////////// 00801 // Function: HTTPClient::send_cookies 00802 // Access: Published 00803 // Description: Writes to the indicated ostream a "Cookie" header 00804 // line for sending the cookies appropriate to the 00805 // indicated URL along with an HTTP request. This also 00806 // removes expired cookies. 00807 //////////////////////////////////////////////////////////////////// 00808 void HTTPClient:: 00809 send_cookies(ostream &out, const URLSpec &url) { 00810 HTTPDate now = HTTPDate::now(); 00811 bool any_expired = false; 00812 bool first_cookie = true; 00813 00814 Cookies::const_iterator ci; 00815 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) { 00816 const HTTPCookie &cookie = (*ci); 00817 if (cookie.is_expired(now)) { 00818 any_expired = true; 00819 00820 } else if (cookie.matches_url(url)) { 00821 if (first_cookie) { 00822 out << "Cookie: "; 00823 first_cookie = false; 00824 } else { 00825 out << "; "; 00826 } 00827 out << cookie.get_name() << "=" << cookie.get_value(); 00828 } 00829 } 00830 00831 if (!first_cookie) { 00832 out << "\r\n"; 00833 } 00834 00835 if (any_expired) { 00836 Cookies new_cookies; 00837 Cookies::const_iterator ci; 00838 for (ci = _cookies.begin(); ci != _cookies.end(); ++ci) { 00839 const HTTPCookie &cookie = (*ci); 00840 if (!cookie.is_expired(now)) { 00841 new_cookies.insert(new_cookies.end(), cookie); 00842 } 00843 } 00844 _cookies.swap(new_cookies); 00845 } 00846 } 00847 00848 //////////////////////////////////////////////////////////////////// 00849 // Function: HTTPClient::load_client_certificate 00850 // Access: Published 00851 // Description: Attempts to load the certificate named by 00852 // set_client_certificate_filename() immediately, and 00853 // returns true if successful, false otherwise. 00854 // 00855 // Normally this need not be explicitly called, since it 00856 // will be called automatically if the server requests a 00857 // certificate, but it may be useful to determine ahead 00858 // of time if the certificate can be loaded correctly. 00859 //////////////////////////////////////////////////////////////////// 00860 bool HTTPClient:: 00861 load_client_certificate() { 00862 if (!_client_certificate_loaded) { 00863 _client_certificate_loaded = true; 00864 00865 if (!_client_certificate_filename.empty()) { 00866 _client_certificate_filename.set_text(); 00867 00868 // First, read the complete file into memory. 00869 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00870 00871 if (!vfs->read_file(_client_certificate_filename, 00872 _client_certificate_pem, true)) { 00873 // Could not find or read file. 00874 downloader_cat.warning() 00875 << "Could not read " << _client_certificate_filename << ".\n"; 00876 return false; 00877 } 00878 } 00879 00880 if (!_client_certificate_pem.empty()) { 00881 // Create an in-memory BIO to read the "file" from the memory 00882 // buffer, and call the low-level routines to read the 00883 // keys from the BIO. 00884 BIO *mbio = BIO_new_mem_buf((void *)_client_certificate_pem.data(), 00885 _client_certificate_pem.length()); 00886 00887 ERR_clear_error(); 00888 _client_certificate_priv = 00889 PEM_read_bio_PrivateKey(mbio, NULL, NULL, 00890 (char *)_client_certificate_passphrase.c_str()); 00891 00892 // Rewind the "file" to the beginning in order to read the public 00893 // key (which might appear first in the file). 00894 BIO_reset(mbio); 00895 00896 ERR_clear_error(); 00897 _client_certificate_pub = 00898 PEM_read_bio_X509(mbio, NULL, NULL, NULL); 00899 00900 BIO_free(mbio); 00901 00902 00903 NotifySeverity sev = NS_debug; 00904 string source = "memory"; 00905 if (!_client_certificate_filename.empty()) { 00906 // Only report status to "info" severity if we have read the 00907 // certificate from a file. If it came from an in-memory image, 00908 // a failure will presumably be handled by whoever set the 00909 // image. 00910 sev = NS_info; 00911 source = _client_certificate_filename; 00912 } 00913 00914 if (downloader_cat.is_on(sev)) { 00915 if (_client_certificate_priv != (EVP_PKEY *)NULL && 00916 _client_certificate_pub != (X509 *)NULL) { 00917 downloader_cat.out(sev) 00918 << "Read client certificate from " << source << "\n"; 00919 00920 } else { 00921 if (_client_certificate_priv == (EVP_PKEY *)NULL) { 00922 downloader_cat.out(sev) 00923 << "Could not read private key from " << source << "\n"; 00924 } 00925 00926 if (_client_certificate_pub == (X509 *)NULL) { 00927 downloader_cat.out(sev) 00928 << "Could not read public key from " << source << "\n"; 00929 } 00930 } 00931 } 00932 } 00933 } 00934 00935 return (_client_certificate_priv != (EVP_PKEY *)NULL && 00936 _client_certificate_pub != (X509 *)NULL); 00937 } 00938 00939 //////////////////////////////////////////////////////////////////// 00940 // Function: HTTPClient::add_preapproved_server_certificate_filename 00941 // Access: Published 00942 // Description: Adds the certificate defined in the indicated PEM 00943 // filename as a "pre-approved" certificate for the 00944 // indicated server, defined by the hostname and port 00945 // (only) from the given URL. 00946 // 00947 // If the server offers this particular certificate on a 00948 // secure connection, it will be accepted without 00949 // question. This is particularly useful for 00950 // communicating with a server using a known self-signed 00951 // certificate. 00952 // 00953 // See also the similar 00954 // add_preapproved_server_certificate_pem(), and the 00955 // weaker add_preapproved_server_certificate_name(). 00956 //////////////////////////////////////////////////////////////////// 00957 bool HTTPClient:: 00958 add_preapproved_server_certificate_filename(const URLSpec &url, const Filename &filename) { 00959 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00960 string pem; 00961 00962 if (!vfs->read_file(filename, pem, true)) { 00963 // Could not find or read file. 00964 downloader_cat.warning() 00965 << "Could not read " << filename << ".\n"; 00966 return false; 00967 } 00968 00969 return add_preapproved_server_certificate_pem(url, pem); 00970 } 00971 00972 //////////////////////////////////////////////////////////////////// 00973 // Function: HTTPClient::add_preapproved_server_certificate_pem 00974 // Access: Published 00975 // Description: Adds the certificate defined in the indicated data 00976 // string, formatted as a PEM block, as a "pre-approved" 00977 // certificate for the indicated server, defined by the 00978 // hostname and port (only) from the given URL. 00979 // 00980 // If the server offers this particular certificate on a 00981 // secure connection, it will be accepted without 00982 // question. This is particularly useful for 00983 // communicating with a server using a known self-signed 00984 // certificate. 00985 // 00986 // See also the similar 00987 // add_preapproved_server_certificate_filename(), and 00988 // the weaker add_preapproved_server_certificate_name(). 00989 //////////////////////////////////////////////////////////////////// 00990 bool HTTPClient:: 00991 add_preapproved_server_certificate_pem(const URLSpec &url, const string &pem) { 00992 // Create an in-memory BIO to read the "file" from the memory 00993 // buffer, and call the low-level routine to read the 00994 // cert from the BIO. 00995 BIO *mbio = BIO_new_mem_buf((void *)pem.data(), pem.length()); 00996 00997 ERR_clear_error(); 00998 X509 *cert = PEM_read_bio_X509(mbio, NULL, NULL, NULL); 00999 BIO_free(mbio); 01000 01001 if (cert == NULL) { 01002 downloader_cat.warning() 01003 << "Could not parse PEM data\n"; 01004 return false; 01005 } 01006 01007 string server_and_port = url.get_server_and_port(); 01008 PreapprovedServerCerts::iterator psci = 01009 _preapproved_server_certs.insert(PreapprovedServerCerts::value_type(server_and_port, PreapprovedServerCert())).first; 01010 01011 PreapprovedServerCert &psc = (*psci).second; 01012 psc._certs.push_back(cert); 01013 01014 return true; 01015 } 01016 01017 //////////////////////////////////////////////////////////////////// 01018 // Function: HTTPClient::add_preapproved_server_certificate_name 01019 // Access: Published 01020 // Description: Adds the certificate *name* only, as a "pre-approved" 01021 // certificate name for the indicated server, defined by 01022 // the hostname and port (only) from the given URL. 01023 // 01024 // This is a weaker function than 01025 // add_preapproved_server_certificate_filename(). This 01026 // checks only the subject name of the certificate, 01027 // without checking for a particular certificate by key. 01028 // This means that a variety of server certificates may 01029 // match the indicated name. 01030 // 01031 // Because this is a weaker verification, it only 01032 // applies to server certificates that are signed by a 01033 // recognized certificate authority. Thus, it cannot be 01034 // used to pre-approve self-signed certificates, but it 01035 // can be used to accept a server certificate offered by 01036 // a different hostname than the one in the cert itself. 01037 // 01038 // The certificate name should be formatted in the form 01039 // /type0=value0/type1=value1/type2=... 01040 //////////////////////////////////////////////////////////////////// 01041 bool HTTPClient:: 01042 add_preapproved_server_certificate_name(const URLSpec &url, const string &name) { 01043 X509_NAME *cert_name = parse_x509_name(name); 01044 if (cert_name == NULL) { 01045 downloader_cat.warning() 01046 << "Could not parse certificate name " << name << "\n"; 01047 return false; 01048 } 01049 01050 string server_and_port = url.get_server_and_port(); 01051 PreapprovedServerCerts::iterator psci = 01052 _preapproved_server_certs.insert(PreapprovedServerCerts::value_type(server_and_port, PreapprovedServerCert())).first; 01053 01054 PreapprovedServerCert &psc = (*psci).second; 01055 psc._cert_names.push_back(cert_name); 01056 01057 return true; 01058 } 01059 01060 //////////////////////////////////////////////////////////////////// 01061 // Function: HTTPClient::clear_preapproved_server_certificates 01062 // Access: Published 01063 // Description: Removes all preapproved server certificates for the 01064 // indicated server and port. 01065 //////////////////////////////////////////////////////////////////// 01066 void HTTPClient:: 01067 clear_preapproved_server_certificates(const URLSpec &url) { 01068 string server_and_port = url.get_server_and_port(); 01069 _preapproved_server_certs.erase(server_and_port); 01070 } 01071 01072 //////////////////////////////////////////////////////////////////// 01073 // Function: HTTPClient::clear_all_preapproved_server_certificates 01074 // Access: Published 01075 // Description: Removes all preapproved server certificates for all 01076 // servers. 01077 //////////////////////////////////////////////////////////////////// 01078 void HTTPClient:: 01079 clear_all_preapproved_server_certificates() { 01080 _preapproved_server_certs.clear(); 01081 } 01082 01083 //////////////////////////////////////////////////////////////////// 01084 // Function: HTTPClient::get_http_version_string 01085 // Access: Published 01086 // Description: Returns the current HTTP version setting as a string, 01087 // e.g. "HTTP/1.0" or "HTTP/1.1". 01088 //////////////////////////////////////////////////////////////////// 01089 string HTTPClient:: 01090 get_http_version_string() const { 01091 switch (_http_version) { 01092 case HTTPEnum::HV_09: 01093 return "HTTP/0.9"; 01094 01095 case HTTPEnum::HV_10: 01096 return "HTTP/1.0"; 01097 01098 case HTTPEnum::HV_11: 01099 return "HTTP/1.1"; 01100 01101 case HTTPEnum::HV_other: 01102 // Report the best we can do. 01103 return "HTTP/1.1"; 01104 } 01105 01106 return "unknown"; 01107 } 01108 01109 //////////////////////////////////////////////////////////////////// 01110 // Function: HTTPClient::parse_http_version_string 01111 // Access: Published 01112 // Description: Matches the string representing a particular HTTP 01113 // version against any of the known versions and returns 01114 // the appropriate enumerated value, or HV_other if the 01115 // version is unknown. 01116 //////////////////////////////////////////////////////////////////// 01117 HTTPEnum::HTTPVersion HTTPClient:: 01118 parse_http_version_string(const string &version) { 01119 if (version == "HTTP/1.0") { 01120 return HTTPEnum::HV_10; 01121 } else if (version == "HTTP/1.1") { 01122 return HTTPEnum::HV_11; 01123 } else if (version.substr(0, 6) == "HTTP/0") { 01124 return HTTPEnum::HV_09; 01125 } else { 01126 return HTTPEnum::HV_other; 01127 } 01128 } 01129 01130 //////////////////////////////////////////////////////////////////// 01131 // Function: HTTPClient::load_certificates 01132 // Access: Published 01133 // Description: Reads the certificate(s) (delimited by -----BEGIN 01134 // CERTIFICATE----- and -----END CERTIFICATE-----) from 01135 // the indicated file and makes them known as trusted 01136 // public keys for validating future connections. 01137 // Returns true on success, false otherwise. 01138 //////////////////////////////////////////////////////////////////// 01139 bool HTTPClient:: 01140 load_certificates(const Filename &filename) { 01141 OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr(); 01142 return (sslw->load_certificates(filename) != 0); 01143 } 01144 01145 //////////////////////////////////////////////////////////////////// 01146 // Function: HTTPClient::make_channel 01147 // Access: Published 01148 // Description: Returns a new HTTPChannel object that may be used 01149 // for reading multiple documents using the same 01150 // connection, for greater network efficiency than 01151 // calling HTTPClient::get_document() repeatedly (which 01152 // would force a new connection for each document). 01153 // 01154 // Also, HTTPChannel has some additional, less common 01155 // interface methods than the basic interface methods 01156 // that exist on HTTPClient; if you wish to call any of 01157 // these methods you must first obtain an HTTPChannel. 01158 // 01159 // Pass true for persistent_connection to gain this 01160 // network efficiency. If, on the other hand, your 01161 // intention is to use the channel to retrieve only one 01162 // document, then pass false to inform the server that 01163 // we will be dropping the connection after the first 01164 // document. 01165 //////////////////////////////////////////////////////////////////// 01166 PT(HTTPChannel) HTTPClient:: 01167 make_channel(bool persistent_connection) { 01168 PT(HTTPChannel) doc = new HTTPChannel(this); 01169 doc->set_persistent_connection(persistent_connection); 01170 return doc; 01171 } 01172 01173 //////////////////////////////////////////////////////////////////// 01174 // Function: HTTPClient::post_form 01175 // Access: Published 01176 // Description: Posts form data to a particular URL and retrieves the 01177 // response. Returns a new HTTPChannel object whether 01178 // the document is successfully read or not; you can 01179 // test is_valid() and get_return_code() to determine 01180 // whether the document was retrieved. 01181 //////////////////////////////////////////////////////////////////// 01182 PT(HTTPChannel) HTTPClient:: 01183 post_form(const URLSpec &url, const string &body) { 01184 PT(HTTPChannel) doc = new HTTPChannel(this); 01185 doc->post_form(url, body); 01186 return doc; 01187 } 01188 01189 //////////////////////////////////////////////////////////////////// 01190 // Function: HTTPClient::get_document 01191 // Access: Published 01192 // Description: Opens the named document for reading. Returns a new 01193 // HTTPChannel object whether the document is 01194 // successfully read or not; you can test is_valid() and 01195 // get_return_code() to determine whether the document 01196 // was retrieved. 01197 //////////////////////////////////////////////////////////////////// 01198 PT(HTTPChannel) HTTPClient:: 01199 get_document(const URLSpec &url) { 01200 PT(HTTPChannel) doc = new HTTPChannel(this); 01201 doc->get_document(url); 01202 return doc; 01203 } 01204 01205 //////////////////////////////////////////////////////////////////// 01206 // Function: HTTPClient::get_header 01207 // Access: Published 01208 // Description: Like get_document(), except only the header 01209 // associated with the document is retrieved. This may 01210 // be used to test for existence of the document; it 01211 // might also return the size of the document (if the 01212 // server gives us this information). 01213 //////////////////////////////////////////////////////////////////// 01214 PT(HTTPChannel) HTTPClient:: 01215 get_header(const URLSpec &url) { 01216 PT(HTTPChannel) doc = new HTTPChannel(this); 01217 doc->get_header(url); 01218 return doc; 01219 } 01220 01221 //////////////////////////////////////////////////////////////////// 01222 // Function: HTTPClient::get_global_ptr 01223 // Access: Published, Static 01224 // Description: Returns the default global HTTPClient. 01225 //////////////////////////////////////////////////////////////////// 01226 HTTPClient *HTTPClient:: 01227 get_global_ptr() { 01228 if (_global_ptr == NULL) { 01229 _global_ptr = new HTTPClient; 01230 } 01231 return _global_ptr; 01232 } 01233 01234 01235 //////////////////////////////////////////////////////////////////// 01236 // Function: HTTPClient::get_ssl_ctx 01237 // Access: Public 01238 // Description: Returns the OpenSSL context object, creating it first 01239 // if needed. 01240 //////////////////////////////////////////////////////////////////// 01241 SSL_CTX *HTTPClient:: 01242 get_ssl_ctx() { 01243 if (_ssl_ctx != (SSL_CTX *)NULL) { 01244 return _ssl_ctx; 01245 } 01246 01247 init_random_seed(); 01248 01249 _ssl_ctx = SSL_CTX_new(SSLv23_client_method()); 01250 01251 #if defined(SSL_097) && !defined(NDEBUG) 01252 // If we have debugging enabled, set a callback that allows us to 01253 // report the SSL messages as they are sent and received. 01254 if (downloader_cat.is_debug()) { 01255 SSL_CTX_set_msg_callback(_ssl_ctx, ssl_msg_callback); 01256 } 01257 #endif 01258 01259 // Make sure the error strings are loaded. 01260 OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr(); 01261 sslw->notify_ssl_errors(); 01262 01263 SSL_CTX_set_cert_store(_ssl_ctx, sslw->get_x509_store()); 01264 01265 return _ssl_ctx; 01266 } 01267 01268 //////////////////////////////////////////////////////////////////// 01269 // Function: HTTPClient::check_preapproved_server_certificate 01270 // Access: Private 01271 // Description: Checks to see if the indicated certificate is on the 01272 // pre-approved list for the indicated server's URL. 01273 // 01274 // If the full cert itself (including its key) is on the 01275 // pre-approved list, sets both cert_preapproved and 01276 // cert_name_preapproved to true. 01277 // 01278 // If the full cert is not on the pre-approved list, but 01279 // its name matches a name on the pre-approved list, 01280 // sets cert_name_preapproved to true, and 01281 // cert_preapproved to false. 01282 // 01283 // Otherwise, sets both values to false. This doesn't 01284 // mean the cert is necessarily invalid, just that it 01285 // wasn't on the pre-approved list (which is usually 01286 // empty anyway). 01287 //////////////////////////////////////////////////////////////////// 01288 void HTTPClient:: 01289 check_preapproved_server_certificate(const URLSpec &url, X509 *cert, 01290 bool &cert_preapproved, bool &cert_name_preapproved) const { 01291 cert_preapproved = false; 01292 cert_name_preapproved = false; 01293 01294 string server_and_port = url.get_server_and_port(); 01295 PreapprovedServerCerts::const_iterator psci = 01296 _preapproved_server_certs.find(server_and_port); 01297 01298 if (psci == _preapproved_server_certs.end()) { 01299 // No preapproved certs defined for this server. 01300 return; 01301 } 01302 01303 const PreapprovedServerCert &psc = (*psci).second; 01304 01305 // See if we have an exact match on the cert itself. 01306 ServerCerts::const_iterator sci; 01307 for (sci = psc._certs.begin(); sci != psc._certs.end(); ++sci) { 01308 if (X509_cmp(cert, *sci) == 0) { 01309 cert_preapproved = true; 01310 cert_name_preapproved = true; 01311 downloader_cat.info() 01312 << "Server certificate is pre-approved.\n"; 01313 return; 01314 } 01315 } 01316 01317 // OK, look for a match on the cert's name only. 01318 X509_NAME *subject = X509_get_subject_name(cert); 01319 ServerCertNames::const_iterator scni; 01320 for (scni = psc._cert_names.begin(); scni != psc._cert_names.end(); ++scni) { 01321 X509_NAME *cert_name = (*scni); 01322 if (x509_name_subset(cert_name, subject)) { 01323 downloader_cat.info() 01324 << "Server certificate name is pre-approved.\n"; 01325 cert_name_preapproved = true; 01326 return; 01327 } 01328 } 01329 01330 // Didn't find any match. 01331 return; 01332 } 01333 01334 //////////////////////////////////////////////////////////////////// 01335 // Function: HTTPClient::get_proxies_for_scheme 01336 // Access: Private 01337 // Description: Adds the proxy servers associated with the indicated 01338 // scheme, if any, to the list. Returns true if any 01339 // were added, false otherwise. 01340 //////////////////////////////////////////////////////////////////// 01341 bool HTTPClient:: 01342 get_proxies_for_scheme(const string &scheme, pvector<URLSpec> &proxies) const { 01343 ProxiesByScheme::const_iterator si = _proxies_by_scheme.find(scheme); 01344 if (si == _proxies_by_scheme.end()) { 01345 return false; 01346 } 01347 const Proxies &scheme_proxies = (*si).second; 01348 if (scheme_proxies.empty()) { 01349 return false; 01350 } 01351 01352 Proxies::const_iterator pi; 01353 for (pi = scheme_proxies.begin(); pi != scheme_proxies.end(); ++pi) { 01354 proxies.push_back(*pi); 01355 } 01356 01357 return true; 01358 } 01359 01360 //////////////////////////////////////////////////////////////////// 01361 // Function: HTTPClient::add_http_username 01362 // Access: Private 01363 // Description: Handles a Config definition for http-username as 01364 // server:realm:username:password, where either or both 01365 // of server and realm may be empty, or just 01366 // server:username:password or username:password. 01367 //////////////////////////////////////////////////////////////////// 01368 void HTTPClient:: 01369 add_http_username(const string &http_username) { 01370 size_t c1 = http_username.find(':'); 01371 if (c1 != string::npos) { 01372 size_t c2 = http_username.find(':', c1 + 1); 01373 if (c2 != string::npos) { 01374 size_t c3 = http_username.find(':', c2 + 1); 01375 if (c3 != string::npos) { 01376 size_t c4 = http_username.find(':', c3 + 1); 01377 if (c4 != string::npos) { 01378 // Oops, we have five? Problem. 01379 downloader_cat.error() 01380 << "Invalid http-username " << http_username << "\n"; 01381 01382 } else { 01383 // Ok, we have four. 01384 set_username(http_username.substr(0, c1), 01385 http_username.substr(c1 + 1, c2 - (c1 + 1)), 01386 http_username.substr(c2 + 1)); 01387 } 01388 01389 } else { 01390 // We have only three. 01391 set_username(string(), 01392 http_username.substr(0, c1), 01393 http_username.substr(c1 + 1)); 01394 } 01395 } else { 01396 // We have only two. 01397 set_username(string(), string(), http_username); 01398 } 01399 } else { 01400 // We have only one? Problem. 01401 downloader_cat.error() 01402 << "Invalid http-username " << http_username << "\n"; 01403 } 01404 } 01405 01406 //////////////////////////////////////////////////////////////////// 01407 // Function: HTTPClient::select_username 01408 // Access: Private 01409 // Description: Chooses a suitable username:password string for the 01410 // given URL and realm. 01411 //////////////////////////////////////////////////////////////////// 01412 string HTTPClient:: 01413 select_username(const URLSpec &url, bool is_proxy, const string &realm) const { 01414 string username; 01415 01416 // Look in several places in order to find the matching username. 01417 01418 // Fist, if there's a username on the URL, that always wins (except 01419 // when we are looking for a proxy username). 01420 if (url.has_username() && !is_proxy) { 01421 username = url.get_username(); 01422 } 01423 01424 // Otherwise, start looking on the HTTPClient. 01425 if (is_proxy) { 01426 if (username.empty()) { 01427 // Try the *proxy/realm. 01428 username = get_username("*proxy", realm); 01429 } 01430 if (username.empty()) { 01431 // Then, try *proxy/any realm. 01432 username = get_username("*proxy", string()); 01433 } 01434 } 01435 if (username.empty()) { 01436 // Try the specific server/realm. 01437 username = get_username(url.get_server(), realm); 01438 } 01439 if (username.empty()) { 01440 // Then, try the specific server/any realm. 01441 username = get_username(url.get_server(), string()); 01442 } 01443 if (username.empty()) { 01444 // Then, try any server with this realm. 01445 username = get_username(string(), realm); 01446 } 01447 if (username.empty()) { 01448 // Then, take the general password. 01449 username = get_username(string(), string()); 01450 } 01451 01452 return username; 01453 } 01454 01455 //////////////////////////////////////////////////////////////////// 01456 // Function: HTTPClient::select_auth 01457 // Access: Private 01458 // Description: Chooses a suitable pre-computed authorization for the 01459 // indicated URL. Returns NULL if no authorization 01460 // matches. 01461 //////////////////////////////////////////////////////////////////// 01462 HTTPAuthorization *HTTPClient:: 01463 select_auth(const URLSpec &url, bool is_proxy, const string &last_realm) { 01464 Domains &domains = is_proxy ? _proxy_domains : _www_domains; 01465 string canon = HTTPAuthorization::get_canonical_url(url).get_url(); 01466 01467 // Look for the longest domain string that is a prefix of our 01468 // canonical URL. We have to make a linear scan through the list. 01469 Domains::const_iterator best_di = domains.end(); 01470 size_t longest_length = 0; 01471 Domains::const_iterator di; 01472 for (di = domains.begin(); di != domains.end(); ++di) { 01473 const string &domain = (*di).first; 01474 size_t length = domain.length(); 01475 if (domain == canon.substr(0, length)) { 01476 // This domain string matches. Is it the longest? 01477 if (length > longest_length) { 01478 best_di = di; 01479 longest_length = length; 01480 } 01481 } 01482 } 01483 01484 if (best_di != domains.end()) { 01485 // Ok, we found a matching domain. Use it. 01486 if (downloader_cat.is_spam()) { 01487 downloader_cat.spam() 01488 << "Choosing domain " << (*best_di).first << " for " << url << "\n"; 01489 } 01490 const Realms &realms = (*best_di).second._realms; 01491 // First, try our last realm. 01492 Realms::const_iterator ri; 01493 ri = realms.find(last_realm); 01494 if (ri != realms.end()) { 01495 return (*ri).second; 01496 } 01497 01498 if (!realms.empty()) { 01499 // Oh well, just return the first realm. 01500 return (*realms.begin()).second; 01501 } 01502 } 01503 01504 // No matching domains. 01505 return NULL; 01506 } 01507 01508 //////////////////////////////////////////////////////////////////// 01509 // Function: HTTPClient::generate_auth 01510 // Access: Private 01511 // Description: Generates a new authorization entry in response to a 01512 // 401 or 407 challenge from the server or proxy. The 01513 // new authorization entry is stored for future 01514 // connections to the same server (or, more precisely, 01515 // the same domain, which may be a subset of the server, 01516 // or it may include multiple servers). 01517 //////////////////////////////////////////////////////////////////// 01518 PT(HTTPAuthorization) HTTPClient:: 01519 generate_auth(const URLSpec &url, bool is_proxy, const string &challenge) { 01520 HTTPAuthorization::AuthenticationSchemes schemes; 01521 HTTPAuthorization::parse_authentication_schemes(schemes, challenge); 01522 01523 PT(HTTPAuthorization) auth; 01524 HTTPAuthorization::AuthenticationSchemes::iterator si; 01525 01526 si = schemes.find("digest"); 01527 if (si != schemes.end()) { 01528 auth = new HTTPDigestAuthorization((*si).second, url, is_proxy); 01529 } 01530 01531 if (auth == (HTTPAuthorization *)NULL || !auth->is_valid()) { 01532 si = schemes.find("basic"); 01533 if (si != schemes.end()) { 01534 auth = new HTTPBasicAuthorization((*si).second, url, is_proxy); 01535 } 01536 } 01537 01538 if (auth == (HTTPAuthorization *)NULL || !auth->is_valid()) { 01539 downloader_cat.warning() 01540 << "Don't know how to use any of the server's available authorization schemes:\n"; 01541 for (si = schemes.begin(); si != schemes.end(); ++si) { 01542 downloader_cat.warning() << (*si).first << "\n"; 01543 } 01544 01545 } else { 01546 // Now that we've got an authorization, store it under under each 01547 // of its suggested domains for future use. 01548 Domains &domains = is_proxy ? _proxy_domains : _www_domains; 01549 const vector_string &domain = auth->get_domain(); 01550 vector_string::const_iterator si; 01551 for (si = domain.begin(); si != domain.end(); ++si) { 01552 domains[(*si)]._realms[auth->get_realm()] = auth; 01553 } 01554 } 01555 01556 return auth; 01557 } 01558 01559 //////////////////////////////////////////////////////////////////// 01560 // Function: HTTPClient::unload_client_certificate 01561 // Access: Private 01562 // Description: Frees the resources allocated by a previous call to 01563 // load_client_certificate(), and marks the certificate 01564 // unloaded. 01565 //////////////////////////////////////////////////////////////////// 01566 void HTTPClient:: 01567 unload_client_certificate() { 01568 if (_client_certificate_priv != (EVP_PKEY *)NULL) { 01569 EVP_PKEY_free(_client_certificate_priv); 01570 _client_certificate_priv = NULL; 01571 } 01572 01573 if (_client_certificate_pub != (X509 *)NULL) { 01574 X509_free(_client_certificate_pub); 01575 _client_certificate_pub = NULL; 01576 } 01577 01578 _client_certificate_loaded = false; 01579 } 01580 01581 //////////////////////////////////////////////////////////////////// 01582 // Function: HTTPClient::parse_x509_name 01583 // Access: Private, Static 01584 // Description: Parses a string of the form 01585 // /type0=value0/type1=value1/type2=... into a newly 01586 // allocated X509_NAME object. Returns NULL if the 01587 // string is invalid. 01588 //////////////////////////////////////////////////////////////////// 01589 X509_NAME *HTTPClient:: 01590 parse_x509_name(const string &source) { 01591 X509_NAME *result = NULL; 01592 01593 result = X509_NAME_new(); 01594 bool added_any = false; 01595 01596 string::const_iterator si; 01597 si = source.begin(); 01598 while (si != source.end()) { 01599 if ((*si) == '/') { 01600 // Skip a slash delimiter. 01601 ++si; 01602 } else { 01603 string type; 01604 while (si != source.end() && (*si) != '=' && (*si) != '/') { 01605 if ((*si) == '\\') { 01606 ++si; 01607 if (si != source.end()) { 01608 type += (*si); 01609 ++si; 01610 } 01611 } else { 01612 type += (*si); 01613 ++si; 01614 } 01615 } 01616 01617 int nid = OBJ_txt2nid((char *)type.c_str()); 01618 if (nid == NID_undef) { 01619 downloader_cat.info() 01620 << "Unknown type " << type << " in X509 name: " << source 01621 << "\n"; 01622 X509_NAME_free(result); 01623 return NULL; 01624 } 01625 01626 string value; 01627 01628 if (si != source.end() && (*si) == '=') { 01629 ++si; 01630 while (si != source.end() && (*si) != '/') { 01631 if ((*si) == '\\') { 01632 ++si; 01633 if (si != source.end()) { 01634 value += (*si); 01635 ++si; 01636 } 01637 } else { 01638 value += (*si); 01639 ++si; 01640 } 01641 } 01642 } 01643 01644 if (!value.empty()) { 01645 int add_result = 01646 X509_NAME_add_entry_by_NID(result, nid, V_ASN1_APP_CHOOSE, 01647 (unsigned char *)value.c_str(), -1, -1, 0); 01648 if (!add_result) { 01649 downloader_cat.info() 01650 << "Unable to add " << type << "=" << value << " in X509 name: " 01651 << source << "\n"; 01652 X509_NAME_free(result); 01653 return NULL; 01654 } 01655 added_any = true; 01656 } 01657 } 01658 } 01659 01660 if (!added_any) { 01661 downloader_cat.info() 01662 << "Invalid empty X509 name: " << source << "\n"; 01663 X509_NAME_free(result); 01664 return NULL; 01665 } 01666 01667 return result; 01668 } 01669 01670 //////////////////////////////////////////////////////////////////// 01671 // Function: HTTPClient::x509_name_subset 01672 // Access: Private, Static 01673 // Description: Returns true if name_a is a subset of name_b: each 01674 // property of name_a is defined in name_b, and the 01675 // defined value is equivalent to that of name_a. 01676 //////////////////////////////////////////////////////////////////// 01677 bool HTTPClient:: 01678 x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) { 01679 int count_a = X509_NAME_entry_count(name_a); 01680 for (int ai = 0; ai < count_a; ai++) { 01681 X509_NAME_ENTRY *na = X509_NAME_get_entry(name_a, ai); 01682 01683 int bi = X509_NAME_get_index_by_OBJ(name_b, na->object, -1); 01684 if (bi < 0) { 01685 // This entry in name_a is not defined in name_b. 01686 return false; 01687 } 01688 01689 X509_NAME_ENTRY *nb = X509_NAME_get_entry(name_b, bi); 01690 if (na->value->length != nb->value->length || 01691 memcmp(na->value->data, nb->value->data, na->value->length) != 0) { 01692 // This entry in name_a doesn't match that of name_b. 01693 return false; 01694 } 01695 } 01696 return true; 01697 } 01698 01699 //////////////////////////////////////////////////////////////////// 01700 // Function: HTTPClient::split_whitespace 01701 // Access: Private, Static 01702 // Description: Puts the first word of c into a, and the remainder 01703 // into b. 01704 //////////////////////////////////////////////////////////////////// 01705 void HTTPClient:: 01706 split_whitespace(string &a, string &b, const string &c) { 01707 size_t p = 0; 01708 01709 // Skip initial whitespace 01710 while (p < c.length() && isspace(c[p])) { 01711 ++p; 01712 } 01713 01714 // Find the length of the first word 01715 size_t q = p; 01716 while (p < c.length() && !isspace(c[p])) { 01717 ++p; 01718 } 01719 01720 a = c.substr(q, p - q); 01721 01722 // Skip whitespace between words 01723 while (p < c.length() && isspace(c[p])) { 01724 ++p; 01725 } 01726 b = c.substr(p); 01727 } 01728 01729 #if defined(SSL_097) && !defined(NDEBUG) 01730 //////////////////////////////////////////////////////////////////// 01731 // Function: HTTPClient::ssl_msg_callback 01732 // Access: Private, Static 01733 // Description: This method is attached as a callback for SSL 01734 // messages only when debug output is enabled. 01735 //////////////////////////////////////////////////////////////////// 01736 void HTTPClient:: 01737 ssl_msg_callback(int write_p, int version, int content_type, 01738 const void *, size_t len, SSL *, void *) { 01739 ostringstream describe; 01740 if (write_p) { 01741 describe << "sent "; 01742 } else { 01743 describe << "received "; 01744 } 01745 switch (version) { 01746 case SSL2_VERSION: 01747 describe << "SSL 2.0 "; 01748 break; 01749 01750 case SSL3_VERSION: 01751 describe << "SSL 3.0 "; 01752 break; 01753 01754 case TLS1_VERSION: 01755 describe << "TLS 1.0 "; 01756 break; 01757 01758 default: 01759 describe << "unknown protocol "; 01760 } 01761 01762 describe << "message: "; 01763 01764 if (version != SSL2_VERSION) { 01765 switch (content_type) { 01766 case 20: 01767 describe << "change cipher spec, "; 01768 break; 01769 01770 case 21: 01771 describe << "alert, "; 01772 break; 01773 01774 case 22: 01775 describe << "handshake, "; 01776 break; 01777 01778 case 23: 01779 describe << "application data, "; 01780 break; 01781 01782 default: 01783 describe << "unknown content type, "; 01784 } 01785 } 01786 01787 describe << len << " bytes.\n"; 01788 01789 downloader_cat.debug() << describe.str(); 01790 } 01791 #endif // defined(SSL_097) && !defined(NDEBUG) 01792 01793 //////////////////////////////////////////////////////////////////// 01794 // Function: HTTPClient::PreapprovedServerCert::Destructor 01795 // Access: Public 01796 // Description: 01797 //////////////////////////////////////////////////////////////////// 01798 HTTPClient::PreapprovedServerCert:: 01799 ~PreapprovedServerCert() { 01800 ServerCerts::const_iterator sci; 01801 for (sci = _certs.begin(); sci != _certs.end(); ++sci) { 01802 X509_free(*sci); 01803 } 01804 01805 ServerCertNames::const_iterator scni; 01806 for (scni = _cert_names.begin(); scni != _cert_names.end(); ++scni) { 01807 X509_NAME_free(*scni); 01808 } 01809 } 01810 01811 #endif // HAVE_OPENSSL