Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : *
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "SecretDecoderRing.h"
8 :
9 : #include "ScopedNSSTypes.h"
10 : #include "mozilla/Base64.h"
11 : #include "mozilla/Casting.h"
12 : #include "mozilla/Services.h"
13 : #include "nsCOMPtr.h"
14 : #include "nsIInterfaceRequestor.h"
15 : #include "nsIInterfaceRequestorUtils.h"
16 : #include "nsIObserverService.h"
17 : #include "nsIServiceManager.h"
18 : #include "nsITokenPasswordDialogs.h"
19 : #include "nsNSSComponent.h"
20 : #include "nsNSSHelper.h"
21 : #include "pk11func.h"
22 : #include "pk11sdr.h" // For PK11SDR_Encrypt, PK11SDR_Decrypt
23 : #include "ssl.h" // For SSL_ClearSessionCache
24 :
25 : using namespace mozilla;
26 :
27 : // NOTE: Should these be the thread-safe versions?
28 0 : NS_IMPL_ISUPPORTS(SecretDecoderRing, nsISecretDecoderRing)
29 :
30 0 : SecretDecoderRing::SecretDecoderRing()
31 : {
32 0 : }
33 :
34 0 : SecretDecoderRing::~SecretDecoderRing()
35 : {
36 0 : nsNSSShutDownPreventionLock locker;
37 0 : if (isAlreadyShutDown()) {
38 0 : return;
39 : }
40 :
41 0 : shutdown(ShutdownCalledFrom::Object);
42 0 : }
43 :
44 : nsresult
45 0 : SecretDecoderRing::Encrypt(const nsACString& data, /*out*/ nsACString& result)
46 : {
47 0 : nsNSSShutDownPreventionLock locker;
48 0 : if (isAlreadyShutDown()) {
49 0 : return NS_ERROR_NOT_AVAILABLE;
50 : }
51 :
52 0 : UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
53 0 : if (!slot) {
54 0 : return NS_ERROR_NOT_AVAILABLE;
55 : }
56 :
57 : /* Make sure token is initialized. */
58 0 : nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
59 0 : nsresult rv = setPassword(slot.get(), ctx, locker);
60 0 : if (NS_FAILED(rv)) {
61 0 : return rv;
62 : }
63 :
64 : /* Force authentication */
65 0 : if (PK11_Authenticate(slot.get(), true, ctx) != SECSuccess) {
66 0 : return NS_ERROR_FAILURE;
67 : }
68 :
69 : /* Use default key id */
70 : SECItem keyid;
71 0 : keyid.data = nullptr;
72 0 : keyid.len = 0;
73 : SECItem request;
74 0 : request.data = BitwiseCast<unsigned char*, const char*>(data.BeginReading());
75 0 : request.len = data.Length();
76 0 : ScopedAutoSECItem reply;
77 0 : if (PK11SDR_Encrypt(&keyid, &request, &reply, ctx) != SECSuccess) {
78 0 : return NS_ERROR_FAILURE;
79 : }
80 :
81 0 : result.Assign(BitwiseCast<char*, unsigned char*>(reply.data), reply.len);
82 0 : return NS_OK;
83 : }
84 :
85 : nsresult
86 0 : SecretDecoderRing::Decrypt(const nsACString& data, /*out*/ nsACString& result)
87 : {
88 0 : nsNSSShutDownPreventionLock locker;
89 0 : if (isAlreadyShutDown()) {
90 0 : return NS_ERROR_NOT_AVAILABLE;
91 : }
92 :
93 : /* Find token with SDR key */
94 0 : UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
95 0 : if (!slot) {
96 0 : return NS_ERROR_NOT_AVAILABLE;
97 : }
98 :
99 : /* Force authentication */
100 0 : nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
101 0 : if (PK11_Authenticate(slot.get(), true, ctx) != SECSuccess) {
102 0 : return NS_ERROR_NOT_AVAILABLE;
103 : }
104 :
105 : SECItem request;
106 0 : request.data = BitwiseCast<unsigned char*, const char*>(data.BeginReading());
107 0 : request.len = data.Length();
108 0 : ScopedAutoSECItem reply;
109 0 : if (PK11SDR_Decrypt(&request, &reply, ctx) != SECSuccess) {
110 0 : return NS_ERROR_FAILURE;
111 : }
112 :
113 0 : result.Assign(BitwiseCast<char*, unsigned char*>(reply.data), reply.len);
114 0 : return NS_OK;
115 : }
116 :
117 : NS_IMETHODIMP
118 0 : SecretDecoderRing::EncryptString(const nsACString& text,
119 : /*out*/ nsACString& encryptedBase64Text)
120 : {
121 0 : nsAutoCString encryptedText;
122 0 : nsresult rv = Encrypt(text, encryptedText);
123 0 : if (NS_FAILED(rv)) {
124 0 : return rv;
125 : }
126 :
127 0 : rv = Base64Encode(encryptedText, encryptedBase64Text);
128 0 : if (NS_FAILED(rv)) {
129 0 : return rv;
130 : }
131 :
132 0 : return NS_OK;
133 : }
134 :
135 : NS_IMETHODIMP
136 0 : SecretDecoderRing::DecryptString(const nsACString& encryptedBase64Text,
137 : /*out*/ nsACString& decryptedText)
138 : {
139 0 : nsAutoCString encryptedText;
140 0 : nsresult rv = Base64Decode(encryptedBase64Text, encryptedText);
141 0 : if (NS_FAILED(rv)) {
142 0 : return rv;
143 : }
144 :
145 0 : rv = Decrypt(encryptedText, decryptedText);
146 0 : if (NS_FAILED(rv)) {
147 0 : return rv;
148 : }
149 :
150 0 : return NS_OK;
151 : }
152 :
153 : NS_IMETHODIMP
154 0 : SecretDecoderRing::ChangePassword()
155 : {
156 0 : nsNSSShutDownPreventionLock locker;
157 0 : if (isAlreadyShutDown()) {
158 0 : return NS_ERROR_NOT_AVAILABLE;
159 : }
160 :
161 0 : UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
162 0 : if (!slot) {
163 0 : return NS_ERROR_NOT_AVAILABLE;
164 : }
165 :
166 0 : NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(slot.get()));
167 :
168 0 : nsCOMPtr<nsITokenPasswordDialogs> dialogs;
169 0 : nsresult rv = getNSSDialogs(getter_AddRefs(dialogs),
170 : NS_GET_IID(nsITokenPasswordDialogs),
171 0 : NS_TOKENPASSWORDSDIALOG_CONTRACTID);
172 0 : if (NS_FAILED(rv)) {
173 0 : return rv;
174 : }
175 :
176 0 : nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
177 : bool canceled; // Ignored
178 0 : return dialogs->SetPassword(ctx, tokenName, &canceled);
179 : }
180 :
181 : NS_IMETHODIMP
182 0 : SecretDecoderRing::Logout()
183 : {
184 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
185 :
186 : nsresult rv;
187 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
188 0 : if (NS_FAILED(rv))
189 0 : return rv;
190 :
191 : {
192 0 : nsNSSShutDownPreventionLock locker;
193 0 : if (isAlreadyShutDown()) {
194 0 : return NS_ERROR_NOT_AVAILABLE;
195 : }
196 :
197 0 : PK11_LogoutAll();
198 0 : SSL_ClearSessionCache();
199 : }
200 :
201 0 : return NS_OK;
202 : }
203 :
204 : NS_IMETHODIMP
205 0 : SecretDecoderRing::LogoutAndTeardown()
206 : {
207 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
208 :
209 : nsresult rv;
210 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
211 0 : if (NS_FAILED(rv))
212 0 : return rv;
213 :
214 : {
215 0 : nsNSSShutDownPreventionLock locker;
216 0 : if (isAlreadyShutDown()) {
217 0 : return NS_ERROR_NOT_AVAILABLE;
218 : }
219 :
220 0 : PK11_LogoutAll();
221 0 : SSL_ClearSessionCache();
222 : }
223 :
224 0 : rv = nssComponent->LogoutAuthenticatedPK11();
225 :
226 : // After we just logged out, we need to prune dead connections to make
227 : // sure that all connections that should be stopped, are stopped. See
228 : // bug 517584.
229 0 : nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
230 0 : if (os)
231 0 : os->NotifyObservers(nullptr, "net:prune-dead-connections", nullptr);
232 :
233 0 : return rv;
234 : }
|