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 |