Bumping manifests a=b2g-bump
[gecko.git] / dom / wifi / WifiCertService.cpp
blob23bca42f24e494da4e13fea1625e2b7cc8d045f2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 // XXX: This must be done prior to including cert.h (directly or indirectly).
7 // CERT_AddTempCertToPerm is exposed as __CERT_AddTempCertToPerm.
8 #define CERT_AddTempCertToPerm __CERT_AddTempCertToPerm
10 #include "WifiCertService.h"
12 #include "mozilla/ClearOnShutdown.h"
13 #include "mozilla/ModuleUtils.h"
14 #include "mozilla/RefPtr.h"
15 #include "mozilla/dom/ToJSValue.h"
16 #include "cert.h"
17 #include "certdb.h"
18 #include "CryptoTask.h"
19 #include "nsIDOMFile.h"
20 #include "nsIWifiService.h"
21 #include "nsNetUtil.h"
22 #include "nsServiceManagerUtils.h"
23 #include "nsXULAppAPI.h"
24 #include "ScopedNSSTypes.h"
26 #define NS_WIFICERTSERVICE_CID \
27 { 0x83585afd, 0x0e11, 0x43aa, {0x83, 0x46, 0xf3, 0x4d, 0x97, 0x5e, 0x46, 0x77} }
29 using namespace mozilla;
30 using namespace mozilla::dom;
32 namespace mozilla {
34 // The singleton Wifi Cert service, to be used on the main thread.
35 StaticRefPtr<WifiCertService> gWifiCertService;
37 class ImportCertTask MOZ_FINAL: public CryptoTask
39 public:
40 ImportCertTask(int32_t aId, nsIDOMBlob* aCertBlob,
41 const nsAString& aCertPassword,
42 const nsAString& aCertNickname)
43 : mBlob(aCertBlob)
44 , mPassword(aCertPassword)
46 MOZ_ASSERT(NS_IsMainThread());
48 mResult.mId = aId;
49 mResult.mStatus = 0;
50 mResult.mUsageFlag = 0;
51 mResult.mNickname = aCertNickname;
54 private:
55 virtual void ReleaseNSSResources() {}
57 virtual nsresult CalculateResult() MOZ_OVERRIDE
59 MOZ_ASSERT(!NS_IsMainThread());
61 // read data from blob.
62 nsCString blobBuf;
63 nsresult rv = ReadBlob(blobBuf);
64 if (NS_FAILED(rv)) {
65 return rv;
68 char* buf;
69 uint32_t size = blobBuf.GetMutableData(&buf);
70 if (size == 0) {
71 return NS_ERROR_OUT_OF_MEMORY;
74 // Only support DER format now.
75 return ImportDERBlob(buf, size, mResult.mNickname,
76 &mResult.mUsageFlag);
79 virtual void CallCallback(nsresult rv)
81 if (NS_FAILED(rv)) {
82 mResult.mStatus = -1;
84 gWifiCertService->DispatchResult(mResult);
87 nsresult ImportDERBlob(char* buf, uint32_t size,
88 const nsAString& aNickname,
89 /*out*/ uint16_t* aUsageFlag)
91 NS_ENSURE_ARG_POINTER(aUsageFlag);
93 // Create certificate object.
94 ScopedCERTCertificate cert(CERT_DecodeCertFromPackage(buf, size));
95 if (!cert) {
96 return MapSECStatus(SECFailure);
99 // Import certificate with nickname.
100 return ImportCert(cert, aNickname, aUsageFlag);
103 nsresult ReadBlob(/*out*/ nsCString& aBuf)
105 NS_ENSURE_ARG_POINTER(mBlob);
107 static const uint64_t MAX_FILE_SIZE = 16384;
108 uint64_t size;
109 nsresult rv = mBlob->GetSize(&size);
110 if (NS_FAILED(rv)) {
111 return rv;
113 if (size > MAX_FILE_SIZE) {
114 return NS_ERROR_FILE_TOO_BIG;
117 nsCOMPtr<nsIInputStream> inputStream;
118 rv = mBlob->GetInternalStream(getter_AddRefs(inputStream));
119 if (NS_FAILED(rv)) {
120 return rv;
123 rv = NS_ReadInputStreamToString(inputStream, aBuf, (uint32_t)size);
124 if (NS_FAILED(rv)) {
125 return rv;
128 return NS_OK;
131 nsresult ImportCert(CERTCertificate* aCert, const nsAString& aNickname,
132 /*out*/ uint16_t* aUsageFlag)
134 NS_ENSURE_ARG_POINTER(aUsageFlag);
136 nsCString userNickname, fullNickname;
138 CopyUTF16toUTF8(aNickname, userNickname);
139 // Determine certificate nickname by adding prefix according to its type.
140 if (aCert->isRoot && (aCert->nsCertType & NS_CERT_TYPE_SSL_CA)) {
141 // Accept self-signed SSL CA as server certificate.
142 fullNickname.AssignLiteral("WIFI_SERVERCERT_");
143 fullNickname += userNickname;
144 *aUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_SERVER;
145 } else {
146 return NS_ERROR_ABORT;
149 char* nickname;
150 uint32_t length;
151 length = fullNickname.GetMutableData(&nickname);
152 if (length == 0) {
153 return NS_ERROR_UNEXPECTED;
156 // Import certificate, duplicated nickname will cause error.
157 SECStatus srv = CERT_AddTempCertToPerm(aCert, nickname, NULL);
158 if (srv != SECSuccess) {
159 return MapSECStatus(srv);
162 return NS_OK;
165 nsCOMPtr<nsIDOMBlob> mBlob;
166 nsString mPassword;
167 WifiCertServiceResultOptions mResult;
170 class DeleteCertTask MOZ_FINAL: public CryptoTask
172 public:
173 DeleteCertTask(int32_t aId, const nsAString& aCertNickname)
175 MOZ_ASSERT(NS_IsMainThread());
177 mResult.mId = aId;
178 mResult.mStatus = 0;
179 mResult.mUsageFlag = 0;
180 mResult.mNickname = aCertNickname;
183 private:
184 virtual void ReleaseNSSResources() {}
186 virtual nsresult CalculateResult() MOZ_OVERRIDE
188 MOZ_ASSERT(!NS_IsMainThread());
190 nsCString userNickname;
191 CopyUTF16toUTF8(mResult.mNickname, userNickname);
193 // Delete server certificate.
194 nsCString serverCertName("WIFI_SERVERCERT_", 16);
195 serverCertName += userNickname;
197 ScopedCERTCertificate cert(
198 CERT_FindCertByNickname(CERT_GetDefaultCertDB(), serverCertName.get())
200 if (!cert) {
201 return MapSECStatus(SECFailure);
204 SECStatus srv = SEC_DeletePermCertificate(cert);
205 if (srv != SECSuccess) {
206 return MapSECStatus(srv);
209 return NS_OK;
212 virtual void CallCallback(nsresult rv)
214 if (NS_FAILED(rv)) {
215 mResult.mStatus = -1;
217 gWifiCertService->DispatchResult(mResult);
220 WifiCertServiceResultOptions mResult;
223 NS_IMPL_ISUPPORTS(WifiCertService, nsIWifiCertService)
225 NS_IMETHODIMP
226 WifiCertService::Start(nsIWifiEventListener* aListener)
228 MOZ_ASSERT(aListener);
230 nsresult rv = NS_NewThread(getter_AddRefs(mRequestThread));
231 if (NS_FAILED(rv)) {
232 NS_WARNING("Certn't create wifi control thread");
233 Shutdown();
234 return NS_ERROR_FAILURE;
237 mListener = aListener;
239 return NS_OK;
242 NS_IMETHODIMP
243 WifiCertService::Shutdown()
245 MOZ_ASSERT(NS_IsMainThread());
246 if (mRequestThread) {
247 mRequestThread->Shutdown();
248 mRequestThread = nullptr;
251 mListener = nullptr;
253 return NS_OK;
256 void
257 WifiCertService::DispatchResult(const WifiCertServiceResultOptions& aOptions)
259 MOZ_ASSERT(NS_IsMainThread());
261 mozilla::AutoSafeJSContext cx;
262 JS::RootedValue val(cx);
263 nsCString dummyInterface;
265 if (!ToJSValue(cx, aOptions, &val)) {
266 return;
269 // Certll the listener with a JS value.
270 mListener->OnCommand(val, dummyInterface);
273 WifiCertService::WifiCertService()
275 MOZ_ASSERT(NS_IsMainThread());
276 MOZ_ASSERT(!gWifiCertService);
279 WifiCertService::~WifiCertService()
281 MOZ_ASSERT(!gWifiCertService);
284 already_AddRefed<WifiCertService>
285 WifiCertService::FactoryCreate()
287 if (XRE_GetProcessType() != GeckoProcessType_Default) {
288 return nullptr;
291 MOZ_ASSERT(NS_IsMainThread());
293 if (!gWifiCertService) {
294 gWifiCertService = new WifiCertService();
295 ClearOnShutdown(&gWifiCertService);
298 nsRefPtr<WifiCertService> service = gWifiCertService.get();
299 return service.forget();
302 NS_IMETHODIMP
303 WifiCertService::ImportCert(int32_t aId, nsIDOMBlob* aCertBlob,
304 const nsAString& aCertPassword,
305 const nsAString& aCertNickname)
307 RefPtr<CryptoTask> task = new ImportCertTask(aId, aCertBlob, aCertPassword,
308 aCertNickname);
309 return task->Dispatch("WifiImportCert");
312 NS_IMETHODIMP
313 WifiCertService::DeleteCert(int32_t aId, const nsAString& aCertNickname)
315 RefPtr<CryptoTask> task = new DeleteCertTask(aId, aCertNickname);
316 return task->Dispatch("WifiDeleteCert");
319 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WifiCertService,
320 WifiCertService::FactoryCreate)
322 NS_DEFINE_NAMED_CID(NS_WIFICERTSERVICE_CID);
324 static const mozilla::Module::CIDEntry kWifiCertServiceCIDs[] = {
325 { &kNS_WIFICERTSERVICE_CID, false, nullptr, WifiCertServiceConstructor },
326 { nullptr }
329 static const mozilla::Module::ContractIDEntry kWifiCertServiceContracts[] = {
330 { "@mozilla.org/wifi/certservice;1", &kNS_WIFICERTSERVICE_CID },
331 { nullptr }
334 static const mozilla::Module kWifiCertServiceModule = {
335 mozilla::Module::kVersion,
336 kWifiCertServiceCIDs,
337 kWifiCertServiceContracts,
338 nullptr
341 } // namespace mozilla
343 NSMODULE_DEFN(WifiCertServiceModule) = &kWifiCertServiceModule;