This commit is contained in:
ddrinan%netscape.com 2001-05-03 01:00:56 +00:00
Родитель 5d46b89952
Коммит cc0f036681
16 изменённых файлов: 1061 добавлений и 26 удалений

Просмотреть файл

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* David Drinan.
*/
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
var dialogParams;
function onLoad()
{
dialogParams = window.arguments[0].QueryInterface(nsIDialogParamBlock);
var selectElement = document.getElementById("tokens");
for (var i=1; i <= dialogParams.GetInt(1); i++) {
var menuItemNode = document.createElement("menuitem");
var token = dialogParams.GetString(i);
menuItemNode.setAttribute("value", token);
menuItemNode.setAttribute("label", token);
selectElement.firstChild.appendChild(menuItemNode);
if (i == 1) {
selectElement.selectedItem = menuItemNode;
}
}
}
function doOK()
{
var tokenList = document.getElementById("tokens");
var token = tokenList.value;
dialogParams.SetInt(1,1);
dialogParams.SetString(1, token);
window.close();
}
function doCancel()
{
dialogParams.SetInt(1,0);
window.close();
}

Просмотреть файл

@ -0,0 +1,62 @@
<?xml version="1.0"?>
<!--
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The Original Code is mozilla.org code.
-
- The Initial Developer of the Original Code is Netscape
- Communications Corporation. Portions created by Netscape are
- Copyright (C) 2001 Netscape Communications Corporation. All
- Rights Reserved.
-
- Contributor(s):
- David Drinan (ddrinan@netscape.com)
-->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % pippkiDTD SYSTEM "chrome://pippki/locale/pippki.dtd" >
%pippkiDTD;
]>
<window
id="ssl_warning" title="&chooseToken.title;"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
debug="false"
height="360"
width="400"
onload="onLoad();"
>
<script src="chrome://global/content/strres.js" />
<script src="pippki.js" />
<script src="choosetoken.js" />
<box orient="vertical" style="margin: 5px;" flex="1">
<titledbox orient="vertical">
<html>&chooseToken.message1;</html>
<menulist id="tokens">
<menupopup/>
</menulist>
</titledbox>
<separator />
<box>
<button id="ok-button" class="dialog" label="&ok.label;"
style="width: 10ex" onclick="doOK();" disabled="false"/>
<button id="cancel-button" class="dialog" label="&cancel.label;"
style="width: 10ex" onclick="doCancel();" />
<button id="help-button" class="dialog" label="&help.label;"
style="width: 10ex" onclick="alert('Will bring up help one day');" />
</box>
</box>
</window>

Просмотреть файл

@ -34,6 +34,8 @@ pippki.jar:
content/pippki/clientauthask.js (content/clientauthask.js)
content/pippki/certViewer.xul (content/certViewer.xul)
content/pippki/certDump.xul (content/certDump.xul)
content/pippki/choosetoken.xul (content/choosetoken.xul)
content/pippki/choosetoken.js (content/choosetoken.js)
locale/en-US/pippki/contents.rdf (locale/en-US/contents.rdf)
locale/en-US/pippki/pippki.dtd (locale/en-US/pippki.dtd)
locale/en-US/pippki/pref-ssl.dtd (locale/en-US/pref-ssl.dtd)

Просмотреть файл

@ -90,3 +90,6 @@
<!ENTITY pkcs12.getpassword.title "Password Entry Dialog">
<!ENTITY pkcs12.getpassword.message "Please enter the portable security password protecting this security certificate and private key.">
<!ENTITY chooseToken.title "Choose Token Dialog">
<!ENTITY chooseToken.message1 "Please choose a token.">

Просмотреть файл

