| OLD | NEW |
| (Empty) |
| 1 // Copyright 2007-2010 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 | |
| 16 // TODO(omaha): might need to remove dependency on winhttp.h when implementing | |
| 17 // support for wininet; see http://b/1119232 | |
| 18 | |
| 19 #ifndef OMAHA_NET_NETWORK_CONFIG_H__ | |
| 20 #define OMAHA_NET_NETWORK_CONFIG_H__ | |
| 21 | |
| 22 #include <windows.h> | |
| 23 #include <winhttp.h> | |
| 24 #include <atlstr.h> | |
| 25 #include <map> | |
| 26 #include <vector> | |
| 27 #include "base/basictypes.h" | |
| 28 #include "base/scoped_ptr.h" | |
| 29 #include "omaha/base/scoped_any.h" | |
| 30 #include "omaha/base/synchronized.h" | |
| 31 #include "omaha/net/detector.h" | |
| 32 #include "omaha/net/http_client.h" | |
| 33 #include "omaha/net/proxy_auth.h" | |
| 34 | |
| 35 namespace ATL { | |
| 36 | |
| 37 class CSecurityDesc; | |
| 38 | |
| 39 } // namespace ATL | |
| 40 | |
| 41 namespace omaha { | |
| 42 | |
| 43 class RegKey; | |
| 44 | |
| 45 // The cup credentials are persisted across sessions. The sk is encrypted | |
| 46 // while on the disk so only a user with the same login credentials as | |
| 47 // the encryptor can decrypt it. The credentials are protected | |
| 48 // using the system default security, so users can't modify each other's | |
| 49 // credentials. In case of elevated administrators, the credentials are | |
| 50 // protected from the non-elevated administrators, so the latter can't | |
| 51 // read the keys and attack the elevated administrator. | |
| 52 // | |
| 53 // Cup credentials can be negotiated using either production keys or | |
| 54 // test keys. There is a registry value override to specify that test keys | |
| 55 // be used. For the change to be effective, the old credentials must be cleared. | |
| 56 struct CupCredentials { | |
| 57 std::vector<uint8> sk; // shared key (sk) | |
| 58 CStringA c; // client cookie (c) | |
| 59 }; | |
| 60 | |
| 61 // There are three ways by which an application could connect to the Internet: | |
| 62 // 1. Direct connection. | |
| 63 // The config for the direction connection must not specify WPAD information | |
| 64 // nor named proxy information. | |
| 65 // 2. Named proxy. | |
| 66 // The config for named proxy only includes proxy and proxy_bypass. | |
| 67 // 3. Proxy auto detection. | |
| 68 // The config for proxy auto detection should include either the auto-detect | |
| 69 // flag or the auto configuration url. Named proxy information is discarded | |
| 70 // if present. | |
| 71 struct ProxyConfig { | |
| 72 ProxyConfig() : auto_detect(false), priority(PROXY_PRIORITY_DEFAULT_NORMAL) {} | |
| 73 | |
| 74 // Used to uniquely identify a proxy. | |
| 75 CString source; | |
| 76 | |
| 77 // Specifies the configuration is WPAD. | |
| 78 bool auto_detect; | |
| 79 | |
| 80 // The url of the proxy configuration script, if known. | |
| 81 CString auto_config_url; | |
| 82 | |
| 83 // Named proxy information. | |
| 84 // The proxy string is usually something as "http=foo:80;https=bar:8080". | |
| 85 // According to the documentation for WINHTTP_PROXY_INFO, multiple proxies | |
| 86 // are separated by semicolons or whitespace. The documentation for | |
| 87 // IBackgroundCopyJob::SetProxySettings says that the list is | |
| 88 // space-delimited. | |
| 89 // TODO(omaha): our proxy information is semicolon-separated. This may | |
| 90 // result in compatibility problems with BITS. Fix this. | |
| 91 CString proxy; | |
| 92 CString proxy_bypass; | |
| 93 | |
| 94 // Suggested priority of the proxy config. When establishing network | |
| 95 // connections, it is a good idea to try higher priority proxy first. | |
| 96 enum Priority { | |
| 97 PROXY_PRIORITY_DEFAULT_NORMAL = 0, | |
| 98 PROXY_PRIORITY_DEFAULT_BROWSER = 1, | |
| 99 PROXY_PRIORITY_LAST_KNOWN_GOOD = 2, | |
| 100 PROXY_PRIORITY_OVERRIDE = 3, | |
| 101 } priority; | |
| 102 }; | |
| 103 | |
| 104 // Manages the network configurations. | |
| 105 class NetworkConfig { | |
| 106 public: | |
| 107 // Abstracts the Internet session, as provided by winhttp or wininet. | |
| 108 // A winhttp session should map to one and only one identity. in other words, | |
| 109 // a winhttp session is used to manage the network traffic of a single | |
| 110 // authenticated user, or a group of anonymous users. | |
| 111 struct Session { | |
| 112 Session() : session_handle(NULL) {} | |
| 113 | |
| 114 HINTERNET session_handle; | |
| 115 }; | |
| 116 | |
| 117 // Hooks up a proxy detector. The class takes ownership of the detector. | |
| 118 void Add(ProxyDetectorInterface* detector); | |
| 119 | |
| 120 // Clears all detectors and configurations. It does not clear the session. | |
| 121 // TODO(omaha): rename to avoid the confusion that Clear clears the sessions | |
| 122 // as well. | |
| 123 void Clear(); | |
| 124 | |
| 125 // Detects the network configuration for each of the registered detectors. | |
| 126 HRESULT Detect(); | |
| 127 | |
| 128 // Detects the network configuration for the given source. | |
| 129 HRESULT Detect(const CString& proxy_source, ProxyConfig* config) const; | |
| 130 | |
| 131 static HRESULT ConfigFromIdentifier(const CString& id, ProxyConfig* config); | |
| 132 | |
| 133 static bool ProxySortPredicate(const ProxyConfig& config1, | |
| 134 const ProxyConfig& config2) { | |
| 135 return config1.priority > config2.priority; | |
| 136 } | |
| 137 | |
| 138 // Sort the proxy configs based on their priorities. Proxy with higher | |
| 139 // priority precedes that with lower priority. | |
| 140 static void SortProxies(std::vector<ProxyConfig>* configurations); | |
| 141 | |
| 142 void AppendLastKnownGoodProxyConfig( | |
| 143 std::vector<ProxyConfig>* configurations) const; | |
| 144 | |
| 145 // Adds static configurations (WPAD & direct) to current detected network | |
| 146 // configuration list. | |
| 147 static void AppendStaticProxyConfigs( | |
| 148 std::vector<ProxyConfig>* configurations); | |
| 149 | |
| 150 // Returns the detected configurations. | |
| 151 std::vector<ProxyConfig> GetConfigurations() const; | |
| 152 | |
| 153 // Gets the persisted CUP credentials. | |
| 154 HRESULT GetCupCredentials(CupCredentials* cup_credentials) const; | |
| 155 | |
| 156 // Saves the CUP credentials in persistent storage. If the parameter is null, | |
| 157 // it clears the credentials. | |
| 158 HRESULT SetCupCredentials(const CupCredentials* cup_credentials) const; | |
| 159 | |
| 160 // Prompts for credentials, or gets cached credentials if they exist. | |
| 161 bool GetProxyCredentials(bool allow_ui, | |
| 162 bool force_ui, | |
| 163 const CString& proxy_settings, | |
| 164 const ProxyAuthConfig& proxy_auth_config, | |
| 165 bool is_https, | |
| 166 CString* username, | |
| 167 CString* password, | |
| 168 uint32* auth_scheme); | |
| 169 | |
| 170 // Once a auth scheme has been verified against a proxy, this allows a client | |
| 171 // to record the auth scheme that was used and was successful, so it can be | |
| 172 // cached for future use within this process. | |
| 173 HRESULT SetProxyAuthScheme(const CString& proxy_settings, | |
| 174 bool is_https, | |
| 175 uint32 auth_scheme); | |
| 176 | |
| 177 // Runs the WPAD protocol to compute the proxy information to be used | |
| 178 // for the given url. The ProxyInfo pointer members must be freed using | |
| 179 // GlobalFree. | |
| 180 HRESULT GetProxyForUrl(const CString& url, | |
| 181 const CString& auto_config_url, | |
| 182 HttpClient::ProxyInfo* proxy_info); | |
| 183 | |
| 184 Session session() const { return session_; } | |
| 185 | |
| 186 // Returns the global configuration override if available. | |
| 187 HRESULT GetConfigurationOverride(ProxyConfig* configuration_override); | |
| 188 | |
| 189 // Sets the global configuration override. The function clears the existing | |
| 190 // configuration if the parameter is NULL. | |
| 191 void SetConfigurationOverride(const ProxyConfig* configuration_override); | |
| 192 | |
| 193 // True if the CUP test keys are being used to negotiate the CUP | |
| 194 // credentials. | |
| 195 bool static IsUsingCupTestKeys(); | |
| 196 | |
| 197 // Returns the prefix of the user agent string. | |
| 198 static CString GetUserAgent(); | |
| 199 | |
| 200 // Returns the MID value under UpdateDev. | |
| 201 static CString GetMID(); | |
| 202 | |
| 203 // Eliminates the redundant configurations, for example, if multiple | |
| 204 // direct connection or proxy auto-detect occur. | |
| 205 static void RemoveDuplicates(std::vector<ProxyConfig>*); | |
| 206 | |
| 207 // Saves/loads a proxy source and auto_detect information to the registry | |
| 208 // so that that proxy can be tried with high priority when establishing | |
| 209 // network connections later on. | |
| 210 static HRESULT SaveProxyConfig(const ProxyConfig& config); | |
| 211 HRESULT LoadProxyConfig(ProxyConfig* config) const; | |
| 212 | |
| 213 // Parses a network configuration string. The format of the string is: | |
| 214 // wpad=[false|true];script=script_url;proxy=host:port | |
| 215 // Ignores the names and the values it does not understand. | |
| 216 static ProxyConfig ParseNetConfig(const CString& net_config); | |
| 217 | |
| 218 // Serializes configurations for debugging purposes. | |
| 219 static CString ToString(const std::vector<ProxyConfig>& configurations); | |
| 220 static CString ToString(const ProxyConfig& configuration); | |
| 221 | |
| 222 static int GetAccessType(const ProxyConfig& config); | |
| 223 | |
| 224 // Returns s1 + delim + s2. Consider making it an utility function if | |
| 225 // more usage patterns are found. | |
| 226 static CString JoinStrings(const TCHAR* s1, | |
| 227 const TCHAR* s2, | |
| 228 const TCHAR* delim); | |
| 229 | |
| 230 // Uses jsproxy to use a PAC proxy configuration file stored on the local | |
| 231 // drive, instead of one sourced from WPAD. | |
| 232 static HRESULT GetProxyForUrlLocal(const CString& url, | |
| 233 const CString& path_to_pac_file, | |
| 234 HttpClient::ProxyInfo* proxy_info); | |
| 235 | |
| 236 private: | |
| 237 explicit NetworkConfig(bool is_machine); | |
| 238 ~NetworkConfig(); | |
| 239 | |
| 240 HRESULT Initialize(); | |
| 241 | |
| 242 // Configures the proxy auth credentials options. Called by Initialize(). | |
| 243 void ConfigureProxyAuth(); | |
| 244 | |
| 245 // Creates the proxy configuration registry key for the calling user | |
| 246 // identified by the token. | |
| 247 static HRESULT CreateProxyConfigRegKey(RegKey* key); | |
| 248 | |
| 249 // Converts a response string from a PAC script into an WinHTTP proxy | |
| 250 // descriptor struct. | |
| 251 static void ConvertPacResponseToProxyInfo(const CStringA& response, | |
| 252 HttpClient::ProxyInfo* proxy_info); | |
| 253 | |
| 254 static const TCHAR* const kUserAgent; | |
| 255 | |
| 256 static const TCHAR* const kRegKeyProxy; | |
| 257 static const TCHAR* const kRegValueSource; | |
| 258 | |
| 259 static const TCHAR* const kWPADIdentifier; | |
| 260 static const TCHAR* const kDirectConnectionIdentifier; | |
| 261 | |
| 262 bool is_machine_; // True if the instance is initialized for machine. | |
| 263 | |
| 264 std::vector<ProxyConfig> configurations_; | |
| 265 std::vector<ProxyDetectorInterface*> detectors_; | |
| 266 | |
| 267 // Synchronizes access to per-process instance data, which includes | |
| 268 // the detectors and configurations. | |
| 269 LLock lock_; | |
| 270 | |
| 271 bool is_initialized_; | |
| 272 | |
| 273 scoped_ptr<ProxyConfig> configuration_override_; | |
| 274 | |
| 275 Session session_; | |
| 276 scoped_ptr<HttpClient> http_client_; | |
| 277 | |
| 278 // Manages the proxy auth credentials. Typically a http client tries to | |
| 279 // use autologon via Negotiate/NTLM with a proxy server. If that fails, the | |
| 280 // Http client then calls GetProxyCredentials() on NetworkConfig. | |
| 281 // GetProxyCredentials() gets credentials by either prompting the user, or | |
| 282 // cached credentials. Then the http client tries again. Options are set via | |
| 283 // ConfigureProxyAuth(). | |
| 284 ProxyAuth proxy_auth_; | |
| 285 | |
| 286 friend class NetworkConfigManager; | |
| 287 DISALLOW_EVIL_CONSTRUCTORS(NetworkConfig); | |
| 288 }; | |
| 289 | |
| 290 class NetworkConfigManager { | |
| 291 public: | |
| 292 static NetworkConfigManager& Instance(); | |
| 293 static void DeleteInstance(); | |
| 294 | |
| 295 // Directs this singleton class to create machine or user instance. | |
| 296 static void set_is_machine(bool is_machine); | |
| 297 | |
| 298 HRESULT GetUserNetworkConfig(NetworkConfig** network_config); | |
| 299 | |
| 300 // Gets the persisted CUP credentials. | |
| 301 HRESULT GetCupCredentials(CupCredentials* cup_credentials); | |
| 302 | |
| 303 // Saves the CUP credentials in persistent storage. | |
| 304 HRESULT SetCupCredentials(const CupCredentials& cup_credentials); | |
| 305 | |
| 306 void ClearCupCredentials(); | |
| 307 | |
| 308 private: | |
| 309 explicit NetworkConfigManager(); | |
| 310 ~NetworkConfigManager(); | |
| 311 | |
| 312 static HRESULT CreateInstance(); | |
| 313 | |
| 314 void DeleteInstanceInternal(); | |
| 315 | |
| 316 HRESULT InitializeLock(); | |
| 317 HRESULT InitializeRegistryKey(); | |
| 318 | |
| 319 HRESULT CreateNetworkConfigInstance(NetworkConfig** network_config_ptr, | |
| 320 bool is_machine); | |
| 321 HRESULT LoadCupCredentialsFromRegistry(); | |
| 322 HRESULT SaveCupCredentialsToRegistry(); | |
| 323 | |
| 324 std::map<CString, NetworkConfig*> user_network_config_map_; | |
| 325 scoped_ptr<CupCredentials> cup_credentials_; | |
| 326 | |
| 327 LLock lock_; | |
| 328 | |
| 329 // Synchronizes access to CUP registry. | |
| 330 GLock global_lock_; | |
| 331 | |
| 332 // Registry sub key where network configuration is persisted. | |
| 333 static const TCHAR* const kNetworkSubkey; | |
| 334 | |
| 335 // Registry sub key where CUP configuration is persisted. | |
| 336 static const TCHAR* const kNetworkCupSubkey; | |
| 337 | |
| 338 // The secret key must be encrypted by the caller. This class does not do any | |
| 339 // encryption. | |
| 340 static const TCHAR* const kCupClientSecretKey; // CUP sk. | |
| 341 static const TCHAR* const kCupClientCookie; // CUP c. | |
| 342 | |
| 343 static const NetworkConfigManager* const kInvalidInstance; | |
| 344 static NetworkConfigManager* instance_; | |
| 345 static LLock instance_lock_; | |
| 346 static bool is_machine_; | |
| 347 | |
| 348 DISALLOW_EVIL_CONSTRUCTORS(NetworkConfigManager); | |
| 349 }; | |
| 350 | |
| 351 } // namespace omaha | |
| 352 | |
| 353 #endif // OMAHA_NET_NETWORK_CONFIG_H__ | |
| 354 | |
| OLD | NEW |