security/manager/ssl/src/nsCertPicker.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsCertPicker.h"
michael@0 7 #include "pkix/pkixtypes.h"
michael@0 8 #include "nsMemory.h"
michael@0 9 #include "nsCOMPtr.h"
michael@0 10 #include "nsXPIDLString.h"
michael@0 11 #include "nsIServiceManager.h"
michael@0 12 #include "nsNSSComponent.h"
michael@0 13 #include "nsNSSCertificate.h"
michael@0 14 #include "nsReadableUtils.h"
michael@0 15 #include "nsICertPickDialogs.h"
michael@0 16 #include "nsNSSShutDown.h"
michael@0 17 #include "nsNSSCertHelper.h"
michael@0 18 #include "ScopedNSSTypes.h"
michael@0 19
michael@0 20 #include "cert.h"
michael@0 21
michael@0 22 using namespace mozilla;
michael@0 23
michael@0 24 NS_IMPL_ISUPPORTS(nsCertPicker, nsIUserCertPicker)
michael@0 25
michael@0 26 nsCertPicker::nsCertPicker()
michael@0 27 {
michael@0 28 }
michael@0 29
michael@0 30 nsCertPicker::~nsCertPicker()
michael@0 31 {
michael@0 32 }
michael@0 33
michael@0 34 NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx,
michael@0 35 const char16_t *selectedNickname,
michael@0 36 int32_t certUsage,
michael@0 37 bool allowInvalid,
michael@0 38 bool allowDuplicateNicknames,
michael@0 39 bool *canceled,
michael@0 40 nsIX509Cert **_retval)
michael@0 41 {
michael@0 42 nsNSSShutDownPreventionLock locker;
michael@0 43 int32_t selectedIndex = -1;
michael@0 44 bool selectionFound = false;
michael@0 45 char16_t **certNicknameList = nullptr;
michael@0 46 char16_t **certDetailsList = nullptr;
michael@0 47 CERTCertListNode* node = nullptr;
michael@0 48 nsresult rv = NS_OK;
michael@0 49
michael@0 50 {
michael@0 51 // Iterate over all certs. This assures that user is logged in to all hardware tokens.
michael@0 52 nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
michael@0 53 mozilla::pkix::ScopedCERTCertList allcerts(
michael@0 54 PK11_ListCerts(PK11CertListUnique, ctx));
michael@0 55 }
michael@0 56
michael@0 57 /* find all user certs that are valid and for SSL */
michael@0 58 /* note that we are allowing expired certs in this list */
michael@0 59
michael@0 60 mozilla::pkix::ScopedCERTCertList certList(
michael@0 61 CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
michael@0 62 (SECCertUsage)certUsage,
michael@0 63 !allowDuplicateNicknames,
michael@0 64 !allowInvalid,
michael@0 65 ctx));
michael@0 66 if (!certList) {
michael@0 67 return NS_ERROR_NOT_AVAILABLE;
michael@0 68 }
michael@0 69
michael@0 70 ScopedCERTCertNicknames nicknames(getNSSCertNicknamesFromCertList(certList.get()));
michael@0 71 if (!nicknames) {
michael@0 72 return NS_ERROR_NOT_AVAILABLE;
michael@0 73 }
michael@0 74
michael@0 75 certNicknameList = (char16_t **)nsMemory::Alloc(sizeof(char16_t *) * nicknames->numnicknames);
michael@0 76 certDetailsList = (char16_t **)nsMemory::Alloc(sizeof(char16_t *) * nicknames->numnicknames);
michael@0 77
michael@0 78 if (!certNicknameList || !certDetailsList) {
michael@0 79 nsMemory::Free(certNicknameList);
michael@0 80 nsMemory::Free(certDetailsList);
michael@0 81 return NS_ERROR_OUT_OF_MEMORY;
michael@0 82 }
michael@0 83
michael@0 84 int32_t CertsToUse;
michael@0 85
michael@0 86 for (CertsToUse = 0, node = CERT_LIST_HEAD(certList.get());
michael@0 87 !CERT_LIST_END(node, certList.get()) &&
michael@0 88 CertsToUse < nicknames->numnicknames;
michael@0 89 node = CERT_LIST_NEXT(node)
michael@0 90 )
michael@0 91 {
michael@0 92 nsNSSCertificate *tempCert = nsNSSCertificate::Create(node->cert);
michael@0 93
michael@0 94 if (tempCert) {
michael@0 95
michael@0 96 // XXX we really should be using an nsCOMPtr instead of manually add-refing,
michael@0 97 // but nsNSSCertificate does not have a default constructor.
michael@0 98
michael@0 99 NS_ADDREF(tempCert);
michael@0 100
michael@0 101 nsAutoString i_nickname(NS_ConvertUTF8toUTF16(nicknames->nicknames[CertsToUse]));
michael@0 102 nsAutoString nickWithSerial;
michael@0 103 nsAutoString details;
michael@0 104
michael@0 105 if (!selectionFound) {
michael@0 106 if (i_nickname == nsDependentString(selectedNickname)) {
michael@0 107 selectedIndex = CertsToUse;
michael@0 108 selectionFound = true;
michael@0 109 }
michael@0 110 }
michael@0 111
michael@0 112 if (NS_SUCCEEDED(tempCert->FormatUIStrings(i_nickname, nickWithSerial, details))) {
michael@0 113 certNicknameList[CertsToUse] = ToNewUnicode(nickWithSerial);
michael@0 114 certDetailsList[CertsToUse] = ToNewUnicode(details);
michael@0 115 }
michael@0 116 else {
michael@0 117 certNicknameList[CertsToUse] = nullptr;
michael@0 118 certDetailsList[CertsToUse] = nullptr;
michael@0 119 }
michael@0 120
michael@0 121 NS_RELEASE(tempCert);
michael@0 122
michael@0 123 ++CertsToUse;
michael@0 124 }
michael@0 125 }
michael@0 126
michael@0 127 if (CertsToUse) {
michael@0 128 nsICertPickDialogs *dialogs = nullptr;
michael@0 129 rv = getNSSDialogs((void**)&dialogs,
michael@0 130 NS_GET_IID(nsICertPickDialogs),
michael@0 131 NS_CERTPICKDIALOGS_CONTRACTID);
michael@0 132
michael@0 133 if (NS_SUCCEEDED(rv)) {
michael@0 134 nsPSMUITracker tracker;
michael@0 135 if (tracker.isUIForbidden()) {
michael@0 136 rv = NS_ERROR_NOT_AVAILABLE;
michael@0 137 }
michael@0 138 else {
michael@0 139 /* Throw up the cert picker dialog and get back the index of the selected cert */
michael@0 140 rv = dialogs->PickCertificate(ctx,
michael@0 141 (const char16_t**)certNicknameList, (const char16_t**)certDetailsList,
michael@0 142 CertsToUse, &selectedIndex, canceled);
michael@0 143 }
michael@0 144
michael@0 145 NS_RELEASE(dialogs);
michael@0 146 }
michael@0 147 }
michael@0 148
michael@0 149 int32_t i;
michael@0 150 for (i = 0; i < CertsToUse; ++i) {
michael@0 151 nsMemory::Free(certNicknameList[i]);
michael@0 152 nsMemory::Free(certDetailsList[i]);
michael@0 153 }
michael@0 154 nsMemory::Free(certNicknameList);
michael@0 155 nsMemory::Free(certDetailsList);
michael@0 156
michael@0 157 if (!CertsToUse) {
michael@0 158 return NS_ERROR_NOT_AVAILABLE;
michael@0 159 }
michael@0 160
michael@0 161 if (NS_SUCCEEDED(rv) && !*canceled) {
michael@0 162 for (i = 0, node = CERT_LIST_HEAD(certList);
michael@0 163 !CERT_LIST_END(node, certList);
michael@0 164 ++i, node = CERT_LIST_NEXT(node)) {
michael@0 165
michael@0 166 if (i == selectedIndex) {
michael@0 167 nsNSSCertificate *cert = nsNSSCertificate::Create(node->cert);
michael@0 168 if (!cert) {
michael@0 169 rv = NS_ERROR_OUT_OF_MEMORY;
michael@0 170 break;
michael@0 171 }
michael@0 172
michael@0 173 nsIX509Cert *x509 = 0;
michael@0 174 nsresult rv = cert->QueryInterface(NS_GET_IID(nsIX509Cert), (void**)&x509);
michael@0 175 if (NS_FAILED(rv)) {
michael@0 176 break;
michael@0 177 }
michael@0 178
michael@0 179 NS_ADDREF(x509);
michael@0 180 *_retval = x509;
michael@0 181 NS_RELEASE(cert);
michael@0 182 break;
michael@0 183 }
michael@0 184 }
michael@0 185 }
michael@0 186
michael@0 187 return rv;
michael@0 188 }

mercurial