@ -111,12 +111,13 @@ nsNSSDialogs::~nsNSSDialogs()
{
}
NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSDialogs, nsINSSDialogs,
NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSDialogs, nsINSSDialogs,
nsITokenPasswordDialogs,
nsISecurityWarningDialogs,
nsIBadCertListener,
nsICertificateDialogs,
nsIClientAuthDialogs);
nsIClientAuthDialogs,
nsITokenDialogs);
nsresult
nsNSSDialogs::Init()
@ -735,3 +736,43 @@ nsNSSDialogs::ViewCert(nsIX509Cert *cert)
block);
return rv;
}
NS_IMETHODIMP
nsNSSDialogs::ChooseToken(nsIInterfaceRequestor *aCtx, const PRUnichar **aTokenList, PRUint32 aCount, PRUnichar **aTokenChosen, PRBool *aCanceled) {
nsresult rv;
PRUint32 i;
*aCanceled = PR_FALSE;
// Get the parent window for the dialog
nsCOMPtr<nsIDOMWindowInternal> parent = do_GetInterface(aCtx);
nsCOMPtr<nsIDialogParamBlock> block(do_CreateInstance("@mozilla.org/embedcomp/dialogparam;1"));
if (!block) return NS_ERROR_FAILURE;
for (i = 0; i < aCount; i++) {
rv = block->SetString(i+1, aTokenList[i]);
if (NS_FAILED(rv)) return rv;
}
rv = block->SetInt(1, aCount);
if (NS_FAILED(rv)) return rv;
rv = nsNSSDialogHelper::openDialog(nsnull,
"chrome://pippki/content/choosetoken.xul",
block);
if (NS_FAILED(rv)) return rv;
PRInt32 status;
rv = block->GetInt(1, &status);
if (NS_FAILED(rv)) return rv;
*aCanceled = (status == 0)?PR_TRUE:PR_FALSE;
if (!*aCanceled) {
// retrieve the nickname
rv = block->GetString(1, aTokenChosen);
}
return rv;
}

Просмотреть файл

