mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
b=74339 Support import of SSL, S/MIME, and CA certs
r=javi sr=alecf
This commit is contained in:
parent
098841f1b3
commit
02d9df0cf7
@ -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();"/>
|
||||
|
@ -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();"/>
|
||||
|
@ -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();"/>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -297,8 +297,10 @@ nsCertTree::UpdateUIContents()
|
||||
orgCert = nextCert;
|
||||
}
|
||||
mNumRows = count + mNumOrgs;
|
||||
if (mTree)
|
||||
if (mTree) {
|
||||
mTree->RowCountChanged(0, mNumRows);
|
||||
mTree->Invalidate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user