1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 : /*Factory for internal browser security resource managers*/
38 :
39 : #include "nsCOMPtr.h"
40 : #include "nsIScriptSecurityManager.h"
41 : #include "nsScriptSecurityManager.h"
42 : #include "nsIPrincipal.h"
43 : #include "nsPrincipal.h"
44 : #include "nsSystemPrincipal.h"
45 : #include "nsNullPrincipal.h"
46 : #include "nsIScriptNameSpaceManager.h"
47 : #include "nsIScriptContext.h"
48 : #include "nsICategoryManager.h"
49 : #include "nsXPIDLString.h"
50 : #include "nsCOMPtr.h"
51 : #include "nsIServiceManager.h"
52 : #include "nsString.h"
53 : #include "nsNetCID.h"
54 : #include "nsIClassInfoImpl.h"
55 : #include "nsJSUtils.h"
56 : #include "nsPIDOMWindow.h"
57 : #include "nsIScriptGlobalObject.h"
58 : #include "nsIDocument.h"
59 : #include "jsfriendapi.h"
60 :
61 : ///////////////////////
62 : // nsSecurityNameSet //
63 : ///////////////////////
64 :
65 0 : nsSecurityNameSet::nsSecurityNameSet()
66 : {
67 0 : }
68 :
69 0 : nsSecurityNameSet::~nsSecurityNameSet()
70 : {
71 0 : }
72 :
73 0 : NS_IMPL_ISUPPORTS1(nsSecurityNameSet, nsIScriptExternalNameSet)
74 :
75 : static JSString *
76 0 : getStringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, unsigned argc, jsval *argv)
77 : {
78 0 : if (argc <= argNum || !JSVAL_IS_STRING(argv[argNum])) {
79 0 : JS_ReportError(cx, "String argument expected");
80 0 : return nsnull;
81 : }
82 :
83 : /*
84 : * We don't want to use JS_ValueToString because we want to be able
85 : * to have an object to represent a target in subsequent versions.
86 : */
87 0 : return JSVAL_TO_STRING(argv[argNum]);
88 : }
89 :
90 : static bool
91 0 : getBytesArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, unsigned argc, jsval *argv,
92 : JSAutoByteString *bytes)
93 : {
94 0 : JSString *str = getStringArgument(cx, obj, argNum, argc, argv);
95 0 : return str && bytes->encode(cx, str);
96 : }
97 :
98 : static void
99 0 : getUTF8StringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum,
100 : unsigned argc, jsval *argv, nsCString& aRetval)
101 : {
102 0 : aRetval.Truncate();
103 :
104 0 : if (argc <= argNum || !JSVAL_IS_STRING(argv[argNum])) {
105 0 : JS_ReportError(cx, "String argument expected");
106 0 : return;
107 : }
108 :
109 : /*
110 : * We don't want to use JS_ValueToString because we want to be able
111 : * to have an object to represent a target in subsequent versions.
112 : */
113 0 : JSString *str = JSVAL_TO_STRING(argv[argNum]);
114 0 : if (!str)
115 0 : return;
116 :
117 0 : const PRUnichar *data = JS_GetStringCharsZ(cx, str);
118 0 : if (!data)
119 0 : return;
120 :
121 0 : CopyUTF16toUTF8(data, aRetval);
122 : }
123 :
124 : static JSBool
125 0 : netscape_security_isPrivilegeEnabled(JSContext *cx, unsigned argc, jsval *vp)
126 : {
127 0 : JSObject *obj = JS_THIS_OBJECT(cx, vp);
128 0 : if (!obj)
129 0 : return JS_FALSE;
130 :
131 0 : bool result = false;
132 0 : if (JSString *str = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp))) {
133 0 : JSAutoByteString cap(cx, str);
134 0 : if (!cap)
135 0 : return JS_FALSE;
136 :
137 : nsresult rv;
138 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
139 0 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
140 0 : if (NS_SUCCEEDED(rv)) {
141 : // NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
142 :
143 0 : rv = securityManager->IsCapabilityEnabled(cap.ptr(), &result);
144 0 : if (NS_FAILED(rv))
145 0 : result = JS_FALSE;
146 : }
147 : } else {
148 0 : return JS_FALSE;
149 : }
150 0 : JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(result));
151 0 : return JS_TRUE;
152 : }
153 :
154 :
155 : static JSBool
156 0 : netscape_security_enablePrivilege(JSContext *cx, unsigned argc, jsval *vp)
157 : {
158 0 : JSObject *obj = JS_THIS_OBJECT(cx, vp);
159 0 : if (!obj)
160 0 : return JS_FALSE;
161 :
162 0 : JSAutoByteString cap;
163 0 : if (!getBytesArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), &cap))
164 0 : return JS_FALSE;
165 :
166 : // Can't use nsContentUtils::GetDocumentFromCaller because that
167 : // depends on various XPConnect stuff that's not set up here.
168 : {
169 0 : JSAutoEnterCompartment ac;
170 0 : if (ac.enter(cx, obj)) {
171 : nsCOMPtr<nsPIDOMWindow> win =
172 0 : do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, obj));
173 0 : if (win) {
174 : nsCOMPtr<nsIDocument> doc =
175 0 : do_QueryInterface(win->GetExtantDocument());
176 0 : if (doc) {
177 0 : doc->WarnOnceAbout(nsIDocument::eEnablePrivilege);
178 : }
179 : }
180 : }
181 : }
182 :
183 : nsresult rv;
184 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
185 0 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
186 0 : if (NS_FAILED(rv))
187 0 : return JS_FALSE;
188 :
189 : // NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
190 :
191 0 : rv = securityManager->EnableCapability(cap.ptr());
192 0 : if (NS_FAILED(rv))
193 0 : return JS_FALSE;
194 0 : JS_SET_RVAL(cx, vp, JSVAL_VOID);
195 0 : return JS_TRUE;
196 : }
197 :
198 : static JSBool
199 0 : netscape_security_disablePrivilege(JSContext *cx, unsigned argc, jsval *vp)
200 : {
201 0 : JSObject *obj = JS_THIS_OBJECT(cx, vp);
202 0 : if (!obj)
203 0 : return JS_FALSE;
204 :
205 0 : JSAutoByteString cap;
206 0 : if (!getBytesArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), &cap))
207 0 : return JS_FALSE;
208 :
209 : nsresult rv;
210 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
211 0 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
212 0 : if (NS_FAILED(rv))
213 0 : return JS_FALSE;
214 :
215 : // NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
216 :
217 0 : rv = securityManager->DisableCapability(cap.ptr());
218 0 : if (NS_FAILED(rv))
219 0 : return JS_FALSE;
220 0 : JS_SET_RVAL(cx, vp, JSVAL_VOID);
221 0 : return JS_TRUE;
222 : }
223 :
224 : static JSBool
225 0 : netscape_security_revertPrivilege(JSContext *cx, unsigned argc, jsval *vp)
226 : {
227 0 : JSObject *obj = JS_THIS_OBJECT(cx, vp);
228 0 : if (!obj)
229 0 : return JS_FALSE;
230 :
231 0 : JSAutoByteString cap;
232 0 : if (!getBytesArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), &cap))
233 0 : return JS_FALSE;
234 :
235 : nsresult rv;
236 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
237 0 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
238 0 : if (NS_FAILED(rv))
239 0 : return JS_FALSE;
240 :
241 : // NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
242 :
243 0 : rv = securityManager->RevertCapability(cap.ptr());
244 0 : if (NS_FAILED(rv))
245 0 : return JS_FALSE;
246 0 : JS_SET_RVAL(cx, vp, JSVAL_VOID);
247 0 : return JS_TRUE;
248 : }
249 :
250 : static JSBool
251 0 : netscape_security_setCanEnablePrivilege(JSContext *cx, unsigned argc, jsval *vp)
252 : {
253 0 : JSObject *obj = JS_THIS_OBJECT(cx, vp);
254 0 : if (!obj)
255 0 : return JS_FALSE;
256 :
257 0 : if (argc < 2) return JS_FALSE;
258 0 : nsCAutoString principalFingerprint;
259 0 : getUTF8StringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), principalFingerprint);
260 0 : JSAutoByteString cap;
261 0 : getBytesArgument(cx, obj, 1, argc, JS_ARGV(cx, vp), &cap);
262 0 : if (principalFingerprint.IsEmpty() || !cap)
263 0 : return JS_FALSE;
264 :
265 : nsresult rv;
266 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
267 0 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
268 0 : if (NS_FAILED(rv))
269 0 : return JS_FALSE;
270 :
271 : // NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
272 :
273 0 : rv = securityManager->SetCanEnableCapability(principalFingerprint,
274 0 : cap.ptr(),
275 0 : nsIPrincipal::ENABLE_GRANTED);
276 0 : if (NS_FAILED(rv))
277 0 : return JS_FALSE;
278 0 : JS_SET_RVAL(cx, vp, JSVAL_VOID);
279 0 : return JS_TRUE;
280 : }
281 :
282 : static JSBool
283 0 : netscape_security_invalidate(JSContext *cx, unsigned argc, jsval *vp)
284 : {
285 0 : JSObject *obj = JS_THIS_OBJECT(cx, vp);
286 0 : if (!obj)
287 0 : return JS_FALSE;
288 :
289 0 : nsCAutoString principalFingerprint;
290 0 : getUTF8StringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), principalFingerprint);
291 0 : if (principalFingerprint.IsEmpty())
292 0 : return JS_FALSE;
293 :
294 : nsresult rv;
295 : nsCOMPtr<nsIScriptSecurityManager> securityManager =
296 0 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
297 0 : if (NS_FAILED(rv))
298 0 : return JS_FALSE;
299 :
300 : // NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
301 :
302 0 : rv = securityManager->SetCanEnableCapability(principalFingerprint,
303 : nsPrincipal::sInvalid,
304 0 : nsIPrincipal::ENABLE_GRANTED);
305 0 : if (NS_FAILED(rv))
306 0 : return JS_FALSE;
307 0 : JS_SET_RVAL(cx, vp, JSVAL_VOID);
308 0 : return JS_TRUE;
309 : }
310 :
311 : static JSFunctionSpec PrivilegeManager_static_methods[] = {
312 : { "isPrivilegeEnabled", netscape_security_isPrivilegeEnabled, 1,0},
313 : { "enablePrivilege", netscape_security_enablePrivilege, 1,0},
314 : { "disablePrivilege", netscape_security_disablePrivilege, 1,0},
315 : { "revertPrivilege", netscape_security_revertPrivilege, 1,0},
316 : //-- System Cert Functions
317 : { "setCanEnablePrivilege", netscape_security_setCanEnablePrivilege,
318 : 2,0},
319 : { "invalidate", netscape_security_invalidate, 1,0},
320 : {nsnull,nsnull,0,0}
321 : };
322 :
323 : /*
324 : * "Steal" calls to netscape.security.PrivilegeManager.enablePrivilege,
325 : * et al. so that code that worked with 4.0 can still work.
326 : */
327 : NS_IMETHODIMP
328 0 : nsSecurityNameSet::InitializeNameSet(nsIScriptContext* aScriptContext)
329 : {
330 0 : JSContext* cx = aScriptContext->GetNativeContext();
331 0 : JSObject *global = JS_ObjectToInnerObject(cx, JS_GetGlobalObject(cx));
332 :
333 : /*
334 : * Find Object.prototype's class by walking up the global object's
335 : * prototype chain.
336 : */
337 0 : JSObject *obj = global;
338 : JSObject *proto;
339 0 : JSAutoRequest ar(cx);
340 0 : while ((proto = JS_GetPrototype(obj)) != nsnull)
341 0 : obj = proto;
342 0 : JSClass *objectClass = JS_GetClass(obj);
343 :
344 : jsval v;
345 0 : if (!JS_GetProperty(cx, global, "netscape", &v))
346 0 : return NS_ERROR_FAILURE;
347 : JSObject *securityObj;
348 0 : if (JSVAL_IS_OBJECT(v)) {
349 : /*
350 : * "netscape" property of window object exists; get the
351 : * "security" property.
352 : */
353 0 : obj = JSVAL_TO_OBJECT(v);
354 0 : if (!JS_GetProperty(cx, obj, "security", &v) || !JSVAL_IS_OBJECT(v))
355 0 : return NS_ERROR_FAILURE;
356 0 : securityObj = JSVAL_TO_OBJECT(v);
357 : } else {
358 : /* define netscape.security object */
359 0 : obj = JS_DefineObject(cx, global, "netscape", objectClass, nsnull, 0);
360 0 : if (obj == nsnull)
361 0 : return NS_ERROR_FAILURE;
362 : securityObj = JS_DefineObject(cx, obj, "security", objectClass,
363 0 : nsnull, 0);
364 0 : if (securityObj == nsnull)
365 0 : return NS_ERROR_FAILURE;
366 : }
367 :
368 : /* Define PrivilegeManager object with the necessary "static" methods. */
369 : obj = JS_DefineObject(cx, securityObj, "PrivilegeManager", objectClass,
370 0 : nsnull, 0);
371 0 : if (obj == nsnull)
372 0 : return NS_ERROR_FAILURE;
373 :
374 0 : return JS_DefineFunctions(cx, obj, PrivilegeManager_static_methods)
375 : ? NS_OK
376 0 : : NS_ERROR_FAILURE;
377 : }
|