@ -41,7 +41,8 @@ class nsNSSDialogs
public nsIBadCertListener,
public nsISecurityWarningDialogs,
public nsICertificateDialogs,
public nsIClientAuthDialogs
public nsIClientAuthDialogs,
public nsITokenDialogs
{
public:
NS_DECL_ISUPPORTS
@ -51,6 +52,7 @@ public:
NS_DECL_NSISECURITYWARNINGDIALOGS
NS_DECL_NSICERTIFICATEDIALOGS
NS_DECL_NSICLIENTAUTHDIALOGS
NS_DECL_NSITOKENDIALOGS
nsNSSDialogs();
virtual ~nsNSSDialogs();

Просмотреть файл

@ -144,13 +144,23 @@ interface nsIClientAuthDialogs : nsISupports
* UI shown when a user is asked to do SSL client auth.
*/
void ChooseCertificate(in nsIInterfaceRequestor ctx,
in wstring cn,
in wstring organization,
in wstring issuer,
[array, size_is(count)] in wstring certNickList,
in PRUint32 count,
out wstring certNick,
out boolean canceled);
in wstring cn,
in wstring organization,
in wstring issuer,
[array, size_is(count)] in wstring certNickList,
in PRUint32 count,
out wstring certNick,
out boolean canceled);
};
[scriptable, uuid(bb4bae9c-39c5-11d5-ba26-00108303b117)]
interface nsITokenDialogs : nsISupports
{
void ChooseToken(in nsIInterfaceRequestor ctx,
[array, size_is(count)] in wstring tokenNameList,
in PRUint32 count,
out wstring tokenName,
out boolean canceled);
};
/**

Просмотреть файл

@ -43,6 +43,7 @@ interface nsISupportsArray;
interface nsIX509Cert;
interface nsIPK11Token;
interface nsILocalFile;
interface nsIInterfaceRequestor;
%{C++
@ -123,6 +124,15 @@ interface nsIX509CertDB : nsISupports {
in unsigned long trust,
in wstring nickname);
/*
* importCertificate
*
* Import a user certificate into the database.
* XXX This method and the importCertificate should be merged into one.
*/
[noscript] void importUserCertificate(in charPtr data,
in unsigned long length,
in nsIInterfaceRequestor ctx);
/*
* deleteCertificate
*

Просмотреть файл

@ -46,6 +46,11 @@ VerifyUserImport=User Import Cert
VerifyCAVerifier=CA Verifier
VerifyStatusResponder=Status Responder Certificate
VerifyAnyCA=Any Certificate Authority
HighGrade=2048 (High Grade)
MediumGrade=1024 (Medium Grade)
LowGrade= 512 (Low Grade)
nick_template=%1$s's %2$s ID
nick_template_with_num=%1$s's %2$s ID #%3$d
#These are the strings set for the ASN1 objects in a certificate.
CertDumpCertificate=Certificate
CertDumpVersion=Version

Просмотреть файл

@ -62,6 +62,7 @@ CPPSRCS = \
nsPKCS12Blob.cpp \
nsNSSASN1Object.cpp \
nsCertOutliner.cpp \
nsKeygenHandler.cpp \
$(NULL)
REQUIRES = nspr security xpcom string necko uriloader pref caps dom intl locale profile windowwatcher js docshell widget layout gfx2

Просмотреть файл

@ -88,6 +88,7 @@ OBJS = \
.\$(OBJDIR)\nsPK11TokenDB.obj \
.\$(OBJDIR)\nsNSSCertificate.obj \
.\$(OBJDIR)\nsPKCS12Blob.obj \
.\$(OBJDIR)\nsKeygenHandler.obj \
.\$(OBJDIR)\nsCertOutliner.obj \
.\$(OBJDIR)\nsNSSASN1Object.obj \
$(NULL)

Просмотреть файл

@ -0,0 +1,519 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
extern "C" {
#include "secdert.h"
#include "keydbt.h"
}
#include "nspr.h"
#include "nsNSSComponent.h" // for PIPNSS string bundle calls.
#include "keyhi.h"
#include "secder.h"
#include "cryptohi.h"
#include "base64.h"
#include "secasn1.h"
#include "nsProxiedService.h"
#include "nsKeygenHandler.h"
#include "nsVoidArray.h"
#include "nsSecureBrowserUIImpl.h"
#include "nsIServiceManager.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsIContent.h"
#include "nsINSSDialogs.h"
//These defines are taken from the PKCS#11 spec
#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
#define CKM_DSA_KEY_PAIR_GEN 0x00000010
//All possible key size choices.
static SECKeySizeChoiceInfo SECKeySizeChoiceList[] = {
{ nsnull, 2048 },
{ nsnull, 1024 },
{ nsnull, 512 },
{ nsnull, 0 },
};
DERTemplate CERTSubjectPublicKeyInfoTemplate[] = {
{ DER_SEQUENCE,
0, nsnull, sizeof(CERTSubjectPublicKeyInfo) },
{ DER_INLINE,
offsetof(CERTSubjectPublicKeyInfo,algorithm),
SECAlgorithmIDTemplate, },
{ DER_BIT_STRING,
offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },
{ 0, }
};
DERTemplate CERTPublicKeyAndChallengeTemplate[] =
{
{ DER_SEQUENCE, 0, nsnull, sizeof(CERTPublicKeyAndChallenge) },
{ DER_ANY, offsetof(CERTPublicKeyAndChallenge,spki), },
{ DER_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge), },
{ 0, }
};
static NS_DEFINE_IID(kFormProcessorIID, NS_IFORMPROCESSOR_IID);
static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID);
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
static const char *mozKeyGen = "-mozilla-keygen";
static PQGParams *
decode_pqg_params(char *aStr)
{
unsigned char *buf;
unsigned int len;
PRArenaPool *arena;
PQGParams *params;
SECStatus status;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena)
return nsnull;
params = NS_STATIC_CAST(PQGParams*, PORT_ArenaZAlloc(arena, sizeof(PQGParams)));
if (!params)
goto loser;
params->arena = arena;
buf = ATOB_AsciiToData(aStr, &len);
if ((!buf) || (len == 0))
goto loser;
status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, (const char*)buf, len);
if (status != SECSuccess)
goto loser;
return params;
loser:
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
if (buf) {
PR_Free(buf);
}
return nsnull;
}
static int
pqg_prime_bits(char *str)
{
PQGParams *params = nsnull;
int primeBits = 0, i;
params = decode_pqg_params(str);
if (!params)
goto done; /* lose */
for (i = 0; params->prime.data[i] == 0; i++)
/* empty */;
primeBits = (params->prime.len - i) * 8;
done:
if (params)
PQG_DestroyParams(params);
return primeBits;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsKeygenFormProcessor, nsIFormProcessor);
MOZ_DECL_CTOR_COUNTER(nsKeygenFormProcessor)
nsKeygenFormProcessor::nsKeygenFormProcessor()
{
NS_INIT_REFCNT();
MOZ_COUNT_CTOR(nsKeygenFormProcessor);
m_ctx = new PipUIContext();
}
nsKeygenFormProcessor::~nsKeygenFormProcessor()
{
MOZ_COUNT_DTOR(nsKeygenFormProcessor);
}
NS_METHOD
nsKeygenFormProcessor::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
{
nsresult rv;
NS_ENSURE_NO_AGGREGATION(aOuter);
nsKeygenFormProcessor* formProc = new nsKeygenFormProcessor();
if (!formProc)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsISupports> stabilize = formProc;
rv = formProc->Init();
if (NS_SUCCEEDED(rv)) {
rv = formProc->QueryInterface(aIID, aResult);
}
return rv;
}
nsresult
nsKeygenFormProcessor::Init()
{
nsresult rv;
nsAutoString str;
// Get the key strings //
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
nssComponent->GetPIPNSSBundleString(
NS_LITERAL_STRING("HighGrade").get(),
str);
SECKeySizeChoiceList[0].name = str.ToNewUnicode();
nssComponent->GetPIPNSSBundleString(
NS_LITERAL_STRING("MediumGrade").get(),
str);
SECKeySizeChoiceList[1].name = str.ToNewUnicode();
nssComponent->GetPIPNSSBundleString(
NS_LITERAL_STRING("LowGrade").get(),
str);
SECKeySizeChoiceList[2].name = str.ToNewUnicode();
return NS_OK;
}
nsresult
nsKeygenFormProcessor::GetSlot(PRUint32 aMechanism, PK11SlotInfo** aSlot)
{
PK11SlotList * slotList = nsnull;
PRUnichar** tokenNameList = nsnull;
nsITokenDialogs * dialogs;
PRUnichar *unicodeTokenChosen;
PK11SlotListElement *slotElement, *tmpSlot;
PRUint32 numSlots = 0, i = 0;
PRBool canceled;
nsresult rv = NS_OK;
*aSlot = nsnull;
// Get the slot
slotList = PK11_GetAllTokens(aMechanism,
PR_TRUE, PR_TRUE, m_ctx);
if (!slotList || !slotList->head) {
rv = NS_ERROR_FAILURE;
goto loser;
}
if (!slotList->head->next) {
/* only one slot available, just return it */
*aSlot = slotList->head->slot;
} else {
// Gerenate a list of slots and ask the user to choose //
tmpSlot = slotList->head;
while (tmpSlot) {
numSlots++;
tmpSlot = tmpSlot->next;
}
// Allocate the slot name buffer //
tokenNameList = NS_STATIC_CAST(PRUnichar**, nsMemory::Alloc(sizeof(PRUnichar *) * numSlots));
i = 0;
slotElement = PK11_GetFirstSafe(slotList);
while (slotElement) {
tokenNameList[i] = NS_ConvertUTF8toUCS2(PK11_GetTokenName(slotElement->slot)).ToNewUnicode();
slotElement = PK11_GetNextSafe(slotList, slotElement, PR_FALSE);
i++;
}
/* Throw up the token list dialog and get back the token */
rv = getNSSDialogs((void**)&dialogs,
NS_GET_IID(nsITokenDialogs));
if (NS_FAILED(rv)) goto loser;
rv = dialogs->ChooseToken(nsnull, (const PRUnichar**)tokenNameList, numSlots, &unicodeTokenChosen, &canceled);
NS_RELEASE(dialogs);
if (NS_FAILED(rv)) goto loser;
if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
// Get the slot //
slotElement = PK11_GetFirstSafe(slotList);
nsAutoString tokenStr(unicodeTokenChosen);
while (slotElement) {
if (tokenStr.Equals(NS_ConvertUTF8toUCS2(PK11_GetTokenName(slotElement->slot)))) {
*aSlot = slotElement->slot;
break;
}
slotElement = PK11_GetNextSafe(slotList, slotElement, PR_FALSE);
}
if(!(*aSlot)) {
rv = NS_ERROR_FAILURE;
goto loser;
}
}
// Get a reference to the slot //
PK11_ReferenceSlot(*aSlot);
loser:
if (slotList) {
PK11_FreeSlotList(slotList);
}
if (tokenNameList) {
nsMemory::Free(tokenNameList);
}
return rv;
}
nsresult
nsKeygenFormProcessor::GetPublicKey(nsString& aValue, nsString& aChallenge,
nsString& aKeyType,
nsString& aOutPublicKey, nsString& aPqg)
{
nsresult rv = NS_ERROR_FAILURE;
char *emptyCString = "null";
char *keystring = nsnull;
char *pqgString = nsnull, *str = nsnull;
nsAutoString rsaStr;
nsAutoString dsaStr;
KeyType type;
PRUint32 keyGenMechanism;
PRInt32 primeBits;
PQGParams *pqgParams;
PK11SlotInfo *slot = nsnull;
PK11RSAGenParams rsaParams;
SECOidTag algTag;
int keysize = 0;
void *params;
SECKEYPrivateKey *privateKey = nsnull;
SECKEYPublicKey *publicKey = nsnull;
CERTSubjectPublicKeyInfo *spkInfo = nsnull;
PRArenaPool *arena = nsnull;
SECStatus sec_rv = SECFailure;
SECItem spkiItem;
SECItem pkacItem;
SECItem signedItem;
CERTPublicKeyAndChallenge pkac;
SECKeySizeChoiceInfo *choice = SECKeySizeChoiceList;
// Get the key size //
while (choice) {
if (aValue.Equals(choice->name)) {
keysize = choice->size;
break;
}
choice++;
}
if (!choice) {
goto loser;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
goto loser;
}
// Set the keygen mechanism
rsaStr.AssignWithConversion("rsa");
dsaStr.AssignWithConversion("dsa");
if (aKeyType.IsEmpty() || aKeyType.Equals(rsaStr)) {
type = rsaKey;
keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
} else if (aKeyType.Equals(dsaStr)) {
char * end;
pqgString = aPqg.ToNewCString();
type = dsaKey;
keyGenMechanism = CKM_DSA_KEY_PAIR_GEN;
if (strcmp(pqgString, "null") == 0)
goto loser;
str = pqgString;
do {
end = strchr(str, ',');
if (end != nsnull)
*end = '\0';
primeBits = pqg_prime_bits(str);
if (choice->size == primeBits)
goto found_match;
str = end + 1;
} while (end != nsnull);
goto loser;
found_match:
pqgParams = decode_pqg_params(str);
} else {
goto loser;
}
// Get the slot
rv = GetSlot(keyGenMechanism, &slot);
if (NS_FAILED(rv)) {
goto loser;
}
switch (keyGenMechanism) {
case CKM_RSA_PKCS_KEY_PAIR_GEN:
rsaParams.keySizeInBits = keysize;
rsaParams.pe = 65537L;
algTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
params = &rsaParams;
break;
case CKM_DSA_KEY_PAIR_GEN:
// XXX Fix this! XXX //
goto loser;
default:
goto loser;
}
sec_rv = PK11_Authenticate(slot, PR_TRUE, m_ctx);
if (sec_rv != SECSuccess) {
goto loser;
}
privateKey = PK11_GenerateKeyPair(slot, keyGenMechanism, params,
&publicKey, PR_TRUE, PR_TRUE, nsnull);
if (!privateKey) {
goto loser;
}
// just in case we'll need to authenticate to the db -jp //
privateKey->wincx = m_ctx;
/*
* Create a subject public key info from the public key.
*/
spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey);
if ( !spkInfo ) {
goto loser;
}
/*
* Now DER encode the whole subjectPublicKeyInfo.
*/
sec_rv=DER_Encode(arena, &spkiItem, CERTSubjectPublicKeyInfoTemplate, spkInfo);
if (sec_rv != SECSuccess) {
goto loser;
}
/*
* set up the PublicKeyAndChallenge data structure, then DER encode it
*/
pkac.spki = spkiItem;
pkac.challenge.len = aChallenge.Length();
pkac.challenge.data = (unsigned char *)aChallenge.ToNewCString();
sec_rv = DER_Encode(arena, &pkacItem, CERTPublicKeyAndChallengeTemplate, &pkac);
if ( sec_rv != SECSuccess ) {
goto loser;
}
/*
* now sign the DER encoded PublicKeyAndChallenge
*/
sec_rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len,
privateKey, algTag);
if ( sec_rv != SECSuccess ) {
goto loser;
}
/*
* Convert the signed public key and challenge into base64/ascii.
*/
keystring = BTOA_DataToAscii(signedItem.data, signedItem.len);
aOutPublicKey.AssignWithConversion(keystring);
nsCRT::free(keystring);
rv = NS_OK;
loser:
if ( sec_rv != SECSuccess ) {
if ( privateKey ) {
PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID);
SECKEY_DestroyPrivateKey(privateKey);
}
if ( publicKey ) {
PK11_DestroyTokenObject(publicKey->pkcs11Slot,publicKey->pkcs11ID);
}
}
if ( spkInfo ) {
SECKEY_DestroySubjectPublicKeyInfo(spkInfo);
}
if ( publicKey ) {
SECKEY_DestroyPublicKey(publicKey);
}
if ( arena ) {
PORT_FreeArena(arena, PR_TRUE);
}
if (slot != nsnull) {
PK11_FreeSlot(slot);
}
return rv;
}
NS_METHOD
nsKeygenFormProcessor::ProcessValue(nsIDOMHTMLElement *aElement,
const nsString& aName,
nsString& aValue)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIDOMHTMLSelectElement>selectElement;
nsresult res = aElement->QueryInterface(kIDOMHTMLSelectElementIID,
getter_AddRefs(selectElement));
if (NS_SUCCEEDED(res)) {
nsAutoString keygenvalue;
nsAutoString challengeValue;
nsAutoString keyTypeValue;
nsAutoString pqgValue;
nsString publicKey;
res = selectElement->GetAttribute(NS_LITERAL_STRING("_moz-type"), keygenvalue);
if (NS_CONTENT_ATTR_HAS_VALUE == res && keygenvalue.Equals(NS_LITERAL_STRING("-mozilla-keygen"))) {
res = selectElement->GetAttribute(NS_LITERAL_STRING("pqg"), pqgValue);
res = selectElement->GetAttribute(NS_LITERAL_STRING("keytype"), keyTypeValue);
if (NS_FAILED(res) || keyTypeValue.IsEmpty()) {
// If this field is not present, we default to rsa.
keyTypeValue.AssignWithConversion("rsa");
}
res = selectElement->GetAttribute(NS_LITERAL_STRING("challenge"), challengeValue);
rv = GetPublicKey(aValue, challengeValue, keyTypeValue,
publicKey, pqgValue);
aValue = publicKey;
}
}
return rv;
}
NS_METHOD nsKeygenFormProcessor::ProvideContent(const nsString& aFormType,
nsVoidArray& aContent,
nsString& aAttribute)
{
nsString selectKey;
SECKeySizeChoiceInfo *choice = SECKeySizeChoiceList;
selectKey.AssignWithConversion("SELECT");
if (Compare(aFormType, NS_LITERAL_STRING("SELECT"),
nsCaseInsensitiveStringComparator()) == 0) {
for (SECKeySizeChoiceInfo* choice = SECKeySizeChoiceList; choice && choice->name; ++choice) {
nsString *str = new nsString(choice->name);
aContent.AppendElement(str);
}
aAttribute.AssignWithConversion(mozKeyGen);
}
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* David Drinan. (ddrinan@netscape.com)
*
*/
#ifndef _NSKEYGENHANDLER_H_
#define _NSKEYGENHANDLER_H_
// Form Processor
#include "nsIFormProcessor.h"
typedef struct SECKeySizeChoiceInfoStr {
PRUnichar *name;
int size;
} SECKeySizeChoiceInfo;
class nsKeygenFormProcessor : public nsIFormProcessor {
public:
nsKeygenFormProcessor();
virtual ~nsKeygenFormProcessor();
nsresult Init();
NS_IMETHOD ProcessValue(nsIDOMHTMLElement *aElement,
const nsString& aName,
nsString& aValue);
NS_IMETHOD ProvideContent(const nsString& aFormType,
nsVoidArray& aContent,
nsString& aAttribute);
NS_DECL_ISUPPORTS
static NS_METHOD Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult);
protected:
nsresult GetPublicKey(nsString& aValue, nsString& aChallenge,
nsString& akeyType, nsString& aOutPublicKey,
nsString& aPqg);
nsresult GetSlot(PRUint32 aMechanism, PK11SlotInfo** aSlot);
private:
nsCOMPtr<nsIInterfaceRequestor> m_ctx;
};
#endif //_NSKEYGENHANDLER_H_

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: nsNSSCertificate.cpp,v 1.20 2001/05/02 22:27:47 javi%netscape.com Exp $
* $Id: nsNSSCertificate.cpp,v 1.21 2001/05/03 01:00:56 ddrinan%netscape.com Exp $
*/
#include "prmem.h"
@ -54,6 +54,7 @@
#include "nsDateTimeFormatCID.h"
#include "nsILocaleService.h"
#include "nspr.h"
extern "C" {
#include "pk11func.h"
#include "certdb.h"
@ -2160,6 +2161,234 @@ done:
return (srv) ? NS_ERROR_FAILURE : NS_OK;
}
static char *
default_nickname(CERTCertificate *cert, nsIInterfaceRequestor* ctx)
{
nsresult rv;
char *username = NULL;
char *caname = NULL;
char *nickname = NULL;
char *tmp = NULL;
int count;
char *nickFmt=NULL, *nickFmtWithNum = NULL;
CERTCertificate *dummycert;
PK11SlotInfo *slot=NULL;
CK_OBJECT_HANDLE keyHandle;
nsAutoString tmpNickFmt;
nsAutoString tmpNickFmtWithNum;
CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
if (NS_FAILED(rv)) goto loser;
username = CERT_GetCommonName(&cert->subject);
if ( username == NULL )
username = PL_strdup("");
if ( username == NULL )
goto loser;
caname = CERT_GetOrgName(&cert->issuer);
if ( caname == NULL )
caname = PL_strdup("");
if ( caname == NULL )
goto loser;
count = 1;
nssComponent->GetPIPNSSBundleString(
NS_LITERAL_STRING("nick_template").get(),
tmpNickFmt);
nickFmt = tmpNickFmt.ToNewUTF8String();
nssComponent->GetPIPNSSBundleString(
NS_LITERAL_STRING("nick_template_with_num").get(),
tmpNickFmtWithNum);
nickFmtWithNum = tmpNickFmtWithNum.ToNewUTF8String();
nickname = PR_smprintf(nickFmt, username, caname);
/*
* We need to see if the private key exists on a token, if it does
* then we need to check for nicknames that already exist on the smart
* card.
*/
slot = PK11_KeyForCertExists(cert, &keyHandle, ctx);
if (slot == NULL) {
goto loser;
}
if (!PK11_IsInternal(slot)) {
tmp = PR_smprintf("%s:%s", PK11_GetTokenName(slot), nickname);
PR_Free(nickname);
nickname = tmp;
tmp = NULL;
}
tmp = nickname;
while ( 1 ) {
if ( count > 1 ) {
nickname = PR_smprintf("%s #%d", tmp, count);
}
if ( nickname == NULL )
goto loser;
if (PK11_IsInternal(slot)) {
/* look up the nickname to make sure it isn't in use already */
dummycert = CERT_FindCertByNickname(defaultcertdb, nickname);
} else {
/*
* Check the cert against others that already live on the smart
* card.
*/
dummycert = PK11_FindCertFromNickname(nickname, ctx);
if (dummycert != NULL) {
/*
* Make sure the subject names are different.
*/
if (CERT_CompareName(&cert->subject, &dummycert->subject) == SECEqual)
{
/*
* There is another certificate with the same nickname and
* the same subject name on the smart card, so let's use this
* nickname.
*/
CERT_DestroyCertificate(dummycert);
dummycert = NULL;
}
}
}
if ( dummycert == NULL )
goto done;
/* found a cert, destroy it and loop */
CERT_DestroyCertificate(dummycert);
if (tmp != nickname) PR_Free(nickname);
count++;
} /* end of while(1) */
loser:
if ( nickname ) {
PR_Free(nickname);
}
nickname = NULL;
done:
if ( caname ) {
PR_Free(caname);
}
if ( username ) {
PR_Free(username);
}
if (slot != NULL) {
PK11_FreeSlot(slot);
if (nickname != NULL) {
tmp = nickname;
nickname = strchr(tmp, ':');
if (nickname != NULL) {
nickname++;
nickname = PL_strdup(nickname);
PR_Free(tmp);
} else {
nickname = tmp;
tmp = NULL;
}
}
}
PR_FREEIF(tmp);
return(nickname);
}
static SECStatus
collect_certs(void *arg, SECItem **certs, int numcerts)
{
CERTDERCerts *collectArgs;
SECItem *cert;
SECStatus rv;
collectArgs = (CERTDERCerts *)arg;
collectArgs->numcerts = numcerts;
collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena,
sizeof(SECItem) * numcerts);
if ( collectArgs->rawCerts == NULL )
return(SECFailure);
cert = collectArgs->rawCerts;
while ( numcerts-- ) {
rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs);
if ( rv == SECFailure )
return(SECFailure);
cert++;
certs++;
}
return (SECSuccess);
}
NS_IMETHODIMP
nsNSSCertificateDB::ImportUserCertificate(char *data, PRUint32 length, nsIInterfaceRequestor *ctx)
{
PK11SlotInfo *slot;
char * nickname = NULL;
SECStatus sec_rv;
int numCACerts;
SECItem *CACerts;
CERTDERCerts * collectArgs;
PRArenaPool *arena;
CERTCertificate * cert=NULL;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if ( arena == NULL )
goto loser;
collectArgs = (CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts));
if ( collectArgs == NULL )
goto loser;
collectArgs->arena = arena;
sec_rv = CERT_DecodeCertPackage(data, length, collect_certs,
(void *)collectArgs);
if (sec_rv != PR_SUCCESS)
goto loser;
cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts,
(char *)NULL, PR_FALSE, PR_TRUE);
if (!cert)
goto loser;
slot = PK11_KeyForCertExists(cert, NULL, ctx);
if ( slot == NULL ) {
goto loser;
}
PK11_FreeSlot(slot);
/* pick a nickname for the cert */
if (cert->subjectList && cert->subjectList->entry &&
cert->subjectList->entry->nickname) {
nickname = cert->subjectList->entry->nickname;
} else {
nickname = default_nickname(cert, ctx);
}
/* user wants to import the cert */
slot = PK11_ImportCertForKey(cert, nickname, ctx);
if (!slot)
goto loser;
PK11_FreeSlot(slot);
numCACerts = collectArgs->numcerts - 1;
if (numCACerts) {
CACerts = collectArgs->rawCerts+1;
sec_rv = CERT_ImportCAChain(CACerts, numCACerts, certUsageUserCertImport);
}
loser:
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
CERT_DestroyCertificate(cert);
return (sec_rv) ? NS_ERROR_FAILURE : NS_OK;
}
/*
* void deleteCertificate(in nsIX509Cert aCert);
*/

