Exemple #1
0
bool
AccessCheck::isCrossOriginAccessPermitted(JSContext* cx, HandleObject wrapper, HandleId id,
                                          Wrapper::Action act)
{
    if (act == Wrapper::CALL)
        return false;

    if (act == Wrapper::ENUMERATE)
        return true;

    // For the case of getting a property descriptor, we allow if either GET or SET
    // is allowed, and rely on FilteringWrapper to filter out any disallowed accessors.
    if (act == Wrapper::GET_PROPERTY_DESCRIPTOR) {
        return isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::GET) ||
               isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::SET);
    }

    RootedObject obj(cx, js::UncheckedUnwrap(wrapper, /* stopAtOuter = */ false));
    CrossOriginObjectType type = IdentifyCrossOriginObject(obj);
    if (JSID_IS_STRING(id)) {
        if (IsPermitted(type, JSID_TO_FLAT_STRING(id), act == Wrapper::SET))
            return true;
    }

    if (act != Wrapper::GET)
        return false;

    // Check for frame IDs. If we're resolving named frames, make sure to only
    // resolve ones that don't shadow native properties. See bug 860494.
    if (type == CrossOriginWindow) {
        if (JSID_IS_STRING(id)) {
            bool wouldShadow = false;
            if (!XrayUtils::HasNativeProperty(cx, wrapper, id, &wouldShadow) ||
                wouldShadow)
            {
                // If the named subframe matches the name of a DOM constructor,
                // the global resolve triggered by the HasNativeProperty call
                // above will try to perform a CheckedUnwrap on |wrapper|, and
                // throw a security error if it fails. That exception isn't
                // really useful for our callers, so we silence it and just
                // deny access to the property (since it matched a builtin).
                //
                // Note that this would be a problem if the resolve code ever
                // tried to CheckedUnwrap the wrapper _before_ concluding that
                // the name corresponds to a builtin global property, since it
                // would mean that we'd never permit cross-origin named subframe
                // access (something we regrettably need to support).
                JS_ClearPendingException(cx);
                return false;
            }
        }
        return IsFrameId(cx, obj, id);
    }
    return false;
}
static const Wrapper*
SelectWrapper(bool securityWrapper, bool wantXrays, XrayType xrayType,
              bool waiveXrays, bool originIsXBLScope, JSObject* obj)
{
    // Waived Xray uses a modified CCW that has transparent behavior but
    // transitively waives Xrays on arguments.
    if (waiveXrays) {
        MOZ_ASSERT(!securityWrapper);
        return &WaiveXrayWrapper::singleton;
    }

    // If we don't want or can't use Xrays, select a wrapper that's either
    // entirely transparent or entirely opaque.
    if (!wantXrays || xrayType == NotXray) {
        if (!securityWrapper)
            return &CrossCompartmentWrapper::singleton;
        return &FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>::singleton;
    }

    // Ok, we're using Xray. If this isn't a security wrapper, use the permissive
    // version and skip the filter.
    if (!securityWrapper) {
        if (xrayType == XrayForWrappedNative)
            return &PermissiveXrayXPCWN::singleton;
        else if (xrayType == XrayForDOMObject)
            return &PermissiveXrayDOM::singleton;
        else if (xrayType == XrayForJSObject)
            return &PermissiveXrayJS::singleton;
        MOZ_ASSERT(xrayType == XrayForOpaqueObject);
        return &PermissiveXrayOpaque::singleton;
    }

    // This is a security wrapper. Use the security versions and filter.
    if (xrayType == XrayForDOMObject && IdentifyCrossOriginObject(obj) != CrossOriginOpaque)
        return &FilteringWrapper<CrossOriginXrayWrapper,
                                 CrossOriginAccessiblePropertiesOnly>::singleton;

    // There's never any reason to expose other objects to non-subsuming actors.
    // Just use an opaque wrapper in these cases.
    //
    // In general, we don't want opaque function wrappers to be callable.
    // But in the case of XBL, we rely on content being able to invoke
    // functions exposed from the XBL scope. We could remove this exception,
    // if needed, by using ExportFunction to generate the content-side
    // representations of XBL methods.
    if (xrayType == XrayForJSObject && originIsXBLScope)
        return &FilteringWrapper<CrossCompartmentSecurityWrapper, OpaqueWithCall>::singleton;
    return &FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>::singleton;
}