static HRESULT DifInstallPreProcess( IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData, IN PCOINSTALLER_CONTEXT_DATA Context ) { HRESULT Error; BOOLEAN Success; BOOLEAN Allow; UNREFERENCED_PARAMETER(DeviceInfoSet); UNREFERENCED_PARAMETER(DeviceInfoData); UNREFERENCED_PARAMETER(Context); Log("====>"); Success = AllowInstall(&Allow); if (!Success) goto fail1; if (!Allow) { SetLastError(ERROR_ACCESS_DENIED); goto fail2; } Success = SupportChildDrivers(); if (!Success) goto fail3; Log("<===="); return NO_ERROR; fail3: Log("fail3"); fail2: Log("fail2"); fail1: Error = GetLastError(); { PTCHAR Message; Message = GetErrorMessage(Error); Log("fail1 (%s)", Message); LocalFree(Message); } return Error; }
NS_IMETHODIMP nsInstallTrigger::UpdateEnabled(nsIURI* aURI, PRBool aUseWhitelist, PRBool* aReturn) { // disallow unless we successfully find otherwise *aReturn = PR_FALSE; if (!aUseWhitelist) { // simple global pref check nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefBranch) prefBranch->GetBoolPref( XPINSTALL_ENABLE_PREF, aReturn); } else if (aURI) { *aReturn = AllowInstall(aURI); } return NS_OK; }
NS_IMETHODIMP nsInstallTrigger::HandleContent(const char * aContentType, nsIInterfaceRequestor* aWindowContext, nsIRequest* aRequest) { nsresult rv = NS_OK; if (!aRequest) return NS_ERROR_NULL_POINTER; if (nsCRT::strcasecmp(aContentType, "application/x-xpinstall") != 0) { // We only support content-type application/x-xpinstall return NS_ERROR_WONT_HANDLE_CONTENT; } // Save the URI so nsXPInstallManager can re-load it later nsCOMPtr<nsIURI> uri; nsCAutoString urispec; nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); if (channel) { rv = channel->GetURI(getter_AddRefs(uri)); if (NS_SUCCEEDED(rv) && uri) rv = uri->GetSpec(urispec); } if (NS_FAILED(rv)) return rv; if (urispec.IsEmpty()) return NS_ERROR_ILLEGAL_VALUE; // Save the referrer if any, for permission checks NS_NAMED_LITERAL_STRING(referrerProperty, "docshell.internalReferrer"); PRBool useReferrer = PR_FALSE; nsCOMPtr<nsIURI> referringURI; nsCOMPtr<nsIPropertyBag2> channelprops(do_QueryInterface(channel)); if (channelprops) { // Get the referrer from the channel properties if we can (not all // channels support our internal-referrer property). // // It's possible docshell explicitly set a null referrer in the case // of typed, pasted, or bookmarked URLs and the like. In such a case // we get a success return value with null pointer. // // A null referrer is automatically whitelisted as an explicit user // action (though they'll still get the confirmation dialog). For a // missing referrer we go to our fall-back plan of using the XPI // location for whitelisting purposes. rv = channelprops->GetPropertyAsInterface(referrerProperty, NS_GET_IID(nsIURI), getter_AddRefs(referringURI)); if (NS_SUCCEEDED(rv)) useReferrer = PR_TRUE; } // Cancel the current request. nsXPInstallManager restarts the download // under its control (shared codepath with InstallTrigger) aRequest->Cancel(NS_BINDING_ABORTED); // Get the global object of the target window for StartSoftwareUpdate nsCOMPtr<nsIScriptGlobalObjectOwner> globalObjectOwner = do_QueryInterface(aWindowContext); nsIScriptGlobalObject* globalObject = globalObjectOwner ? globalObjectOwner->GetScriptGlobalObject() : nsnull; if ( !globalObject ) return NS_ERROR_INVALID_ARG; nsCOMPtr<nsIURI> checkuri; if ( useReferrer ) { // easiest and most common case: base decision on the page that // contained the link // // NOTE: the XPI itself may be from elsewhere; the user can decide if // they trust the actual source when they get the install confirmation // dialog. The decision we're making here is whether the triggering // site is one which is allowed to annoy the user with modal dialogs. checkuri = referringURI; } else { // Now we're stumbing in the dark. In the most likely case the user // simply clicked on an FTP link (no referrer) and it's perfectly // sane to use the current window. // // On the other hand the user might be opening a non-http XPI link // in an unrelated existing window (typed in location bar, bookmark, // dragged link ...) in which case the current window is irrelevant. // If we knew it was one of these explicit user actions we'd like to // allow it, but we have no way of knowing that here. // // But there's no way to distinguish the innocent cases from a clever // malicious site. If we used the target window then evil.com could // embed a presumed allowed site (e.g. mozilla.org) in a frame, then // change the location to the XPI and trigger the install. Or evil.com // could do the same thing in a new window (more work to get around // popup blocking, but possible). // // Our choices appear to be block this type of load entirely or to // trust only the install URI. The former is unacceptably restrictive, // the latter allows malicious sites to pester people with modal // dialogs. As long as the trusted sites don't host bad content that's // no worse than an endless stream of alert()s -- already possible. // If the trusted sites don't even have an ftp server then even this // level of annoyance is not possible. // // If a trusted site hosts an install with an exploitable flaw it // might be possible that a malicious site would attempt to trick // people into installing it, hoping to turn around and exploit it. // This is not entirely far-fetched (it's been done with ActiveX // controls) and will require community policing of the default // trusted sites. checkuri = uri; } nsAutoPtr<nsXPITriggerInfo> trigger(new nsXPITriggerInfo()); nsAutoPtr<nsXPITriggerItem> item(new nsXPITriggerItem(0, NS_ConvertUTF8toUTF16(urispec).get(), nsnull)); if (trigger && item) { // trigger will own the item now trigger->Add(item.forget()); nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject)); nsCOMPtr<nsIXPIInstallInfo> installInfo = new nsXPIInstallInfo(win, checkuri, trigger, 0); if (installInfo) { // From here trigger is owned by installInfo until passed on to nsXPInstallManager trigger.forget(); if (AllowInstall(checkuri)) { return StartInstall(installInfo, nsnull); } else { nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1")); if (os) os->NotifyObservers(installInfo, "xpinstall-install-blocked", nsnull); return NS_ERROR_ABORT; } } } return NS_ERROR_OUT_OF_MEMORY; }
static FORCEINLINE HRESULT __DifInstallPreProcess( IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData, IN PCOINSTALLER_CONTEXT_DATA Context ) { BOOLEAN Success; PTCHAR DeviceInstance; PTCHAR ActiveDeviceInstance; HRESULT Error; UNREFERENCED_PARAMETER(Context); Log("====>"); Success = AllowInstall(); if (!Success) goto fail1; DeviceInstance = GetDeviceInstance(DeviceInfoSet, DeviceInfoData); if (DeviceInstance == NULL) goto fail2; ActiveDeviceInstance = NULL; Success = GetActiveDeviceInstance(&ActiveDeviceInstance); if (!Success) goto fail3; if (ActiveDeviceInstance == NULL) { Success = SetActiveDeviceInstance(DeviceInstance); if (!Success) goto fail4; } else { free(ActiveDeviceInstance); } free(DeviceInstance); Log("<===="); return ERROR_DI_POSTPROCESSING_REQUIRED; fail4: Log("fail4"); free(ActiveDeviceInstance); fail3: Log("fail3"); free(DeviceInstance); fail2: Log("fail2"); fail1: Error = GetLastError(); { PTCHAR Message; Message = GetErrorMessage(Error); Log("fail1 (%s)", Message); LocalFree(Message); } return Error; }