[Author: andreip]
[google-gears.git] / gears / base / common / security_model.cc
blobfb67612f6f6d8810d9d78897362b88a457e4d443
1 // Copyright 2006, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <algorithm>
27 #include <cctype>
28 #include <string>
29 #include "gears/base/common/security_model.h"
30 #include "gears/base/common/string_utils.h"
31 #include "gears/localserver/common/http_constants.h"
33 // TODO(mpcomplete): implement these.
34 #if BROWSER_NPAPI && defined(WIN32)
35 #define BROWSER_IE 1
36 #endif
38 #if BROWSER_IE
39 #include <windows.h>
40 #include <wininet.h>
41 #elif BROWSER_FF
42 #include <gecko_sdk/include/nsIURI.h>
43 #include "gears/base/common/common.h"
44 #include "gears/base/firefox/dom_utils.h"
45 #elif BROWSER_SAFARI
46 #include "gears/base/safari/browser_utils.h"
47 #include "gears/base/safari/scoped_cf.h"
48 #include "gears/base/safari/string_utils.h"
49 #endif
52 const char16* kUnknownDomain = STRING16(L"_null_.localdomain");
53 const char* kUnknownDomainAscii = "_null_.localdomain";
55 //------------------------------------------------------------------------------
56 // Init
57 //------------------------------------------------------------------------------
58 bool SecurityOrigin::Init(const char16 *full_url, const char16 *scheme,
59 const char16 *host, int port) {
60 assert(full_url && scheme && host); // file URLs pass 0 for 'port'
61 if (!full_url[0] || !scheme[0] || !host[0])
62 return false;
64 full_url_ = full_url;
65 scheme_ = scheme;
66 host_ = host;
67 port_ = port;
69 port_string_ = IntegerToString16(port_);
70 LowerString(scheme_);
71 LowerString(host_);
73 url_ = scheme_;
74 url_ += STRING16(L"://");
75 url_ += host;
76 if (!IsDefaultPort(scheme_, port_)) {
77 url_ += STRING16(L":");
78 url_ += port_string_;
81 initialized_ = true;
82 return true;
86 //------------------------------------------------------------------------------
87 // InitFromUrl
88 //------------------------------------------------------------------------------
89 bool SecurityOrigin::InitFromUrl(const char16 *full_url) {
90 initialized_ = false;
92 #if BROWSER_IE
93 URL_COMPONENTSW components = {0};
94 components.dwStructSize = sizeof(URL_COMPONENTSW);
95 components.dwHostNameLength = 1;
96 components.dwSchemeLength = 1;
97 if (!InternetCrackUrlW(full_url, 0, 0, &components)) {
98 return false;
101 // Expcilitly disallow urls with embedded username:passwords. These
102 // are disabled by default in IE such that InternetCrackUrl fails.
103 // To have consistent behavior, do the same for all browsers.
104 if (components.lpszUserName && components.dwUserNameLength) {
105 return false;
107 switch (components.nScheme) {
108 case INTERNET_SCHEME_HTTP:
109 case INTERNET_SCHEME_HTTPS: {
110 if (!components.lpszScheme || !components.lpszHostName) {
111 return false;
113 std::string16 scheme(components.lpszScheme, components.dwSchemeLength);
114 std::string16 host(components.lpszHostName, components.dwHostNameLength);
115 return Init(full_url, scheme.c_str(), host.c_str(), components.nPort);
117 case INTERNET_SCHEME_FILE:
118 return Init(full_url, HttpConstants::kFileScheme, kUnknownDomain, 0);
119 default:
120 return false;
123 #elif BROWSER_FF
124 nsCOMPtr<nsIURI> url_obj;
125 if (!DOMUtils::NewAbsoluteURI(full_url, getter_AddRefs(url_obj)))
126 return false;
128 // Expcilitly disallow urls with embedded username:passwords. These
129 // are disabled by default in IE such that InternetCrackUrl fails.
130 // To have consistent behavior, do the same for all browsers.
131 nsCString user_name;
132 url_obj->GetUsername(user_name);
133 if (user_name.Length() > 0)
134 return false;
136 enum SchemeType { kSchemeTypeHttp, kSchemeTypeHttps, kSchemeTypeFile };
137 const struct {
138 SchemeType scheme_type;
139 const char16 *scheme;
140 const char *schemeAscii;
141 int default_port;
142 } kSchemes [] = {
143 { kSchemeTypeHttp, HttpConstants::kHttpScheme,
144 HttpConstants::kHttpSchemeAscii, HttpConstants::kHttpDefaultPort },
145 { kSchemeTypeHttps, HttpConstants::kHttpsScheme,
146 HttpConstants::kHttpsSchemeAscii, HttpConstants::kHttpsDefaultPort },
147 { kSchemeTypeFile, HttpConstants::kFileScheme,
148 HttpConstants::kFileSchemeAscii, HttpConstants::kFileDefaultPort }
150 nsresult nr = NS_OK;
151 PRBool match = PR_FALSE;
152 size_t i = 0;
153 for (; i < ARRAYSIZE(kSchemes); ++i) {
154 nr = url_obj->SchemeIs(kSchemes[i].schemeAscii, &match);
155 if (NS_FAILED(nr)) { return false; }
156 if (match)
157 break;
159 if (!match) { return false; }
160 switch (kSchemes[i].scheme_type) {
161 case kSchemeTypeHttp:
162 case kSchemeTypeHttps: {
163 nsCString utf8;
164 nr = url_obj->GetHost(utf8); // or GetAsciiHost to convert using IDNA spec
165 if (NS_FAILED(nr)) { return false; }
166 std::string16 host(NS_ConvertUTF8toUTF16(utf8).get());
167 int port = -1;
168 nr = url_obj->GetPort(&port);
169 if (NS_FAILED(nr)) { return false; }
170 if (port == -1) {
171 // -1 implies the default port for the scheme
172 port = kSchemes[i].default_port;
174 return Init(full_url, kSchemes[i].scheme, host.c_str(), port);
176 case kSchemeTypeFile:
177 return Init(full_url, HttpConstants::kFileScheme, kUnknownDomain, 0);
178 default:
179 return false;
182 #elif BROWSER_SAFARI
183 scoped_CFString url_str(CFStringCreateWithString16(full_url));
184 scoped_CFURL url(CFURLCreateWithString(kCFAllocatorDefault,
185 url_str.get(), NULL));
186 if (!url.get())
187 return false;
189 // Expcilitly disallow urls with embedded username:passwords.
190 // To have consistent behavior, do the same for all browsers.
191 // CFURLCopyUserName() will return NULL if there is no user name.
192 scoped_CFString user_name(CFURLCopyUserName(url.get()));
193 if (user_name.get())
194 return false;
196 scoped_CFString scheme_str(CFURLCopyScheme(url.get()));
197 if (!scheme_str.get())
198 return false;
200 std::string16 scheme;
201 CFStringRefToString16(scheme_str.get(), &scheme);
202 LowerString(scheme);
204 if (scheme == HttpConstants::kHttpScheme ||
205 scheme == HttpConstants::kHttpsScheme) {
206 scoped_CFString host_str(CFURLCopyHostName(url.get()));
207 std::string16 host;
208 CFStringRefToString16(host_str.get(), &host);
210 // CF's implementation is that if no port is specified, it returns -1
211 // The expectation is that http defaults to 80 and https defaults to 443.
212 int port = CFURLGetPortNumber(url.get());
214 if (port < 0) {
215 if (scheme == HttpConstants::kHttpsScheme)
216 port = HttpConstants::kHttpsDefaultPort;
217 else
218 port = HttpConstants::kHttpDefaultPort;
221 return Init(full_url, scheme.c_str(), host.c_str(), port);
222 } else if (scheme == HttpConstants::kFileScheme) {
223 return Init(full_url, HttpConstants::kFileScheme, kUnknownDomain, 0);
225 #endif
227 return false;