Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 #include "nsCertPicker.h"
7 #include "pkix/pkixtypes.h"
8 #include "nsMemory.h"
9 #include "nsCOMPtr.h"
10 #include "nsXPIDLString.h"
11 #include "nsIServiceManager.h"
12 #include "nsNSSComponent.h"
13 #include "nsNSSCertificate.h"
14 #include "nsReadableUtils.h"
15 #include "nsICertPickDialogs.h"
16 #include "nsNSSShutDown.h"
17 #include "nsNSSCertHelper.h"
18 #include "ScopedNSSTypes.h"
20 #include "cert.h"
22 using namespace mozilla;
24 NS_IMPL_ISUPPORTS(nsCertPicker, nsIUserCertPicker)
26 nsCertPicker::nsCertPicker()
27 {
28 }
30 nsCertPicker::~nsCertPicker()
31 {
32 }
34 NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx,
35 const char16_t *selectedNickname,
36 int32_t certUsage,
37 bool allowInvalid,
38 bool allowDuplicateNicknames,
39 bool *canceled,
40 nsIX509Cert **_retval)
41 {
42 nsNSSShutDownPreventionLock locker;
43 int32_t selectedIndex = -1;
44 bool selectionFound = false;
45 char16_t **certNicknameList = nullptr;
46 char16_t **certDetailsList = nullptr;
47 CERTCertListNode* node = nullptr;
48 nsresult rv = NS_OK;
50 {
51 // Iterate over all certs. This assures that user is logged in to all hardware tokens.
52 nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
53 mozilla::pkix::ScopedCERTCertList allcerts(
54 PK11_ListCerts(PK11CertListUnique, ctx));
55 }
57 /* find all user certs that are valid and for SSL */
58 /* note that we are allowing expired certs in this list */
60 mozilla::pkix::ScopedCERTCertList certList(
61 CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
62 (SECCertUsage)certUsage,
63 !allowDuplicateNicknames,
64 !allowInvalid,
65 ctx));
66 if (!certList) {
67 return NS_ERROR_NOT_AVAILABLE;
68 }
70 ScopedCERTCertNicknames nicknames(getNSSCertNicknamesFromCertList(certList.get()));
71 if (!nicknames) {
72 return NS_ERROR_NOT_AVAILABLE;
73 }
75 certNicknameList = (char16_t **)nsMemory::Alloc(sizeof(char16_t *) * nicknames->numnicknames);
76 certDetailsList = (char16_t **)nsMemory::Alloc(sizeof(char16_t *) * nicknames->numnicknames);
78 if (!certNicknameList || !certDetailsList) {
79 nsMemory::Free(certNicknameList);
80 nsMemory::Free(certDetailsList);
81 return NS_ERROR_OUT_OF_MEMORY;
82 }
84 int32_t CertsToUse;
86 for (CertsToUse = 0, node = CERT_LIST_HEAD(certList.get());
87 !CERT_LIST_END(node, certList.get()) &&
88 CertsToUse < nicknames->numnicknames;
89 node = CERT_LIST_NEXT(node)
90 )
91 {
92 nsNSSCertificate *tempCert = nsNSSCertificate::Create(node->cert);
94 if (tempCert) {
96 // XXX we really should be using an nsCOMPtr instead of manually add-refing,
97 // but nsNSSCertificate does not have a default constructor.
99 NS_ADDREF(tempCert);
101 nsAutoString i_nickname(NS_ConvertUTF8toUTF16(nicknames->nicknames[CertsToUse]));
102 nsAutoString nickWithSerial;
103 nsAutoString details;
105 if (!selectionFound) {
106 if (i_nickname == nsDependentString(selectedNickname)) {
107 selectedIndex = CertsToUse;
108 selectionFound = true;
109 }
110 }
112 if (NS_SUCCEEDED(tempCert->FormatUIStrings(i_nickname, nickWithSerial, details))) {
113 certNicknameList[CertsToUse] = ToNewUnicode(nickWithSerial);
114 certDetailsList[CertsToUse] = ToNewUnicode(details);
115 }
116 else {
117 certNicknameList[CertsToUse] = nullptr;
118 certDetailsList[CertsToUse] = nullptr;
119 }
121 NS_RELEASE(tempCert);
123 ++CertsToUse;
124 }
125 }
127 if (CertsToUse) {
128 nsICertPickDialogs *dialogs = nullptr;
129 rv = getNSSDialogs((void**)&dialogs,
130 NS_GET_IID(nsICertPickDialogs),
131 NS_CERTPICKDIALOGS_CONTRACTID);
133 if (NS_SUCCEEDED(rv)) {
134 nsPSMUITracker tracker;
135 if (tracker.isUIForbidden()) {
136 rv = NS_ERROR_NOT_AVAILABLE;
137 }
138 else {
139 /* Throw up the cert picker dialog and get back the index of the selected cert */
140 rv = dialogs->PickCertificate(ctx,
141 (const char16_t**)certNicknameList, (const char16_t**)certDetailsList,
142 CertsToUse, &selectedIndex, canceled);
143 }
145 NS_RELEASE(dialogs);
146 }
147 }
149 int32_t i;
150 for (i = 0; i < CertsToUse; ++i) {
151 nsMemory::Free(certNicknameList[i]);
152 nsMemory::Free(certDetailsList[i]);
153 }
154 nsMemory::Free(certNicknameList);
155 nsMemory::Free(certDetailsList);
157 if (!CertsToUse) {
158 return NS_ERROR_NOT_AVAILABLE;
159 }
161 if (NS_SUCCEEDED(rv) && !*canceled) {
162 for (i = 0, node = CERT_LIST_HEAD(certList);
163 !CERT_LIST_END(node, certList);
164 ++i, node = CERT_LIST_NEXT(node)) {
166 if (i == selectedIndex) {
167 nsNSSCertificate *cert = nsNSSCertificate::Create(node->cert);
168 if (!cert) {
169 rv = NS_ERROR_OUT_OF_MEMORY;
170 break;
171 }
173 nsIX509Cert *x509 = 0;
174 nsresult rv = cert->QueryInterface(NS_GET_IID(nsIX509Cert), (void**)&x509);
175 if (NS_FAILED(rv)) {
176 break;
177 }
179 NS_ADDREF(x509);
180 *_retval = x509;
181 NS_RELEASE(cert);
182 break;
183 }
184 }
185 }
187 return rv;
188 }