b=74339 Support import of SSL, S/MIME, and CA certs

r=javi sr=alecf
This commit is contained in:
kaie%netscape.com 2002-08-06 13:11:15 +00:00
parent 098841f1b3
commit 02d9df0cf7
10 changed files with 264 additions and 62 deletions

View File

@ -53,11 +53,9 @@
<button id="ca_editButton"
label="&certmgr.edit.label;"
disabled="true" oncommand="editCerts();"/>
<!-- future - import a DER cert?
<button id="ca_addButton"
label="&certmgr.add.label;"
oncommand="addCerts();"/>
-->
label="&certmgr.restore.label;"
oncommand="addCACerts();"/>
<button id="ca_deleteButton"
label="&certmgr.delete.label;"
disabled="true" oncommand="deleteCerts();"/>

View File

@ -71,11 +71,9 @@
label="&certmgr.edit.label;"
disabled="true" oncommand="editCerts();"/>
-->
<!-- future - import a DER cert?
<button id="email_addButton"
label="&certmgr.add.label;"
oncommand="addCerts();"/>
-->
label="&certmgr.restore.label;"
oncommand="addEmailCert();"/>
<button id="email_deleteButton"
label="&certmgr.delete.label;"
disabled="true" oncommand="deleteCerts();"/>

View File

@ -53,11 +53,9 @@
<button id="websites_editButton"
label="&certmgr.edit.label;"
disabled="true" oncommand="editCerts();"/>
<!-- future - import a DER cert?
<button id="websites_addButton"
label="&certmgr.add.label;"
oncommand="addCerts();"/>
-->
label="&certmgr.restore.label;"
oncommand="addWebSiteCert();"/>
<button id="websites_deleteButton"
label="&certmgr.delete.label;"
disabled="true" oncommand="deleteCerts();"/>

View File

@ -303,9 +303,9 @@ function restoreCerts()
if (fp.show() == nsIFilePicker.returnOK) {
var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
certdb.importPKCS12File(null, fp.file);
userTreeView.loadCerts(nsIX509Cert.USER_CERT);
userTreeView.selection.clearSelection();
}
userTreeView.loadCerts(nsIX509Cert.USER_CERT);
userTreeView.selection.clearSelection();
}
function deleteCerts()
@ -406,8 +406,53 @@ function viewCerts()
}
}
/* XXX future - import a DER cert from a file? */
function addCerts()
function addCACerts()
{
alert("Add cert chosen");
var bundle = srGetStrBundle("chrome://pippki/locale/pippki.properties");
var fp = Components.classes[nsFilePicker].createInstance(nsIFilePicker);
fp.init(window,
bundle.GetStringFromName("importCACertsPrompt"),
nsIFilePicker.modeOpen);
fp.appendFilter("Certificate Files", "*.crt; *.cert; *.cer; *.pem; *.der");
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) {
var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
certdb.importCertsFromFile(null, fp.file, nsIX509Cert.CA_CERT);
caTreeView.loadCerts(nsIX509Cert.CA_CERT);
caTreeView.selection.clearSelection();
}
}
function addEmailCert()
{
var bundle = srGetStrBundle("chrome://pippki/locale/pippki.properties");
var fp = Components.classes[nsFilePicker].createInstance(nsIFilePicker);
fp.init(window,
bundle.GetStringFromName("importEmailCertPrompt"),
nsIFilePicker.modeOpen);
fp.appendFilter("Certificate Files", "*.crt; *.cert; *.cer; *.pem; *.der");
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) {
var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
certdb.importCertsFromFile(null, fp.file, nsIX509Cert.EMAIL_CERT);
emailTreeView.loadCerts(nsIX509Cert.EMAIL_CERT);
emailTreeView.selection.clearSelection();
}
}
function addWebSiteCert()
{
var bundle = srGetStrBundle("chrome://pippki/locale/pippki.properties");
var fp = Components.classes[nsFilePicker].createInstance(nsIFilePicker);
fp.init(window,
bundle.GetStringFromName("importWebSiteCertPrompt"),
nsIFilePicker.modeOpen);
fp.appendFilter("Certificate Files", "*.crt; *.cert; *.cer; *.pem; *.der");
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) {
var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
certdb.importCertsFromFile(null, fp.file, nsIX509Cert.SERVER_CERT);
serverTreeView.loadCerts(nsIX509Cert.SERVER_CERT);
serverTreeView.selection.clearSelection();
}
}

View File