Просмотреть файл

@ -585,7 +585,7 @@ PipUIContext::~PipUIContext()
/* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
NS_IMETHODIMP PipUIContext::GetInterface(const nsIID & uuid, void * *result)
{
nsresult rv;
nsresult rv = NS_OK;
if (uuid.Equals(NS_GET_IID(nsIPrompt))) {
nsCOMPtr<nsIProxyObjectManager> proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID));
@ -795,6 +795,17 @@ CertDownloader::OnDataAvailable(nsIRequest* request,
PRUint32 amt;
nsresult err;
//Do a check to see if we need to allocate more memory.
if ((mBufferOffset + (PRInt32)aLength) > mContentLength) {
size_t newSize = mContentLength + kDefaultCertAllocLength;
char *newBuffer;
newBuffer = (char*)nsMemory::Realloc(mByteData, newSize);
if (newBuffer == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
mByteData = newBuffer;
mContentLength = newSize;
}
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnDataAvailable\n"));
do {
@ -819,24 +830,35 @@ CertDownloader::OnStopRequest(nsIRequest* request,
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnStopRequest\n"));
/* this will init NSS if it hasn't happened already */
nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
nsCOMPtr<nsIX509Cert> cert = new nsNSSCertificate(mByteData, mBufferOffset);
if (certdb == nsnull)
return NS_ERROR_FAILURE;
nsresult rv;
nsCOMPtr<nsIInterfaceRequestor> ctx = new CertDownloaderContext();
nsCOMPtr<nsICertificateDialogs> dialogs;
PRBool canceled;
PRUint32 trust;
rv = ::getNSSDialogs(getter_AddRefs(dialogs),
NS_GET_IID(nsICertificateDialogs));
if (NS_FAILED(rv)) goto loser;
rv = dialogs->DownloadCACert(ctx, cert, &trust, &canceled);
if (NS_FAILED(rv)) goto loser;
if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trust));
return certdb->ImportCertificate(cert, mType, trust, nsnull);
switch (mType) {
case nsIX509Cert::CA_CERT:
{
nsCOMPtr<nsIX509Cert> cert = new nsNSSCertificate(mByteData, mBufferOffset);
if (certdb == nsnull)
return NS_ERROR_FAILURE;
nsCOMPtr<nsICertificateDialogs> dialogs;
PRBool canceled;
PRUint32 trust;
rv = ::getNSSDialogs(getter_AddRefs(dialogs),
NS_GET_IID(nsICertificateDialogs));
if (NS_FAILED(rv)) goto loser;
rv = dialogs->DownloadCACert(ctx, cert, &trust, &canceled);
if (NS_FAILED(rv)) goto loser;
if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trust));
return certdb->ImportCertificate(cert, mType, trust, nsnull);
}
case nsIX509Cert::USER_CERT:
return certdb->ImportUserCertificate(mByteData, mBufferOffset, ctx);
default:
rv = NS_ERROR_FAILURE;
break;
}
loser:
return rv;
}

Просмотреть файл

@ -30,6 +30,7 @@
#include "nsSecureBrowserUIImpl.h"
#include "nsSSLSocketProvider.h"
#include "nsTLSSocketProvider.h"
#include "nsKeygenHandler.h"
#include "nsCURILoader.h"
@ -149,6 +150,13 @@ static nsModuleComponentInfo components[] =
nsNSSCertificateDBConstructor
},
{
"Form Processor",
NS_FORMPROCESSOR_CID,
NS_FORMPROCESSOR_CONTRACTID,
nsKeygenFormProcessor::Create
},
{
"Certificate Outliner",
NS_CERTOUTLINER_CID,