1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/extensions/pref/autoconfig/src/nsReadConfig.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,313 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifdef MOZ_LOGGING 1.10 +// sorry, this has to be before the pre-compiled header 1.11 +#define FORCE_PR_LOG /* Allow logging in the release build */ 1.12 +#endif 1.13 +#include "nsReadConfig.h" 1.14 +#include "nsAppDirectoryServiceDefs.h" 1.15 +#include "nsIAppStartup.h" 1.16 +#include "nsDirectoryServiceDefs.h" 1.17 +#include "nsIAutoConfig.h" 1.18 +#include "nsIComponentManager.h" 1.19 +#include "nsIFile.h" 1.20 +#include "nsIObserverService.h" 1.21 +#include "nsIPrefBranch.h" 1.22 +#include "nsIPrefService.h" 1.23 +#include "nsIPromptService.h" 1.24 +#include "nsIServiceManager.h" 1.25 +#include "nsIStringBundle.h" 1.26 +#include "nsToolkitCompsCID.h" 1.27 +#include "nsXPIDLString.h" 1.28 +#include "nsNetUtil.h" 1.29 +#include "prmem.h" 1.30 +#include "nsString.h" 1.31 +#include "nsCRT.h" 1.32 +#include "nspr.h" 1.33 +#include "nsXULAppAPI.h" 1.34 + 1.35 +extern PRLogModuleInfo *MCD; 1.36 + 1.37 +extern nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length, 1.38 + const char *filename, 1.39 + bool bGlobalContext, 1.40 + bool bCallbacks, 1.41 + bool skipFirstLine); 1.42 +extern nsresult CentralizedAdminPrefManagerInit(); 1.43 +extern nsresult CentralizedAdminPrefManagerFinish(); 1.44 + 1.45 + 1.46 +static void DisplayError(void) 1.47 +{ 1.48 + nsresult rv; 1.49 + 1.50 + nsCOMPtr<nsIPromptService> promptService = do_GetService("@mozilla.org/embedcomp/prompt-service;1"); 1.51 + if (!promptService) 1.52 + return; 1.53 + 1.54 + nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID); 1.55 + if (!bundleService) 1.56 + return; 1.57 + 1.58 + nsCOMPtr<nsIStringBundle> bundle; 1.59 + bundleService->CreateBundle("chrome://autoconfig/locale/autoconfig.properties", 1.60 + getter_AddRefs(bundle)); 1.61 + if (!bundle) 1.62 + return; 1.63 + 1.64 + nsXPIDLString title; 1.65 + rv = bundle->GetStringFromName(MOZ_UTF16("readConfigTitle"), getter_Copies(title)); 1.66 + if (NS_FAILED(rv)) 1.67 + return; 1.68 + 1.69 + nsXPIDLString err; 1.70 + rv = bundle->GetStringFromName(MOZ_UTF16("readConfigMsg"), getter_Copies(err)); 1.71 + if (NS_FAILED(rv)) 1.72 + return; 1.73 + 1.74 + promptService->Alert(nullptr, title.get(), err.get()); 1.75 +} 1.76 + 1.77 +// nsISupports Implementation 1.78 + 1.79 +NS_IMPL_ISUPPORTS(nsReadConfig, nsIReadConfig, nsIObserver) 1.80 + 1.81 +nsReadConfig::nsReadConfig() : 1.82 + mRead(false) 1.83 +{ 1.84 + if (!MCD) 1.85 + MCD = PR_NewLogModule("MCD"); 1.86 +} 1.87 + 1.88 +nsresult nsReadConfig::Init() 1.89 +{ 1.90 + nsresult rv; 1.91 + 1.92 + nsCOMPtr<nsIObserverService> observerService = 1.93 + do_GetService("@mozilla.org/observer-service;1", &rv); 1.94 + 1.95 + if (observerService) { 1.96 + rv = observerService->AddObserver(this, NS_PREFSERVICE_READ_TOPIC_ID, false); 1.97 + } 1.98 + return(rv); 1.99 +} 1.100 + 1.101 +nsReadConfig::~nsReadConfig() 1.102 +{ 1.103 + CentralizedAdminPrefManagerFinish(); 1.104 +} 1.105 + 1.106 +NS_IMETHODIMP nsReadConfig::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData) 1.107 +{ 1.108 + nsresult rv = NS_OK; 1.109 + 1.110 + if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) { 1.111 + rv = readConfigFile(); 1.112 + if (NS_FAILED(rv)) { 1.113 + DisplayError(); 1.114 + 1.115 + nsCOMPtr<nsIAppStartup> appStartup = 1.116 + do_GetService(NS_APPSTARTUP_CONTRACTID); 1.117 + if (appStartup) 1.118 + appStartup->Quit(nsIAppStartup::eAttemptQuit); 1.119 + } 1.120 + } 1.121 + return rv; 1.122 +} 1.123 + 1.124 + 1.125 +nsresult nsReadConfig::readConfigFile() 1.126 +{ 1.127 + nsresult rv = NS_OK; 1.128 + nsXPIDLCString lockFileName; 1.129 + nsXPIDLCString lockVendor; 1.130 + uint32_t fileNameLen = 0; 1.131 + 1.132 + nsCOMPtr<nsIPrefBranch> defaultPrefBranch; 1.133 + nsCOMPtr<nsIPrefService> prefService = 1.134 + do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); 1.135 + if (NS_FAILED(rv)) 1.136 + return rv; 1.137 + 1.138 + rv = prefService->GetDefaultBranch(nullptr, getter_AddRefs(defaultPrefBranch)); 1.139 + if (NS_FAILED(rv)) 1.140 + return rv; 1.141 + 1.142 + // This preference is set in the all.js or all-ns.js (depending whether 1.143 + // running mozilla or netscp6) 1.144 + 1.145 + rv = defaultPrefBranch->GetCharPref("general.config.filename", 1.146 + getter_Copies(lockFileName)); 1.147 + 1.148 + 1.149 + PR_LOG(MCD, PR_LOG_DEBUG, ("general.config.filename = %s\n", lockFileName.get())); 1.150 + if (NS_FAILED(rv)) 1.151 + return rv; 1.152 + 1.153 + // This needs to be read only once. 1.154 + // 1.155 + if (!mRead) { 1.156 + // Initiate the new JS Context for Preference management 1.157 + 1.158 + rv = CentralizedAdminPrefManagerInit(); 1.159 + if (NS_FAILED(rv)) 1.160 + return rv; 1.161 + 1.162 + // Open and evaluate function calls to set/lock/unlock prefs 1.163 + rv = openAndEvaluateJSFile("prefcalls.js", 0, false, false); 1.164 + if (NS_FAILED(rv)) 1.165 + return rv; 1.166 + 1.167 + // Evaluate platform specific directives 1.168 + rv = openAndEvaluateJSFile("platform.js", 0, false, false); 1.169 + if (NS_FAILED(rv)) 1.170 + return rv; 1.171 + 1.172 + mRead = true; 1.173 + } 1.174 + // If the lockFileName is nullptr return ok, because no lockFile will be used 1.175 + 1.176 + 1.177 + // Once the config file is read, we should check that the vendor name 1.178 + // is consistent By checking for the vendor name after reading the config 1.179 + // file we allow for the preference to be set (and locked) by the creator 1.180 + // of the cfg file meaning the file can not be renamed (successfully). 1.181 + 1.182 + nsCOMPtr<nsIPrefBranch> prefBranch; 1.183 + rv = prefService->GetBranch(nullptr, getter_AddRefs(prefBranch)); 1.184 + NS_ENSURE_SUCCESS(rv, rv); 1.185 + 1.186 + int32_t obscureValue = 0; 1.187 + (void) defaultPrefBranch->GetIntPref("general.config.obscure_value", &obscureValue); 1.188 + PR_LOG(MCD, PR_LOG_DEBUG, ("evaluating .cfg file %s with obscureValue %d\n", lockFileName.get(), obscureValue)); 1.189 + rv = openAndEvaluateJSFile(lockFileName.get(), obscureValue, true, true); 1.190 + if (NS_FAILED(rv)) 1.191 + { 1.192 + PR_LOG(MCD, PR_LOG_DEBUG, ("error evaluating .cfg file %s %x\n", lockFileName.get(), rv)); 1.193 + return rv; 1.194 + } 1.195 + 1.196 + rv = prefBranch->GetCharPref("general.config.filename", 1.197 + getter_Copies(lockFileName)); 1.198 + if (NS_FAILED(rv)) 1.199 + // There is NO REASON we should ever get here. This is POST reading 1.200 + // of the config file. 1.201 + return NS_ERROR_FAILURE; 1.202 + 1.203 + 1.204 + rv = prefBranch->GetCharPref("general.config.vendor", 1.205 + getter_Copies(lockVendor)); 1.206 + // If vendor is not nullptr, do this check 1.207 + if (NS_SUCCEEDED(rv)) { 1.208 + 1.209 + fileNameLen = strlen(lockFileName); 1.210 + 1.211 + // lockVendor and lockFileName should be the same with the addtion of 1.212 + // .cfg to the filename by checking this post reading of the cfg file 1.213 + // this value can be set within the cfg file adding a level of security. 1.214 + 1.215 + if (PL_strncmp(lockFileName, lockVendor, fileNameLen - 4) != 0) 1.216 + return NS_ERROR_FAILURE; 1.217 + } 1.218 + 1.219 + // get the value of the autoconfig url 1.220 + nsXPIDLCString urlName; 1.221 + rv = prefBranch->GetCharPref("autoadmin.global_config_url", 1.222 + getter_Copies(urlName)); 1.223 + if (NS_SUCCEEDED(rv) && !urlName.IsEmpty()) { 1.224 + 1.225 + // Instantiating nsAutoConfig object if the pref is present 1.226 + mAutoConfig = do_CreateInstance(NS_AUTOCONFIG_CONTRACTID, &rv); 1.227 + if (NS_FAILED(rv)) 1.228 + return NS_ERROR_OUT_OF_MEMORY; 1.229 + 1.230 + rv = mAutoConfig->SetConfigURL(urlName); 1.231 + if (NS_FAILED(rv)) 1.232 + return NS_ERROR_FAILURE; 1.233 + 1.234 + } 1.235 + 1.236 + return NS_OK; 1.237 +} // ReadConfigFile 1.238 + 1.239 + 1.240 +nsresult nsReadConfig::openAndEvaluateJSFile(const char *aFileName, int32_t obscureValue, 1.241 + bool isEncoded, 1.242 + bool isBinDir) 1.243 +{ 1.244 + nsresult rv; 1.245 + 1.246 + nsCOMPtr<nsIInputStream> inStr; 1.247 + if (isBinDir) { 1.248 + nsCOMPtr<nsIFile> jsFile; 1.249 + rv = NS_GetSpecialDirectory(XRE_EXECUTABLE_FILE, 1.250 + getter_AddRefs(jsFile)); 1.251 + if (NS_FAILED(rv)) 1.252 + return rv; 1.253 + 1.254 + rv = jsFile->SetNativeLeafName(nsDependentCString(aFileName)); 1.255 + if (NS_FAILED(rv)) 1.256 + return rv; 1.257 + 1.258 + rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), jsFile); 1.259 + if (NS_FAILED(rv)) 1.260 + return rv; 1.261 + 1.262 + } else { 1.263 + nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); 1.264 + if (NS_FAILED(rv)) 1.265 + return rv; 1.266 + 1.267 + nsAutoCString location("resource://gre/defaults/autoconfig/"); 1.268 + location += aFileName; 1.269 + 1.270 + nsCOMPtr<nsIURI> uri; 1.271 + rv = ioService->NewURI(location, nullptr, nullptr, getter_AddRefs(uri)); 1.272 + if (NS_FAILED(rv)) 1.273 + return rv; 1.274 + 1.275 + nsCOMPtr<nsIChannel> channel; 1.276 + rv = ioService->NewChannelFromURI(uri, getter_AddRefs(channel)); 1.277 + if (NS_FAILED(rv)) 1.278 + return rv; 1.279 + 1.280 + rv = channel->Open(getter_AddRefs(inStr)); 1.281 + if (NS_FAILED(rv)) 1.282 + return rv; 1.283 + } 1.284 + 1.285 + uint64_t fs64; 1.286 + uint32_t amt = 0; 1.287 + rv = inStr->Available(&fs64); 1.288 + if (NS_FAILED(rv)) 1.289 + return rv; 1.290 + // PR_Malloc dones't support over 4GB 1.291 + if (fs64 > UINT32_MAX) 1.292 + return NS_ERROR_FILE_TOO_BIG; 1.293 + uint32_t fs = (uint32_t)fs64; 1.294 + 1.295 + char *buf = (char *)PR_Malloc(fs * sizeof(char)); 1.296 + if (!buf) 1.297 + return NS_ERROR_OUT_OF_MEMORY; 1.298 + 1.299 + rv = inStr->Read(buf, (uint32_t)fs, &amt); 1.300 + NS_ASSERTION((amt == fs), "failed to read the entire configuration file!!"); 1.301 + if (NS_SUCCEEDED(rv)) { 1.302 + if (obscureValue > 0) { 1.303 + 1.304 + // Unobscure file by subtracting some value from every char. 1.305 + for (uint32_t i = 0; i < amt; i++) 1.306 + buf[i] -= obscureValue; 1.307 + } 1.308 + rv = EvaluateAdminConfigScript(buf, amt, aFileName, 1.309 + false, true, 1.310 + isEncoded ? true:false); 1.311 + } 1.312 + inStr->Close(); 1.313 + PR_Free(buf); 1.314 + 1.315 + return rv; 1.316 +}