@ -168,3 +168,8 @@ crlAutoupdateEnabled=Enabled
crlAutoupdateNotEnabled=Not Enabled
crlAutoupdateOk=OK
crlAutoupdateFailed=Failed
#Import certificate(s) file dialog
importEmailCertPrompt=Select File containing somebody's Email certificate to import
importCACertsPrompt=Select File containing CA certificate(s) to import
importWebSiteCertPrompt=Select File containing Web Site certificate to import

View File

@ -161,6 +161,10 @@ interface nsIX509CertDB : nsISupports {
in unsigned long length,
in nsIInterfaceRequestor ctx);
[noscript] void importServerCertificate(in charPtr data,
in unsigned long length,
in nsIInterfaceRequestor ctx);
/*
* importEmailCertificate2
*
@ -214,6 +218,15 @@ interface nsIX509CertDB : nsISupports {
in unsigned long certType,
in unsigned long trustType);
/*
* importCertsFromFile
*
* Import certificate(s) from file
*/
void importCertsFromFile(in nsIPK11Token aToken,
in nsILocalFile aFile,
in unsigned long aType);
/*
* importPKCS12File
*

View File

@ -297,8 +297,10 @@ nsCertTree::UpdateUIContents()
orgCert = nextCert;
}
mNumRows = count + mNumOrgs;
if (mTree)
if (mTree) {
mTree->RowCountChanged(0, mNumRows);
mTree->Invalidate();
}
return NS_OK;
}

View File

@ -126,6 +126,8 @@ public:
void SetTrustedServerCA();
/* equivalent to "CT,CT,CT" */
void SetTrustedCA();
/* equivalent to "p,," */
void SetValidServerPeer();
/* equivalent to "p,p,p" */
void SetValidPeer();
/* equivalent to "P,P,P" */
@ -339,6 +341,20 @@ nsNSSCertTrust::SetValidPeer()
PR_FALSE, PR_FALSE);
}
void
nsNSSCertTrust::SetValidServerPeer()
{
SetSSLTrust(PR_TRUE, PR_FALSE,
PR_FALSE, PR_FALSE, PR_FALSE,
PR_FALSE, PR_FALSE);
SetEmailTrust(PR_FALSE, PR_FALSE,
PR_FALSE, PR_FALSE, PR_FALSE,
PR_FALSE, PR_FALSE);
SetObjSignTrust(PR_FALSE, PR_FALSE,
PR_FALSE, PR_FALSE, PR_FALSE,
PR_FALSE, PR_FALSE);
}
void
nsNSSCertTrust::SetTrustedPeer()
{
@ -3178,7 +3194,6 @@ nsNSSCertificateDB::ImportCertificates(char * data, PRUint32 length,
nsIInterfaceRequestor *ctx)
{
SECStatus srv = SECFailure;
nsresult nsrv;
PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
@ -3219,8 +3234,6 @@ nsNSSCertificateDB::ImportCertificates(char * data, PRUint32 length,
break;
}
PORT_FreeArena(arena, PR_FALSE);
if (srv != SECSuccess && nsrv == NS_OK)
nsrv = NS_ERROR_FAILURE;
return nsrv;
}
@ -3288,6 +3301,107 @@ loser:
return nsrv;
}
char* nsNSSCertificate::defaultServerNickname(CERTCertificate* cert)
{
char* nickname = nsnull;
int count;
PRBool conflict;
char* servername = nsnull;
servername = CERT_GetCommonName(&cert->subject);
if (servername == NULL) {
return nsnull;
}
count = 1;
while (1) {
if (count == 1) {
nickname = PR_smprintf("%s", servername);
}
else {
nickname = PR_smprintf("%s #%d", servername, count);
}
if (nickname == NULL) {
break;
}
conflict = SEC_CertNicknameConflict(nickname, &cert->derSubject,
cert->dbhandle);
if (conflict == PR_SUCCESS) {
break;
}
PR_Free(nickname);
count++;
}
PR_FREEIF(servername);
return nickname;
}
NS_IMETHODIMP
nsNSSCertificateDB::ImportServerCertificate(char * data, PRUint32 length,
nsIInterfaceRequestor *ctx)
{
SECStatus srv = SECFailure;
nsresult nsrv = NS_OK;
CERTCertificate * cert;
SECItem **rawCerts = nsnull;
int numcerts;
int i;
nsNSSCertTrust trust;
char *serverNickname = nsnull;
PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena)
return NS_ERROR_OUT_OF_MEMORY;
CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
if (!certCollection) {
PORT_FreeArena(arena, PR_FALSE);
return NS_ERROR_FAILURE;
}
cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts,
(char *)NULL, PR_FALSE, PR_TRUE);
if (!cert) {
nsrv = NS_ERROR_FAILURE;
goto loser;
}
numcerts = certCollection->numcerts;
rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
if ( !rawCerts ) {
nsrv = NS_ERROR_FAILURE;
goto loser;
}
for ( i = 0; i < numcerts; i++ ) {
rawCerts[i] = &certCollection->rawCerts[i];
}
serverNickname = nsNSSCertificate::defaultServerNickname(cert);
srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer,
numcerts, rawCerts, NULL, PR_TRUE, PR_FALSE,
serverNickname);
PR_FREEIF(serverNickname);
if ( srv != SECSuccess ) {
nsrv = NS_ERROR_FAILURE;
goto loser;
}
trust.SetValidServerPeer();
srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust());
if ( srv != SECSuccess ) {
nsrv = NS_ERROR_FAILURE;
goto loser;
}
loser:
PORT_Free(rawCerts);
if (arena)
PORT_FreeArena(arena, PR_TRUE);
return nsrv;
}
char *
default_nickname(CERTCertificate *cert, nsIInterfaceRequestor* ctx)
{
@ -3616,6 +3730,73 @@ nsNSSCertificateDB::GetCertTrust(nsIX509Cert *cert,
return NS_OK;
}
NS_IMETHODIMP
nsNSSCertificateDB::ImportCertsFromFile(nsIPK11Token *aToken,
nsILocalFile *aFile,
PRUint32 aType)
{
switch (aType) {
case nsIX509Cert::CA_CERT:
case nsIX509Cert::EMAIL_CERT:
case nsIX509Cert::SERVER_CERT:
// good
break;
default:
// not supported (yet)
return NS_ERROR_FAILURE;
}
nsresult rv;
PRFileDesc *fd = nsnull;
rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
if (NS_FAILED(rv))
return rv;
if (!fd)
return NS_ERROR_FAILURE;
PRFileInfo file_info;
if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &file_info))
return NS_ERROR_FAILURE;
char *buf = new char[file_info.size];
if (!buf)
return NS_ERROR_OUT_OF_MEMORY;
PRInt32 bytes_obtained = PR_Read(fd, buf, file_info.size);
PR_Close(fd);
if (bytes_obtained != file_info.size)
rv = NS_ERROR_FAILURE;
else {
nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
switch (aType) {
case nsIX509Cert::CA_CERT:
rv = ImportCertificates(buf, bytes_obtained, aType, cxt);
break;
case nsIX509Cert::SERVER_CERT:
rv = ImportServerCertificate(buf, bytes_obtained, cxt);
break;
case nsIX509Cert::EMAIL_CERT:
rv = ImportEmailCertificate(buf, bytes_obtained, cxt);
break;
default:
break;
}
}
delete [] buf;
return rv;
}
/*
* void importPKCS12File(in nsIPK11Token aToken,
* in nsILocalFile aFile);

View File

@ -72,6 +72,8 @@ public:
nsresult FormatUIStrings(const nsAutoString &nickname, nsAutoString &nickWithSerial, nsAutoString &details);
static nsNSSCertificate* ConstructFromDER(char *certDER, int derLen);
static char* defaultServerNickname(CERTCertificate* cert);
private:
CERTCertificate *mCert;
PRBool mPermDelete;

View File

@ -1133,46 +1133,6 @@ nsSSLIOLayerNewSocket(const char *host,
return NS_OK;
}
static char* defaultServerNickname(CERTCertificate* cert)
{
char* nickname = nsnull;
int count;
PRBool conflict;
char* servername = nsnull;
servername = CERT_GetCommonName(&cert->subject);
if (servername == NULL) {
return nsnull;
}
count = 1;
while (1) {
if (count == 1) {
nickname = PR_smprintf("%s", servername);
}
else {
nickname = PR_smprintf("%s #%d", servername, count);
}
if (nickname == NULL) {
break;
}
conflict = SEC_CertNicknameConflict(nickname, &cert->derSubject,
cert->dbhandle);
if (conflict == PR_SUCCESS) {
break;
}
PR_Free(nickname);
count++;
}
PR_FREEIF(servername);
return nickname;
}
static nsresult
addCertToDB(CERTCertificate *peerCert, PRInt16 addType)
{
@ -1183,7 +1143,7 @@ addCertToDB(CERTCertificate *peerCert, PRInt16 addType)
switch (addType) {
case nsIBadCertListener::ADD_TRUSTED_PERMANENTLY:
nickname = defaultServerNickname(peerCert);
nickname = nsNSSCertificate::defaultServerNickname(peerCert);
if (nsnull == nickname)
break;
memset((void*)&trust, 0, sizeof(trust));