зеркало из https://github.com/mozilla/gecko-dev.git
2760 строки
78 KiB
C
2760 строки
78 KiB
C
/*
|
|
* 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 the Netscape security libraries.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU General Public License Version 2 or later (the
|
|
* "GPL"), in which case the provisions of the GPL are applicable
|
|
* instead of those above. If you wish to allow use of your
|
|
* version of this file only under the terms of the GPL and not to
|
|
* allow others to use your version of this file under the MPL,
|
|
* indicate your decision by deleting the provisions above and
|
|
* replace them with the notice and other provisions required by
|
|
* the GPL. If you do not delete the provisions above, a recipient
|
|
* may use your version of this file under either the MPL or the
|
|
* GPL.
|
|
*/
|
|
#include "certres.h"
|
|
#include "sechash.h"
|
|
#include "ssmerrs.h"
|
|
#include "ctrlconn.h"
|
|
#include "certlist.h"
|
|
#include "resource.h"
|
|
#include "ssldlgs.h"
|
|
#include "certsearch.h"
|
|
#include "secpkcs7.h"
|
|
#include "secerr.h"
|
|
#include "advisor.h"
|
|
|
|
typedef enum
|
|
{ myCert = 0,
|
|
othersCert,
|
|
webCert,
|
|
caCert,
|
|
badCert
|
|
} certPane;
|
|
|
|
enum {
|
|
USER_CERT = (PRIntn) 0,
|
|
EMAIL_CERT,
|
|
CA_CERT,
|
|
WEBSITE_CERT
|
|
};
|
|
|
|
enum {
|
|
NICKNAME = (PRIntn) 0,
|
|
EMAILADDR
|
|
};
|
|
|
|
SSMStatus SSM_DeleteCertificate(SSMResourceCert * resource);
|
|
SECItem * unhexify(char * hex);
|
|
SSMStatus
|
|
ssm_select_cert(SSMTextGenContext * cx, char ** result, char * fmt,
|
|
PRIntn type, PRIntn key, char * nickname);
|
|
SSMStatus
|
|
ssm_create_select_cert_entry(SSMTextGenContext * cx, CERTCertificate * cert,
|
|
char **result, char *fmt, char * checked);
|
|
SSMStatus
|
|
ssm_cert_belongs_type(CERTCertificate * cert, PRIntn type);
|
|
static
|
|
certPane SSMUI_CertBelongs(CERTCertificate * cert);
|
|
|
|
/* ### mwelch Defined in libcert. Should we be using this? */
|
|
SEC_BEGIN_PROTOS
|
|
extern SECStatus cert_GetKeyID(CERTCertificate *cert);
|
|
SEC_END_PROTOS
|
|
|
|
CERTCertificate * FindCertByKeyIDAndNickname(SSMControlConnection * ctrl,
|
|
char *nickname, SECItem *keyID,
|
|
char * serial);
|
|
|
|
CERTCertList *
|
|
SSMControlConnection_CreateCertListByNickname(SSMControlConnection * ctrl,
|
|
char * nick, PRBool email);
|
|
CERTCertificate *
|
|
SSMControlConnection_FindCertByNickname(SSMControlConnection * ctrl,
|
|
char * nick, PRBool email);
|
|
SSMStatus SSM_RefreshRefererPage(HTTPRequest * req);
|
|
SSMStatus SSM_ProcessCertResourceUIAction(HTTPRequest * req,
|
|
SSMResourceCert * certres);
|
|
extern SSMStatus httpparse_count_params(HTTPRequest * req);
|
|
extern SSMStatus httpparse_parse_params(HTTPRequest * req);
|
|
|
|
/* Shorthand macros for inherited classes */
|
|
#define SSMRESOURCE(ss) (&(ss)->super)
|
|
|
|
SSMStatus SSMResourceCert_GetAttr(SSMResource * resource,
|
|
SSMAttributeID attrib,
|
|
SSMResourceAttrType attrType,
|
|
SSMAttributeValue *value)
|
|
{
|
|
SSMResourceCert * res = (SSMResourceCert *)resource;
|
|
SECItem secitem;
|
|
SSMStatus rv;
|
|
char *tmpstr = NULL;
|
|
|
|
if (!res || !res->cert || !value )
|
|
goto loser;
|
|
|
|
/* Access fields in the certificate and pass up in the data field */
|
|
switch (attrib) {
|
|
case SSM_FID_CERT_SUBJECT_NAME:
|
|
if (!res->cert->subjectName)
|
|
goto loser;
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
value->u.string.len = strlen(res->cert->subjectName);
|
|
value->u.string.data = (unsigned char *) strdup(res->cert->subjectName);
|
|
break;
|
|
|
|
case SSM_FID_CERT_ISSUER_NAME:
|
|
if (!res->cert->issuerName)
|
|
goto loser;
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
value->u.string.len = strlen(res->cert->issuerName);
|
|
value->u.string.data = (unsigned char *) strdup(res->cert->issuerName);
|
|
break;
|
|
|
|
case SSM_FID_CERT_SERIAL_NUMBER:
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
tmpstr = CERT_Hexify(&(res->cert->serialNumber), 1);
|
|
if (tmpstr == NULL)
|
|
goto loser;
|
|
value->u.string.len = strlen(tmpstr);
|
|
value->u.string.data = (unsigned char *) strdup(tmpstr);
|
|
break;
|
|
|
|
case SSM_FID_CERT_EXP_DATE:
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
tmpstr = DER_UTCDayToAscii(&(res->cert->validity.notAfter));
|
|
if (tmpstr == NULL)
|
|
goto loser;
|
|
value->u.string.len = strlen(tmpstr);
|
|
value->u.string.data = (unsigned char *) strdup(tmpstr);
|
|
break;
|
|
|
|
case SSM_FID_CERT_FINGERPRINT:
|
|
{
|
|
unsigned char buf[MD5_LENGTH];
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
MD5_HashBuf(buf, res->cert->derCert.data, res->cert->derCert.len);
|
|
secitem.data = buf;
|
|
secitem.len = 16;
|
|
tmpstr = CERT_Hexify(&secitem, 1);
|
|
if (tmpstr == NULL)
|
|
goto loser;
|
|
value->u.string.len = strlen(tmpstr);
|
|
value->u.string.data = (unsigned char *) strdup(tmpstr);
|
|
break;
|
|
}
|
|
|
|
case SSM_FID_CERT_COMMON_NAME:
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
tmpstr = CERT_GetCommonName(&(res->cert->subject));
|
|
if (tmpstr == NULL)
|
|
goto loser;
|
|
value->u.string.len = strlen(tmpstr);
|
|
value->u.string.data = (unsigned char *) strdup(tmpstr);
|
|
break;
|
|
|
|
case SSM_FID_CERT_NICKNAME:
|
|
if (!res->cert->nickname)
|
|
goto loser;
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
value->u.string.len = strlen(res->cert->nickname);
|
|
value->u.string.data = (unsigned char *) strdup(res->cert->nickname);
|
|
break;
|
|
|
|
case SSM_FID_CERT_ORG_NAME:
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
tmpstr = CERT_GetOrgName(&(res->cert->subject));
|
|
if (tmpstr == NULL)
|
|
goto loser;
|
|
value->u.string.len = strlen(tmpstr);
|
|
value->u.string.data = (unsigned char *) strdup(tmpstr);
|
|
break;
|
|
|
|
case SSM_FID_CERT_EMAIL_ADDRESS:
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
tmpstr = PL_strdup(CERT_GetCertificateEmailAddress(res->cert));
|
|
if (tmpstr == NULL)
|
|
goto loser;
|
|
value->u.string.len = PL_strlen(tmpstr);
|
|
value->u.string.data = (unsigned char *) PL_strdup(tmpstr);
|
|
break;
|
|
|
|
case SSM_FID_CERT_PICKLE_CERT:
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
if (!(value->u.string.data = (unsigned char *) PR_Malloc(res->cert->derCert.len))) {
|
|
goto loser;
|
|
}
|
|
memcpy(value->u.string.data, res->cert->derCert.data, res->cert->derCert.len);
|
|
value->u.string.len = res->cert->derCert.len;
|
|
break;
|
|
|
|
case SSM_FID_CERT_HTML_CERT:
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
rv = (*resource->m_html_func)(resource, NULL, (void **)&tmpstr);
|
|
if (rv != PR_SUCCESS)
|
|
goto loser;
|
|
value->u.string.len = PL_strlen(tmpstr);
|
|
value->u.string.data = (unsigned char *) PL_strdup(tmpstr);
|
|
break;
|
|
|
|
case SSM_FID_CERT_CERTKEY:
|
|
value->type = SSM_STRING_ATTRIBUTE;
|
|
if (!(value->u.string.data = (unsigned char *) PR_Malloc(res->cert->certKey.len))) {
|
|
goto loser;
|
|
}
|
|
memcpy(value->u.string.data, res->cert->certKey.data, res->cert->certKey.len);
|
|
value->u.string.len = res->cert->certKey.len;
|
|
break;
|
|
|
|
case SSM_FID_CERT_FIND_CERT_ISSUER:
|
|
{
|
|
SSMResourceCert *certRes;
|
|
SSMResourceID certID;
|
|
SSMStatus rv;
|
|
CERTCertificate *cert;
|
|
|
|
/* Make sure we have a cert to return. */
|
|
cert = CERT_FindCertIssuer(res->cert, PR_Now(), certUsageObjectSigner);
|
|
if (!cert) {
|
|
goto loser;
|
|
}
|
|
|
|
if ((cert->certKey.len != res->cert->certKey.len) ||
|
|
(memcmp(cert->certKey.data,
|
|
res->cert->certKey.data,
|
|
cert->certKey.len)))
|
|
{
|
|
rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
|
|
cert, resource->m_connection, &certID,
|
|
(SSMResource**)&certRes);
|
|
if (rv != PR_SUCCESS)
|
|
goto loser;
|
|
rv = SSM_ClientGetResourceReference(SSMRESOURCE(certRes), &certID);
|
|
SSM_FreeResource(SSMRESOURCE(certRes));
|
|
if (rv != PR_SUCCESS)
|
|
goto loser;
|
|
}
|
|
else
|
|
{
|
|
rv = SSM_ClientGetResourceReference(SSMRESOURCE(res), &certID);
|
|
if (rv != PR_SUCCESS)
|
|
goto loser;
|
|
}
|
|
|
|
value->type = SSM_RID_ATTRIBUTE;
|
|
value->u.rid = certID;
|
|
|
|
rv = PR_SUCCESS;
|
|
break;
|
|
}
|
|
case SSM_FID_CERT_ISPERM:
|
|
value->type = SSM_NUMERIC_ATTRIBUTE;
|
|
value->u.numeric = res->cert->isperm;
|
|
rv = PR_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
goto loser;
|
|
}
|
|
|
|
if (tmpstr != NULL)
|
|
PR_Free(tmpstr);
|
|
return PR_SUCCESS;
|
|
|
|
loser:
|
|
value->type = SSM_NO_ATTRIBUTE;
|
|
if (tmpstr != NULL)
|
|
PR_Free(tmpstr);
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
|
|
SSMStatus SSMResourceCert_Pickle(SSMResource * res,
|
|
PRIntn * len,
|
|
void ** data)
|
|
{
|
|
SSMAttributeValue value;
|
|
SSMStatus rv;
|
|
|
|
if (!res || !((SSMResourceCert *)res)->cert || !data || !len )
|
|
return PR_FAILURE;
|
|
|
|
rv = ((*(SSMResourceCert *)res).super.m_get_func)(res,
|
|
SSM_FID_CERT_PICKLE_CERT,
|
|
SSM_STRING_ATTRIBUTE,
|
|
&value);
|
|
if (rv != PR_SUCCESS)
|
|
goto loser;
|
|
|
|
*data = PR_Malloc(value.u.string.len);
|
|
if (!*data) {
|
|
goto loser;
|
|
}
|
|
memcpy(*data, value.u.string.data, value.u.string.len);
|
|
*len = value.u.string.len;
|
|
SSM_DestroyAttrValue(&value, PR_FALSE);
|
|
loser:
|
|
return rv;
|
|
}
|
|
|
|
|
|
SSMStatus SSMResourceCert_GetAttrIDs(SSMResource *res,
|
|
SSMAttributeID **ids,
|
|
PRIntn *count)
|
|
{
|
|
int i=-1;
|
|
|
|
if (!res || !ids || !count)
|
|
goto loser;
|
|
|
|
/* all certificate attributes accessible to client */
|
|
*count = SSM_FID_CERT_ORG_NAME - SSM_FID_CERT_SUBJECT_NAME + 1;
|
|
*ids = (SSMAttributeID *)PORT_ZAlloc(*count * (sizeof(SSMAttributeID)));
|
|
if (!*ids) goto loser;
|
|
|
|
while (i < *count) {
|
|
(*ids)[i] = (SSMAttributeID) ((int) SSM_FID_CERT_SUBJECT_NAME + i);
|
|
i++;
|
|
}
|
|
return PR_SUCCESS;
|
|
|
|
loser:
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
|
|
SSMStatus
|
|
SSMResourceCert_Create(void *arg, SSMControlConnection * connection,
|
|
SSMResource **res)
|
|
{
|
|
SSMStatus rv = PR_SUCCESS;
|
|
SSMResourceCert * certResource = NULL;
|
|
|
|
if (!res)
|
|
goto loser;
|
|
*res = NULL;
|
|
|
|
if (!arg)
|
|
goto loser;
|
|
|
|
/* before creating a cert, make sure we don't have it already */
|
|
SSMControlConnection_CertLookUp(connection, arg, res);
|
|
if (*res)
|
|
goto done; /* found cert resource! */
|
|
|
|
certResource = (SSMResourceCert *)PR_CALLOC(sizeof(SSMResourceCert));
|
|
if (!certResource)
|
|
goto loser;
|
|
rv = SSMResourceCert_Init(certResource, connection, arg);
|
|
if (rv != PR_SUCCESS) goto loser;
|
|
|
|
*res = (SSMResource *)&certResource->super;
|
|
/* enter cert into cert db */
|
|
rv = SSM_HashInsert(connection->m_certIdDB, (SSMHashKey) arg, (void *)*res);
|
|
if (rv != PR_SUCCESS)
|
|
goto loser;
|
|
|
|
done:
|
|
return PR_SUCCESS;
|
|
loser:
|
|
if (certResource)
|
|
(*((SSMRESOURCE(certResource))->m_destroy_func))
|
|
((SSMResource *)certResource, PR_TRUE);
|
|
else
|
|
if (arg)
|
|
PR_Free(arg);
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
SSMStatus SSMResourceCert_Init(SSMResourceCert * certResource,
|
|
SSMControlConnection * conn,
|
|
void * arg)
|
|
|
|
{
|
|
SSMResource_Init(conn, SSMRESOURCE(certResource), SSM_RESTYPE_CERTIFICATE);
|
|
certResource->cert = (CERTCertificate *)arg;
|
|
if (!arg)
|
|
return SSM_FAILURE;
|
|
|
|
if (certResource->cert->slot)
|
|
PK11_ReferenceSlot(certResource->cert->slot);
|
|
certResource->m_verify_func = &SSMResourceCert_Verify;
|
|
certResource->m_deletecert_func = &SSMResourceCert_DeleteCert;
|
|
certResource->m_markedForDeletion = PR_FALSE;
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMStatus SSMResourceCert_Unpickle(SSMResource ** resource,
|
|
SSMControlConnection * connection,
|
|
PRInt32 len,
|
|
void * value)
|
|
{
|
|
SSMStatus rv = PR_SUCCESS;
|
|
SSMResourceID resID;
|
|
CERTCertificate * cert;
|
|
SECItem certArg;
|
|
|
|
if (!resource || !value)
|
|
goto loser;
|
|
certArg.len = len;
|
|
certArg.data = (unsigned char *) value;
|
|
|
|
cert = CERT_NewTempCertificate(connection->m_certdb,(SECItem *)&certArg,
|
|
NULL, PR_FALSE, PR_TRUE);
|
|
if (!cert) {
|
|
rv = (SSMStatus) PR_GetError();
|
|
goto loser;
|
|
}
|
|
rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, (void *)cert, connection,
|
|
&resID, resource);
|
|
if (rv != PR_SUCCESS) goto loser;
|
|
goto done;
|
|
|
|
loser:
|
|
|
|
if (resource && *resource) {
|
|
SSM_DEBUG("Error unpickling cert: %d.\n", rv);
|
|
((*resource)->m_destroy_func)(*resource, PR_TRUE);
|
|
PR_Free(*resource);
|
|
}
|
|
SSM_DEBUG("Error unpickling cert: %d.\n", rv);
|
|
done:
|
|
return rv;
|
|
}
|
|
|
|
|
|
|
|
SSMStatus SSMResourceCert_Destroy(SSMResource * resource, PRBool doFree)
|
|
{
|
|
SSMResourceCert * res = (SSMResourceCert *)resource;
|
|
SSMResource *tmpRes;
|
|
|
|
if (!res) goto loser;
|
|
SSM_DEBUG("Trying to remove cert with id: %d\n", resource->m_id);
|
|
/* remove cert from the cert resource db */
|
|
SSM_HashRemove(resource->m_connection->m_certIdDB, (SSMHashKey) res->cert,
|
|
(void**)&tmpRes);
|
|
PR_ASSERT(tmpRes == resource);
|
|
|
|
if (res->cert != NULL) {
|
|
if (res->m_markedForDeletion) {
|
|
SSM_DEBUG("Cert id %d is being deleted.\n", resource->m_id);
|
|
if (SSMUI_CertBelongs(res->cert) == myCert) {
|
|
PK11_DeleteTokenCertAndKey(res->cert, res->super.m_connection);
|
|
}
|
|
else {
|
|
SEC_DeletePermCertificate(res->cert);
|
|
}
|
|
}
|
|
else {
|
|
CERT_DestroyCertificate(res->cert);
|
|
}
|
|
res->cert = NULL;
|
|
}
|
|
|
|
/* Destroy superclass */
|
|
SSMResource_Destroy(SSMRESOURCE(res), PR_FALSE);
|
|
|
|
if (doFree)
|
|
PR_Free(res);
|
|
|
|
return PR_SUCCESS;
|
|
loser:
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
SSMStatus SSM_VerifyCert(SSMResourceCert * resource,
|
|
SECCertUsage certUsage)
|
|
{
|
|
return (*resource->m_verify_func)(resource, certUsage);
|
|
}
|
|
|
|
SSMStatus SSM_DeleteCertificate(SSMResourceCert * resource)
|
|
{
|
|
return (*resource->m_deletecert_func)(resource);
|
|
}
|
|
|
|
SSMStatus SSMResourceCert_DeleteCert(SSMResourceCert * res)
|
|
{
|
|
|
|
PR_ASSERT(SSM_IsAKindOf((SSMResource *)res, SSM_RESTYPE_CERTIFICATE));
|
|
if (!res || !res->cert) {
|
|
SSM_DEBUG("DeleteCert: bad argument!\n");
|
|
goto done;
|
|
}
|
|
|
|
SSM_DEBUG("Cert id %d is marked for deletion.\n", ((SSMResource*)res)->m_id);
|
|
SSM_LockResource((SSMResource*)res);
|
|
res->m_markedForDeletion = PR_TRUE; /* delete it from disk */
|
|
SSM_UnlockResource((SSMResource*)res);
|
|
|
|
/* this will get the reference count right */
|
|
SSM_FreeResource((SSMResource*)res);
|
|
|
|
done:
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
|
|
SSMStatus SSMResourceCert_Verify(SSMResourceCert * resource,
|
|
SECCertUsage certUsage)
|
|
{
|
|
if (!resource || !resource->cert)
|
|
goto loser;
|
|
|
|
if (CERT_VerifyCertNow(SSMRESOURCE(resource)->m_connection->m_certdb,
|
|
resource->cert, PR_TRUE,
|
|
certUsage,
|
|
SSMRESOURCE(resource)->m_connection) != SECSuccess)
|
|
goto loser;
|
|
return PR_SUCCESS;
|
|
loser:
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
SSMStatus SSMResourceCert_HTML(SSMResource *res, PRIntn * len, void ** value)
|
|
{
|
|
SSMStatus rv = PR_SUCCESS;
|
|
SSMResourceCert * resource = (SSMResourceCert *)res;
|
|
|
|
if (!resource || !resource->cert || !value) {
|
|
rv = (SSMStatus) PR_INVALID_ARGUMENT_ERROR;
|
|
goto loser;
|
|
}
|
|
*value = NULL;
|
|
if (len) *len = 0;
|
|
|
|
*value = CERT_HTMLCertInfo(resource->cert, PR_FALSE, PR_TRUE);
|
|
if (!*value) {
|
|
rv = (SSMStatus) PR_GetError();
|
|
goto loser;
|
|
}
|
|
|
|
if (len)
|
|
*len = strlen((char *)*value);
|
|
goto done;
|
|
|
|
loser:
|
|
if (len && *len)
|
|
*len = 0;
|
|
if (value && *value)
|
|
*value = NULL;
|
|
|
|
done:
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_CertRenewalHandler(HTTPRequest * req)
|
|
{
|
|
SSMResourceCert * target = (SSMResourceCert *)req->target;
|
|
char * value;
|
|
SSMStatus rv;
|
|
|
|
/* Renew cert action */
|
|
rv = SSM_HTTPParamValue(req, "action", &value);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
if (PL_strcmp(value, "now") == 0) {
|
|
target->m_renewCert = PR_TRUE;
|
|
} else {
|
|
target->m_renewCert = PR_FALSE;
|
|
}
|
|
done:
|
|
SSM_NotifyUIEvent((SSMResource *)target);
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMStatus
|
|
SSMResourceCert_FormSubmitHandler(SSMResource *res, HTTPRequest * req)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char* tmpStr = NULL;
|
|
|
|
/* make sure you got the right baseRef */
|
|
rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
|
|
if (rv != SSM_SUCCESS ||
|
|
PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
|
|
goto loser;
|
|
}
|
|
|
|
rv = SSM_HTTPCloseAndSleep(req);
|
|
if (rv != SSM_SUCCESS)
|
|
SSM_DEBUG("Errors closing window in FormSubmitHandler: %d\n", rv);
|
|
|
|
if (!res->m_formName)
|
|
goto loser;
|
|
if (PL_strcmp(res->m_formName, "cert_edit") == 0)
|
|
rv = SSM_EditCertificateTrustHandler(req);
|
|
else if (PL_strcmp(res->m_formName, "trust_new_ca") == 0)
|
|
rv = SSM_CertCAImportCommandHandler2(req);
|
|
else if (PL_strcmp(res->m_formName, "cert_renewal") == 0) {
|
|
rv = SSM_CertRenewalHandler(req);
|
|
} else {
|
|
SSM_DEBUG("CertResource_FormsubmitHandler: bad formName %s\n", res->m_formName);
|
|
}
|
|
|
|
loser:
|
|
return rv;
|
|
}
|
|
|
|
static
|
|
certPane SSMUI_CertBelongs(CERTCertificate * cert)
|
|
{
|
|
CERTCertTrust * trust;
|
|
certPane owner = badCert;
|
|
|
|
if (!cert || !cert->trust)
|
|
goto done;
|
|
trust = cert->trust;
|
|
|
|
if ((trust->sslFlags & CERTDB_USER) ||
|
|
(trust->emailFlags & CERTDB_USER) ||
|
|
(trust->objectSigningFlags & CERTDB_USER))
|
|
owner = myCert;
|
|
else if ((trust->sslFlags & CERTDB_VALID_CA) ||
|
|
(trust->emailFlags & CERTDB_VALID_CA) ||
|
|
(trust->objectSigningFlags & CERTDB_VALID_CA))
|
|
owner = caCert;
|
|
else if (trust->sslFlags & CERTDB_VALID_PEER)
|
|
owner = webCert;
|
|
else if (trust->emailFlags & CERTDB_VALID_PEER)
|
|
owner = othersCert;
|
|
done:
|
|
return owner;
|
|
}
|
|
|
|
/*
|
|
* Find correct help target for the kind of cert we're deleting.
|
|
*/
|
|
SSMStatus SSM_DeleteCertHelpKeywordHandler(SSMTextGenContext * cx)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
certPane kind = badCert;
|
|
PR_ASSERT(cx != NULL);
|
|
PR_ASSERT(cx->m_request != NULL);
|
|
PR_ASSERT(cx->m_params != NULL);
|
|
PR_ASSERT(cx->m_result != NULL);
|
|
PR_ASSERT(SSM_IsAKindOf(cx->m_request->target, SSM_RESTYPE_CERTIFICATE));
|
|
|
|
kind = SSMUI_CertBelongs(((SSMResourceCert *)cx->m_request->target)->cert);
|
|
switch (kind) {
|
|
case caCert:
|
|
rv = SSM_GetAndExpandText(cx, "help_delete_ca", &cx->m_result);
|
|
break;
|
|
case myCert:
|
|
rv = SSM_GetAndExpandText(cx, "help_delete_mine", &cx->m_result);
|
|
break;
|
|
case webCert:
|
|
rv = SSM_GetAndExpandText(cx, "help_delete_websites", &cx->m_result);
|
|
break;
|
|
case othersCert:
|
|
rv = SSM_GetAndExpandText(cx, "help_delete_others", &cx->m_result);
|
|
break;
|
|
default:
|
|
SSM_DEBUG("DeleteCertHelpKeyword: can't figure out cert type!\n");
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus SSM_DeleteCertWarnKeywordHandler(SSMTextGenContext * cx)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
certPane kind = badCert;
|
|
|
|
PR_ASSERT(cx != NULL);
|
|
PR_ASSERT(cx->m_request != NULL);
|
|
PR_ASSERT(cx->m_params != NULL);
|
|
PR_ASSERT(cx->m_result != NULL);
|
|
PR_ASSERT(SSM_IsAKindOf(cx->m_request->target, SSM_RESTYPE_CERTIFICATE));
|
|
|
|
kind = SSMUI_CertBelongs(((SSMResourceCert *)cx->m_request->target)->cert);
|
|
switch (kind) {
|
|
case othersCert:
|
|
rv = SSM_GetAndExpandText(cx, "delete_cert_warning_others", &cx->m_result);
|
|
break;
|
|
case myCert:
|
|
rv = SSM_GetAndExpandText(cx, "delete_cert_warning_mine", &cx->m_result);
|
|
break;
|
|
case caCert:
|
|
rv = SSM_GetAndExpandText(cx, "delete_cert_warning_ca", &cx->m_result);
|
|
break;
|
|
case webCert:
|
|
rv = SSM_GetAndExpandText(cx, "delete_cert_warning_web", &cx->m_result);
|
|
break;
|
|
default:
|
|
SSM_DEBUG("DeleteCertWarnKeyword: can't figure out cert type!\n");
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
|
|
|
|
SSMStatus SSM_DeleteCertHandler(HTTPRequest * req)
|
|
{
|
|
SSMStatus rv;
|
|
char * value = NULL;
|
|
char * nickname = NULL;
|
|
|
|
/* if this brakes, we're in deep trouble */
|
|
PR_ASSERT(SSM_IsAKindOf(req->target, SSM_RESTYPE_CERTIFICATE));
|
|
|
|
/* close the window */
|
|
rv = SSM_HTTPCloseAndSleep(req);
|
|
if (rv != SSM_SUCCESS)
|
|
SSM_DEBUG("DeleteCertHandler: Problem closing DeleteCertificateWindow!\n");
|
|
|
|
/* check which button was clicked */
|
|
rv = SSM_HTTPParamValue(req, "do_cancel", &value);
|
|
if (rv == SSM_SUCCESS) {
|
|
req->ctrlconn->super.super.m_buttonType = SSM_BUTTON_CANCEL;
|
|
goto done;
|
|
}
|
|
|
|
rv = SSM_HTTPParamValue(req, "do_ok", &value);
|
|
if (rv == SSM_SUCCESS) {
|
|
if (((SSMResourceCert *)req->target)->cert->nickname)
|
|
nickname = PL_strdup(((SSMResourceCert *)req->target)->cert->nickname);
|
|
else nickname = PL_strdup(((SSMResourceCert *)req->target)->cert->emailAddr);
|
|
rv = (SSMStatus) SSM_DeleteCertificate((SSMResourceCert *)req->target);
|
|
/* delete this cert from Security Advisor hashtable */
|
|
rv = SSM_ChangeCertSecAdvisorList(req, nickname, (ssmCertHashAction)-1);
|
|
PR_Free(nickname);
|
|
goto done;
|
|
}
|
|
SSM_DEBUG("DeleteCertHandler: can't figure out which button was clicked in DeleteCert dialog!\n");
|
|
|
|
done:
|
|
SSM_NotifyUIEvent(&req->ctrlconn->super.super);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus SSM_ProcessCertDeleteButton(HTTPRequest * req)
|
|
{
|
|
SSMResource * target;
|
|
char * params = NULL;
|
|
char * certNickname = NULL, * formName = NULL;
|
|
char * page = NULL, * outPage = NULL;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
|
|
rv = SSM_HTTPParamValue(req, "selectCert", &certNickname);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_HTTPParamValue(req, "formName", &formName);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* Get the target resource. */
|
|
target = (req->target ? req->target : (SSMResource *) req->ctrlconn);
|
|
PR_ASSERT(target);
|
|
|
|
params = PR_smprintf("action=delete_cert&nick=%s&formName=%s",certNickname,
|
|
formName);
|
|
SSM_LockUIEvent(&req->ctrlconn->super.super);
|
|
rv = SSMControlConnection_SendUIEvent(req->ctrlconn, "cert", "delete_cert",
|
|
target, params,
|
|
&target->m_clientContext, PR_TRUE);
|
|
SSM_WaitUIEvent(&req->ctrlconn->super.super, PR_INTERVAL_NO_TIMEOUT);
|
|
/* See if the user canceled, if so send back HTTP_NO_CONTENT
|
|
* so security advisor doesn't redraw the same content.
|
|
*/
|
|
if (req->ctrlconn->super.super.m_buttonType == SSM_BUTTON_CANCEL) {
|
|
SSM_HTTPReportError(req, HTTP_NO_CONTENT);
|
|
goto done;
|
|
}
|
|
/* tell the secadvisor page to reload */
|
|
rv = SSM_RefreshRefererPage(req);
|
|
goto done;
|
|
|
|
loser:
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
SSM_HTTPReportSpecificError(req,
|
|
"ProcessDeleteCert: can't send/process delete cert UIEvent", rv);
|
|
|
|
done:
|
|
PR_FREEIF(params);
|
|
PR_FREEIF(page);
|
|
PR_FREEIF(outPage);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus SSM_RefreshRefererPage(HTTPRequest * req)
|
|
{
|
|
SSMTextGenContext * cx = NULL;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char * page = NULL, * outPage = NULL, * ptr = NULL;
|
|
|
|
if (!req)
|
|
goto done;
|
|
|
|
/* ptr will point the last '/' in the referer URL. We are interested
|
|
* in everything AFTER the last '/'.
|
|
*/
|
|
ptr = strrchr(req->referer, '/');
|
|
|
|
rv = SSMTextGen_NewTopLevelContext(req, &cx);
|
|
rv = SSM_GetAndExpandText(cx, "refresh_window_content", &page);
|
|
SSMTextGen_DestroyContext(cx);
|
|
outPage = PR_smprintf(page, ptr+1);
|
|
req->sentResponse = PR_TRUE;
|
|
rv = SSM_HTTPSendOKHeader(req, NULL, "text/html");
|
|
rv = SSM_HTTPSendUTF8String(req, outPage);
|
|
|
|
done:
|
|
return rv;
|
|
}
|
|
|
|
|
|
SSMStatus SSM_HTTPCertListHandler(HTTPRequest * req)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char * nick = NULL, * action = NULL, *target, * page=NULL, *outPage = NULL;
|
|
char * nickhtml = NULL, * formName = NULL;
|
|
CERTCertificate * cert;
|
|
CERTCertList * certList = NULL;
|
|
SSMTextGenContext * cx;
|
|
PRBool emailCert = PR_FALSE;
|
|
char * certres;
|
|
SSMResource * certresource;
|
|
SSMResourceCert * certRes;
|
|
SSM_DEBUG("In cert_list handler\n");
|
|
|
|
/* figure out the certificate */
|
|
|
|
/* this is a cert identified by resource id */
|
|
rv = SSM_HTTPParamValue(req, "certresource", &certres);
|
|
if (rv == SSM_SUCCESS) {
|
|
rv = SSM_RIDTextToResource(req, certres, &certresource);
|
|
if (rv != SSM_SUCCESS || !certresource
|
|
|| !(SSM_IsAKindOf(certresource, SSM_RESTYPE_CERTIFICATE))) {
|
|
SSM_DEBUG("certListHandler:can't find cert by resource ID %s!\n", certres);
|
|
goto loser;
|
|
}
|
|
|
|
certRes = ((SSMResourceCert *)certresource);
|
|
rv = SSM_ProcessCertResourceUIAction(req, certRes);
|
|
goto done;
|
|
}
|
|
|
|
rv = SSM_HTTPParamValue(req, "target", &target);
|
|
if (rv != SSM_SUCCESS)
|
|
/* can't find target */
|
|
goto loser;
|
|
|
|
rv = SSM_HTTPParamValue(req, "nick", &nick);
|
|
if (rv != SSM_SUCCESS || PL_strcmp(nick,"undefined")==0) {
|
|
/* can't find cert selection */
|
|
SSM_DEBUG("certListHandler: can't find cert nick!\n");
|
|
goto loser;
|
|
}
|
|
|
|
nickhtml = SSM_ConvertStringToHTMLString(nick);
|
|
if (!nickhtml) {
|
|
SSM_DEBUG("HTTPCertListHandler: error in ConvertStringToHTMLString\n");
|
|
goto loser;
|
|
}
|
|
rv = SSM_HTTPParamValue(req, "formName", &formName);
|
|
if (rv != SSM_SUCCESS || !formName) {
|
|
SSM_DEBUG("certListHandler: no originating formName found!\n");
|
|
goto loser;
|
|
}
|
|
|
|
/* look for certs by nickname, unless it's "others",
|
|
* then check email address
|
|
*/
|
|
if (strstr(formName,"_others"))
|
|
emailCert = PR_TRUE;
|
|
|
|
certList = SSMControlConnection_CreateCertListByNickname(req->ctrlconn,
|
|
nick,
|
|
emailCert);
|
|
if (certList && SSM_CertListCount(certList) > 1)
|
|
{ /* more than one cert under the same nickname */
|
|
|
|
/* get current values */
|
|
rv = SSM_HTTPParamValue(req, "action", &action);
|
|
if (rv != SSM_SUCCESS) {
|
|
/* can't find action selection */
|
|
goto loser;
|
|
}
|
|
|
|
rv = SSMTextGen_NewTopLevelContext(req, &cx);
|
|
rv = SSM_GetAndExpandText(cx, "choose_cert_content", &page);
|
|
SSMTextGen_DestroyContext(cx);
|
|
outPage = PR_smprintf(page, atoi(target), action, nickhtml, formName);
|
|
rv = SSM_HTTPSendOKHeader(req, NULL, "text/html");
|
|
rv = SSM_HTTPSendUTF8String(req, outPage);
|
|
|
|
}
|
|
else
|
|
{
|
|
/* get selected certificate */
|
|
cert = SSMControlConnection_FindCertByNickname(req->ctrlconn, nick,
|
|
emailCert);
|
|
if (!cert) {
|
|
SSM_DEBUG("HTTPCertListHandler: can't find cert with nick %s!\n",nick);
|
|
goto loser;
|
|
}
|
|
rv = SSM_ProcessCertUIAction(req, cert);
|
|
}
|
|
done:
|
|
PR_FREEIF(page);
|
|
PR_FREEIF(outPage);
|
|
PR_FREEIF(nickhtml);
|
|
if (certList)
|
|
CERT_DestroyCertList(certList);
|
|
|
|
return rv;
|
|
|
|
loser:
|
|
if (certList)
|
|
CERT_DestroyCertList(certList);
|
|
|
|
/* kill the window */
|
|
rv = SSMTextGen_NewTopLevelContext(req, &cx);
|
|
rv = SSM_GetAndExpandText(cx, "windowclose_doclose_js_content", &page);
|
|
SSMTextGen_DestroyContext(cx);
|
|
req->sentResponse = PR_TRUE;
|
|
rv = SSM_HTTPSendOKHeader(req, NULL, "text/html");
|
|
rv = SSM_HTTPSendUTF8String(req, page);
|
|
/* notify owner if this a UI event */
|
|
if (((SSMResource *)req->ctrlconn)->m_UILock)
|
|
SSM_NotifyUIEvent((SSMResource *)req->ctrlconn);
|
|
|
|
return SSM_SUCCESS;
|
|
|
|
}
|
|
|
|
SSMStatus SSM_ProcessCertResourceUIAction(HTTPRequest * req,
|
|
SSMResourceCert * certres)
|
|
{
|
|
SSMResourceID resID;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char * page = NULL, *outPage = NULL;
|
|
char * action, *ref;
|
|
SSMTextGenContext * cx = NULL;
|
|
|
|
/* Free reference to the previous target
|
|
*/
|
|
if (req->target) {
|
|
SSM_FreeResource(req->target);
|
|
}
|
|
req->target = &certres->super;
|
|
/*
|
|
* Sigh, this is so hacked up that the only way I can prevent a crash now
|
|
* is to get an extra reference here so the target doesn't disappear.
|
|
* -javi
|
|
*/
|
|
SSM_GetResourceReference(req->target);
|
|
resID = certres->super.m_id;
|
|
/* figure out what action was requested */
|
|
rv = SSM_HTTPParamValue(req, "action", &action);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("ProcessCertUIAction: no action parameter found!\n");
|
|
SSM_HTTPReportError(req, HTTP_NO_CONTENT);
|
|
goto done;
|
|
}
|
|
ref = PR_smprintf("%s_content", action);
|
|
rv = SSMTextGen_NewTopLevelContext(req, &cx);
|
|
if (rv != SSM_SUCCESS)
|
|
SSM_DEBUG("ProcessUIAction: can't get new TopLevelContext\n");
|
|
rv = SSM_GetAndExpandText(cx, ref, &page);
|
|
if (rv != SSM_SUCCESS)
|
|
SSM_DEBUG("ProcessUIAction:can't get wrapper for %s\n", action);
|
|
SSMTextGen_DestroyContext(cx);
|
|
outPage = PR_smprintf(page, resID, action, "bogus");
|
|
rv = SSM_HTTPSendOKHeader(req, NULL, "text/html");
|
|
rv = SSM_HTTPSendUTF8String(req, outPage);
|
|
|
|
done:
|
|
PR_FREEIF(page);
|
|
PR_FREEIF(outPage);
|
|
return rv;
|
|
}
|
|
|
|
|
|
SSMStatus
|
|
SSM_ProcessCertUIAction(HTTPRequest * req, CERTCertificate * cert)
|
|
{
|
|
SSMResourceCert * certres = NULL;
|
|
SSMStatus rv;
|
|
SSMResourceID resID;
|
|
|
|
if (!cert) {
|
|
SSM_DEBUG("ProcessCertUIAction: no cert. Either user hit Cancel or smth is wrong.\n");
|
|
SSM_DEBUG("Close the window \n");
|
|
goto done;
|
|
}
|
|
|
|
/* get a resource for this cert */
|
|
rv = (SSMStatus) SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, (void *)cert,
|
|
req->ctrlconn, &resID, (SSMResource**)&certres);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
/*
|
|
* XXX This is a gross hack. But, iff the previous target was another
|
|
* certificate, release the reference so that reference counts will
|
|
* stay in sync.
|
|
*/
|
|
if (SSM_IsAKindOf(req->target, SSM_RESTYPE_CERTIFICATE)) {
|
|
SSM_FreeResource(req->target);
|
|
}
|
|
return SSM_ProcessCertResourceUIAction(req, certres);
|
|
done:
|
|
return rv;
|
|
}
|
|
|
|
|
|
char * digits = "0123456789ABCDEF";
|
|
#define HEX_DIGIT(x) (strchr(digits, *x) - digits)
|
|
|
|
SECItem *
|
|
unhexify(char * hex)
|
|
{
|
|
SECItem * result = NULL;
|
|
char * data = NULL;
|
|
char * ptr, *ch;
|
|
PRIntn len;
|
|
|
|
if (!hex)
|
|
return NULL;
|
|
|
|
result = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
|
|
|
|
ch = hex;
|
|
len = strlen(hex)/2;
|
|
if (strlen(hex)&1)
|
|
len++;
|
|
|
|
ptr = data = (char *) PORT_ZAlloc(len);
|
|
if (strlen(hex)&1) {
|
|
*ptr = HEX_DIGIT(ch);
|
|
ptr++;
|
|
ch++;
|
|
}
|
|
|
|
|
|
while (*ch) {
|
|
*ptr = (HEX_DIGIT(ch) << 4) + HEX_DIGIT((ch+1));
|
|
ch += 2;
|
|
ptr++;
|
|
}
|
|
result->data = (unsigned char *) data;
|
|
result->len = len;
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* Here's how we do unhexify -jp
|
|
* Number[J]=HexDigit(*P)*16+HexDigit(*(P+1));
|
|
* J++;
|
|
* P+=2;
|
|
* char *Digits="012345679ABCDEF"
|
|
*return(strchr(Digits,toupper(Char))-Digits)
|
|
*/
|
|
|
|
SSMStatus SSM_ChooseCertUsageHandler(HTTPRequest * req)
|
|
{
|
|
SSMResource * target = NULL, *origTarget;
|
|
char * value = NULL, * nick = NULL, *serialNum;
|
|
char * tmp;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
SECItem * keyID;
|
|
CERTCertificate * cert = NULL;
|
|
SSMTextGenContext * cx;
|
|
char * urlStr=NULL, *action=NULL, * redirectHTML=NULL, * outStr=NULL;
|
|
SSMResourceID resID;
|
|
char * windowName = NULL, * params = NULL;
|
|
|
|
/* Get the target resource. */
|
|
target = (req->target ? req->target : (SSMResource *) req->ctrlconn);
|
|
PR_ASSERT(target);
|
|
origTarget = target;
|
|
rv = SSM_HTTPParamValue(req, "selectItem", &value);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_HTTPParamValue(req, "nick", &nick);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
rv = SSM_HTTPParamValue(req, "baseRef", &action);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
tmp = PL_strdup(value);
|
|
value = strtok(tmp, ":");
|
|
serialNum = strtok(NULL, ":");
|
|
keyID = unhexify(value);
|
|
cert = FindCertByKeyIDAndNickname(req->ctrlconn, nick, keyID, serialNum);
|
|
SECITEM_FreeItem(keyID,PR_TRUE);
|
|
PR_Free(tmp);
|
|
|
|
SSM_DEBUG("ChooseCertUsageHandler: found certificate %lx!\n", cert);
|
|
|
|
req->ctrlconn->super.super.m_uiData = (void *)cert;
|
|
|
|
/* set the window name:
|
|
* View is done through http thread, window name is popup
|
|
* Delete is done with UIEvent, window name is PSM
|
|
*/
|
|
if (PL_strcmp(action, "cert_view") == 0 ||
|
|
PL_strcmp(action, "ca_policy_view") == 0)
|
|
windowName = PR_smprintf("popup");
|
|
else if (PL_strcmp(action, "delete_cert") == 0)
|
|
windowName = PR_smprintf("PSM");
|
|
else if (PL_strcmp(action, "backup") == 0)
|
|
windowName = NULL;
|
|
else if (PL_strcmp(action, "cert_edit") == 0)
|
|
windowName = PR_smprintf("popup");
|
|
else {
|
|
SSM_DEBUG("ChooseCertUsageHandler: bad action baseRef = %s", action);
|
|
goto loser;
|
|
}
|
|
|
|
/* make sure the next URL takes up the whole window */
|
|
rv = SSMTextGen_NewTopLevelContext(req, &cx);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("ChooseCertUsageHandler: can't get new textGen context\n");
|
|
goto loser;
|
|
}
|
|
rv = (SSMStatus) SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, (void *)cert,
|
|
req->ctrlconn, &resID, &target);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("ChooseCertUsageHandler: can't create cert resource \n");
|
|
goto loser;
|
|
}
|
|
if (!MIN_STRCMP(action, "backup")) {
|
|
rv = SSM_GetAndExpandText(cx, "windowclose_doclose_js_content", &outStr);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
SSM_NotifyUIEvent(origTarget);
|
|
} else {
|
|
|
|
/* policy view requires extra parameters */
|
|
if (PL_strcmp(action, "ca_policy_view") == 0)
|
|
params = PR_smprintf("&certresource=%d&bogus=bogus", resID);
|
|
|
|
urlStr = PR_smprintf("get?baseRef=%s&target=%d%s", action, resID, params?params:"");
|
|
|
|
rv = SSM_GetAndExpandText(cx, "refresh_frameset_content", &redirectHTML);
|
|
if (rv != SSM_SUCCESS)
|
|
SSM_DEBUG("ChooseCertUsageHandler: can't create redirectHTML");
|
|
outStr = PR_smprintf(redirectHTML, urlStr, windowName);
|
|
SSMTextGen_DestroyContext(cx);
|
|
cx = NULL;
|
|
PR_Free(urlStr);
|
|
PR_Free(redirectHTML);
|
|
}
|
|
req->sentResponse = PR_TRUE;
|
|
rv = SSM_HTTPSendOKHeader(req, NULL, "text/html");
|
|
if (rv != SSM_SUCCESS)
|
|
SSM_DEBUG("ChooseCertUsageHandler: error sending OKHeaders\n");
|
|
rv = SSM_HTTPSendUTF8String(req, outStr);
|
|
if (rv != SSM_SUCCESS)
|
|
SSM_DEBUG("ChooseCertUsageHandler: error sending <%s>\n", outStr);
|
|
PR_FREEIF(windowName);
|
|
PR_Free(outStr);
|
|
if (cx != NULL)
|
|
SSMTextGen_DestroyContext(cx);
|
|
return rv;
|
|
loser:
|
|
if (cx != NULL)
|
|
SSMTextGen_DestroyContext(cx);
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
SSM_DEBUG("ChooseCertUsageHandler: somethings is very wrong!\n");
|
|
return SSM_HTTPCloseWindow(req);
|
|
}
|
|
|
|
CERTCertificate *
|
|
FindCertByKeyIDAndNickname(SSMControlConnection * ctrl, char *nickname,
|
|
SECItem *keyID, char * serial)
|
|
{
|
|
CERTCertificate *cert = NULL;
|
|
CERTCertList *certList = NULL;
|
|
CERTCertListNode *node;
|
|
char *hexSerial=NULL;
|
|
|
|
certList = SSMControlConnection_CreateCertListByNickname(ctrl, nickname,
|
|
PR_FALSE);
|
|
if (!certList) /* could not find certs with this nick, try email address */
|
|
certList = SSMControlConnection_CreateCertListByNickname(ctrl, nickname,
|
|
PR_TRUE);
|
|
if (!certList)
|
|
goto loser;
|
|
|
|
node = CERT_LIST_HEAD(certList);
|
|
while (!CERT_LIST_END(node, certList)) {
|
|
if (cert_GetKeyID(node->cert) != SECSuccess)
|
|
goto loser;
|
|
hexSerial = CERT_Hexify(&node->cert->serialNumber, 0);
|
|
if ( SECITEM_CompareItem(keyID, &node->cert->subjectKeyID) == SECEqual &&
|
|
(hexSerial == NULL ||
|
|
strcmp(hexSerial, serial) == 0)) {
|
|
PR_FREEIF(hexSerial);
|
|
goto found;
|
|
}
|
|
PR_FREEIF(hexSerial);
|
|
node = CERT_LIST_NEXT(node);
|
|
}
|
|
|
|
SSM_DEBUG("FindCertByKeyIDAndNickname: could not find certificate!\n");
|
|
goto loser;
|
|
|
|
found:
|
|
cert = CERT_DupCertificate(node->cert);
|
|
|
|
loser:
|
|
if (certList)
|
|
CERT_DestroyCertList(certList);
|
|
return cert;
|
|
|
|
}
|
|
|
|
static SSMStatus
|
|
SSM_DoOCSPError(SSMTextGenContext *cx, CERTCertificate *cert,
|
|
const char* textKey)
|
|
{
|
|
SSMStatus rv;
|
|
char *tmp=NULL, *url=NULL;
|
|
|
|
rv = SSM_GetAndExpandText(cx, textKey, &tmp);
|
|
if (rv == SSM_SUCCESS) {
|
|
PR_FREEIF(cx->m_result);
|
|
url = SSM_GetOCSPURL(cert, cx->m_request->target->m_connection->m_prefs);
|
|
PR_ASSERT(url != NULL);
|
|
cx->m_result = PR_smprintf(tmp, url);
|
|
PR_Free(url);
|
|
}
|
|
PR_FREEIF(tmp);
|
|
return rv;
|
|
}
|
|
|
|
static SSMStatus
|
|
SSM_BuildErrorMessage(SSMTextGenContext *cx, SSMResourceCert *certres)
|
|
{
|
|
PRErrorCode err;
|
|
SECCertUsage certUsage;
|
|
SSMStatus rv;
|
|
|
|
if (ssm_cert_belongs_type(certres->cert, USER_CERT) == SSM_SUCCESS) {
|
|
certUsage = certUsageEmailRecipient;
|
|
} else
|
|
if (ssm_cert_belongs_type(certres->cert, EMAIL_CERT) == SSM_SUCCESS) {
|
|
certUsage = certUsageEmailRecipient;
|
|
} else
|
|
if (ssm_cert_belongs_type(certres->cert, CA_CERT) == SSM_SUCCESS) {
|
|
certUsage = certUsageSSLCA;
|
|
} else
|
|
if (ssm_cert_belongs_type(certres->cert, WEBSITE_CERT) == SSM_SUCCESS) {
|
|
certUsage = certUsageSSLServer;
|
|
}
|
|
|
|
if (SSM_VerifyCert(certres, certUsage) != SECSuccess) {
|
|
err = PR_GetError();
|
|
switch (err) {
|
|
case SEC_ERROR_EXPIRED_CERTIFICATE:
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_expired_cert_text",
|
|
&cx->m_result);
|
|
break;
|
|
case SEC_ERROR_REVOKED_CERTIFICATE:
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_revoked_cert_text",
|
|
&cx->m_result);
|
|
break;
|
|
case SEC_ERROR_UNKNOWN_ISSUER:
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_unknown_issuer_text",
|
|
&cx->m_result);
|
|
break;
|
|
case SEC_ERROR_CA_CERT_INVALID:
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_ca_invalid_text",
|
|
&cx->m_result);
|
|
break;
|
|
case SEC_ERROR_UNTRUSTED_ISSUER:
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_untrusted_issuer_text",
|
|
&cx->m_result);
|
|
break;
|
|
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_expired_issuer_text",
|
|
&cx->m_result);
|
|
break;
|
|
case SEC_ERROR_UNTRUSTED_CERT:
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_untrusted_cert_text",
|
|
&cx->m_result);
|
|
break;
|
|
case SEC_ERROR_CERT_BAD_ACCESS_LOCATION:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "not_verified_bad_ocsp_url");
|
|
break;
|
|
case SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE:
|
|
rv = SSM_DoOCSPError(cx, certres->cert,
|
|
"not_verified_unknown_ocsp_response_type");
|
|
break;
|
|
case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE:
|
|
rv = SSM_DoOCSPError(cx, certres->cert,
|
|
"bad_ocsp_http_response");
|
|
break;
|
|
case SEC_ERROR_OCSP_SERVER_ERROR:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_server_error");
|
|
break;
|
|
case SEC_ERROR_OCSP_MALFORMED_REQUEST:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "bad_ocsp_der");
|
|
break;
|
|
case SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_unauthorized_responder");
|
|
break;
|
|
case SEC_ERROR_OCSP_TRY_SERVER_LATER:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_try_server_later");
|
|
break;
|
|
case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_response_needs_sig");
|
|
break;
|
|
case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_unauthorized_request");
|
|
break;
|
|
case SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_unknown_status");
|
|
break;
|
|
case SEC_ERROR_OCSP_UNKNOWN_CERT:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_unknown_cert");
|
|
break;
|
|
case SEC_ERROR_OCSP_NOT_ENABLED:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_not_enabled");
|
|
break;
|
|
case SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_no_default_responder");
|
|
break;
|
|
case SEC_ERROR_OCSP_MALFORMED_RESPONSE:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_malformed_response");
|
|
break;
|
|
case SEC_ERROR_OCSP_FUTURE_RESPONSE:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_future_response");
|
|
break;
|
|
case SEC_ERROR_OCSP_OLD_RESPONSE:
|
|
rv = SSM_DoOCSPError(cx, certres->cert, "ocsp_old_response");
|
|
break;
|
|
case PR_DIRECTORY_LOOKUP_ERROR:
|
|
/* Add some extra logic because NSS doesn't always set error
|
|
* codes for OCSP failures.
|
|
*/
|
|
if (SSM_IsOCSPEnabled(certres->super.m_connection)) {
|
|
rv = SSM_DoOCSPError(cx, certres->cert,
|
|
"not_verified_bad_ocsp_url");
|
|
break;
|
|
}
|
|
default:
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_unknown_error_text",
|
|
&cx->m_result);
|
|
}
|
|
} else {
|
|
rv = SSM_GetAndExpandText(cx, "not_verified_unknown_error_text",
|
|
&cx->m_result);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_VerifyCertKeywordHandler(SSMTextGenContext * cx)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
SSMResourceCert * certres = NULL;
|
|
/* All the certUsage values currently defined in NSS */
|
|
/* All of these strings should come from the properties files. */
|
|
char * formatKey = NULL, * fmt = NULL;
|
|
PRBool verified[12];
|
|
char * result = NULL;
|
|
PRInt32 i, j;
|
|
PRBool valid = PR_FALSE;
|
|
|
|
PR_ASSERT(cx != NULL);
|
|
PR_ASSERT(cx->m_request != NULL);
|
|
PR_ASSERT(cx->m_params != NULL);
|
|
PR_ASSERT(cx->m_result != NULL);
|
|
PR_ASSERT(SSM_IsAKindOf(cx->m_request->target, SSM_RESTYPE_CERTIFICATE));
|
|
|
|
/* get certificate resource */
|
|
certres = (SSMResourceCert *)cx->m_request->target;
|
|
|
|
for (i = 0, j= 0; i < certUsageAnyCA + 1; i++) {
|
|
/* UserCertImport, ProtectedObjectSigner, AnyCA, VerifyCA certUsages
|
|
* cause NSS to panic, make sure we don't try to verify it.
|
|
*/
|
|
if (i == certUsageUserCertImport ||
|
|
i == certUsageProtectedObjectSigner ||
|
|
i == certUsageVerifyCA ||
|
|
i == certUsageAnyCA) {
|
|
verified[i] = PR_FALSE;
|
|
continue;
|
|
}
|
|
if (SSM_VerifyCert(certres, (SECCertUsage) i) == SECSuccess) {
|
|
verified[i] = PR_TRUE;
|
|
valid = PR_TRUE;
|
|
}
|
|
else verified[i] = PR_FALSE;
|
|
}
|
|
|
|
if (valid) {
|
|
rv = SSM_GetAndExpandText(cx, "verified_prefix",
|
|
&cx->m_result);
|
|
} else {
|
|
rv = SSM_BuildErrorMessage(cx, certres);
|
|
}
|
|
formatKey = (char *) SSM_At(cx->m_params, (PRIntn)0);
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, formatKey, &fmt);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
result = PR_smprintf(fmt, verified[0], verified[1], verified[2],
|
|
verified[3], verified[4], verified[5],
|
|
verified[6], verified[7], verified[8],
|
|
verified[9], verified[10], verified[11], valid);
|
|
rv = SSM_ConcatenateUTF8String(&cx->m_result, result);
|
|
PR_Free(result);
|
|
rv = SSM_SUCCESS;
|
|
goto done;
|
|
|
|
loser:
|
|
SSM_DEBUG("VerifyCertKeywordHandler: something is wrong!\n");
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
if (cx->m_result)
|
|
PR_Free(cx->m_result);
|
|
cx->m_result = NULL;
|
|
done:
|
|
PR_FREEIF(fmt);
|
|
return rv;
|
|
}
|
|
|
|
|
|
SSMStatus
|
|
SSM_EditCertKeywordHandler(SSMTextGenContext * cx)
|
|
{
|
|
SSMStatus rv;
|
|
SSMResourceCert * target = (SSMResourceCert *)SSMTextGen_GetTargetObject(cx);
|
|
CERTCertTrust * trust;
|
|
char * tmpStr = NULL, *checked = NULL, *notAvailable = NULL, * donot= NULL;
|
|
PRBool trusted=PR_FALSE, trustca = PR_FALSE;
|
|
PRBool emailtrust=PR_FALSE, signtrust=PR_FALSE, ssltrust = PR_FALSE;
|
|
/* edit cert dialog help targets */
|
|
char * emailCertHelpTarget = "1036027";
|
|
char * sslCertHelpTarget = "1035916";
|
|
char * caCertHelpTarget = "1036857";
|
|
|
|
|
|
PR_ASSERT(target && SSM_IsAKindOf((SSMResource *)target, SSM_RESTYPE_CERTIFICATE));
|
|
PR_ASSERT(target->cert);
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "text_checked", &checked);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("EditCertKeywordHandler: can't get text for 'checked'\n");
|
|
goto done;
|
|
}
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "trust_do_not", &donot);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("EditCertKeywordHandler: can't get text for 'trust_do_not'\n");
|
|
goto done;
|
|
}
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "text_not_available",
|
|
¬Available);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("EditCertKeywordHandler: can't get text for notAvailable\n");
|
|
goto done;
|
|
}
|
|
if ((trust = target->cert->trust) == NULL) {
|
|
SSM_DEBUG("EditCertKeywordHandler: cert trust object is NULL!\n");
|
|
rv = SSM_FAILURE;
|
|
goto done;
|
|
}
|
|
|
|
/* website cert */
|
|
if (trust->sslFlags & CERTDB_VALID_PEER) {
|
|
CERTCertificate * issuer = CERT_FindCertIssuer(target->cert, PR_Now(),
|
|
certUsageAnyCA);
|
|
if (issuer && issuer->trust &&
|
|
(issuer->trust->sslFlags & CERTDB_TRUSTED_CA))
|
|
trustca = PR_TRUE;
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "edit_cert_website", &tmpStr);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("EditCertKeywordHandler: can't find edit_cert_website \n");
|
|
goto done;
|
|
}
|
|
/* check first button if trusted, second if not */
|
|
if (trust->sslFlags & CERTDB_TRUSTED)
|
|
trusted = PR_TRUE;
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = PR_smprintf(tmpStr, target->cert->nickname,
|
|
CERT_GetCommonName(&target->cert->issuer),
|
|
issuer?issuer->nickname:notAvailable,
|
|
trusted?checked:"",
|
|
trusted?"":checked,
|
|
sslCertHelpTarget,
|
|
trustca?"":donot,
|
|
trustca?"":donot);
|
|
|
|
} else if ( (trust->sslFlags & CERTDB_VALID_CA) ||
|
|
(trust->emailFlags & CERTDB_VALID_CA ) ||
|
|
( trust->objectSigningFlags & CERTDB_VALID_CA )) {
|
|
|
|
/* security advisor in 4.x does this, should we? */
|
|
if ( ! ( target->cert->nsCertType & NS_CERT_TYPE_CA ) )
|
|
target->cert->nsCertType = NS_CERT_TYPE_CA;
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "edit_cert_authority", &tmpStr);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("EditCertKeywordHandler: can't get edit_cert_authority wrapper\n");
|
|
goto done;
|
|
}
|
|
|
|
/* check first button if trusted, second if not */
|
|
if (trust->sslFlags & CERTDB_TRUSTED_CA)
|
|
ssltrust = PR_TRUE;
|
|
if (trust->emailFlags & CERTDB_TRUSTED_CA)
|
|
emailtrust = PR_TRUE;
|
|
if (trust->objectSigningFlags & CERTDB_TRUSTED_CA )
|
|
signtrust = PR_TRUE;
|
|
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = PR_smprintf(tmpStr, ssltrust?checked:"",
|
|
emailtrust?checked:"",
|
|
signtrust?checked:"",
|
|
target->cert->nickname,
|
|
caCertHelpTarget);
|
|
} else if (trust->emailFlags & CERTDB_VALID_PEER) {
|
|
CERTCertificate * issuer = CERT_FindCertIssuer(target->cert, PR_Now(),
|
|
certUsageAnyCA);
|
|
char *CN = NULL;
|
|
if (issuer && issuer->trust &&
|
|
(issuer->trust->emailFlags & CERTDB_TRUSTED_CA))
|
|
trustca = PR_TRUE;
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "edit_cert_others", &tmpStr);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("EditCertKeywordHandler: can't get edit_cert_authority wrapper\n");
|
|
goto done;
|
|
}
|
|
if (trust->emailFlags & CERTDB_TRUSTED)
|
|
trusted = PR_TRUE;
|
|
PR_FREEIF(cx->m_result);
|
|
CN = CERT_GetCommonName(&target->cert->issuer);
|
|
cx->m_result = PR_smprintf(tmpStr, target->cert->emailAddr,
|
|
CN,
|
|
issuer?issuer->nickname:notAvailable,
|
|
trusted?checked:"",
|
|
trusted?"":checked,
|
|
emailCertHelpTarget,
|
|
trustca?"":donot,
|
|
trustca?"":donot);
|
|
PR_FREEIF(CN);
|
|
} else {
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = PR_smprintf("Bad certificate type, don't know how to edit.\n");
|
|
}
|
|
|
|
done:
|
|
PR_FREEIF(tmpStr);
|
|
PR_FREEIF(checked);
|
|
PR_FREEIF(donot);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_EditCertificateTrustHandler(HTTPRequest * req)
|
|
{
|
|
SSMResourceCert * target = (SSMResourceCert *)req->target;
|
|
CERTCertTrust trust;
|
|
char * value;
|
|
SSMStatus rv;
|
|
|
|
PR_ASSERT(target && target->cert);
|
|
rv = (SSMStatus) CERT_GetCertTrust(target->cert, &trust);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("EditCertificateTrustHandler: can't get cert trust object\n");
|
|
goto done;
|
|
}
|
|
|
|
if (trust.sslFlags & CERTDB_VALID_PEER) {
|
|
/* this is website cert we're editing */
|
|
rv = SSM_HTTPParamValue(req, "trustoption", &value);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
if (strcmp(value, "trust") == 0)
|
|
trust.sslFlags |= CERTDB_TRUSTED;
|
|
else trust.sslFlags &= (~CERTDB_TRUSTED);
|
|
}
|
|
else
|
|
if ( (trust.sslFlags & CERTDB_VALID_CA) ||
|
|
(trust.emailFlags & CERTDB_VALID_CA ) ||
|
|
( trust.objectSigningFlags & CERTDB_VALID_CA )
|
|
) {
|
|
/* security advisor in 4.x does this, should we? */
|
|
if ( ! ( target->cert->nsCertType & NS_CERT_TYPE_CA ) )
|
|
target->cert->nsCertType = NS_CERT_TYPE_CA;
|
|
|
|
if (target->cert->nsCertType & NS_CERT_TYPE_SSL_CA)
|
|
trust.sslFlags |= CERTDB_VALID_CA;
|
|
if (target->cert->nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA)
|
|
trust.objectSigningFlags |= CERTDB_VALID_CA;
|
|
if (target->cert->nsCertType & NS_CERT_TYPE_EMAIL_CA)
|
|
trust.emailFlags |= CERTDB_VALID_CA;
|
|
|
|
rv = SSM_HTTPParamValue(req, "networksite", &value);
|
|
if (rv == SSM_SUCCESS)
|
|
trust.sslFlags |= CERTDB_TRUSTED_CA;
|
|
else trust.sslFlags &= (~CERTDB_TRUSTED_CA);
|
|
|
|
rv = SSM_HTTPParamValue(req, "emailuser", &value);
|
|
if (rv == SSM_SUCCESS)
|
|
trust.emailFlags |= CERTDB_TRUSTED_CA;
|
|
else trust.emailFlags &= (~CERTDB_TRUSTED_CA);
|
|
|
|
rv = SSM_HTTPParamValue(req, "software", &value);
|
|
if (rv == SSM_SUCCESS)
|
|
trust.objectSigningFlags |= CERTDB_TRUSTED_CA;
|
|
else trust.objectSigningFlags &= (~CERTDB_TRUSTED_CA);
|
|
}
|
|
else if (trust.emailFlags & CERTDB_VALID_PEER)
|
|
{
|
|
/* edit email cert */
|
|
rv = SSM_HTTPParamValue(req, "trustoption", &value);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
if (PL_strcmp(value, "trust") == 0)
|
|
trust.emailFlags |= CERTDB_TRUSTED;
|
|
else trust.emailFlags &= (~CERTDB_TRUSTED);
|
|
}
|
|
else
|
|
{
|
|
SSM_DEBUG("EditCertificateTrustHandler: trying to edit bad cert\n");
|
|
goto done;
|
|
}
|
|
rv = (SSMStatus) CERT_ChangeCertTrust(req->ctrlconn->m_certdb, target->cert, &trust);
|
|
SSL_ClearSessionCache();
|
|
|
|
done:
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_SelectCertKeywordHandler(SSMTextGenContext * cx)
|
|
{
|
|
SSMStatus rv = SSM_SUCCESS;
|
|
char * value = NULL, *formName = NULL;
|
|
char * fmt = NULL;
|
|
PRIntn PARAM_FORMAT = (PRIntn) 0;
|
|
PRIntn certType, certKey;
|
|
|
|
/* Check for parameter validity */
|
|
PR_ASSERT(cx);
|
|
PR_ASSERT(cx->m_request);
|
|
PR_ASSERT(cx->m_params);
|
|
PR_ASSERT(cx->m_result);
|
|
if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
|
|
{
|
|
rv = (SSMStatus) PR_INVALID_ARGUMENT_ERROR;
|
|
goto loser;
|
|
}
|
|
|
|
rv = SSM_HTTPParamValue(cx->m_request, "origin", &formName);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
|
|
/* figure which certs we're looking for */
|
|
if (strstr(formName, "_mine")) {
|
|
certType = USER_CERT;
|
|
certKey = NICKNAME;
|
|
} else if (strstr(formName, "_others")) {
|
|
certType = EMAIL_CERT;
|
|
certKey = EMAILADDR;
|
|
} else if (strstr(formName, "_websites")) {
|
|
certType = WEBSITE_CERT;
|
|
certKey = NICKNAME;
|
|
} else if (strstr(formName, "_authorities")) {
|
|
certType = CA_CERT;
|
|
certKey = NICKNAME;
|
|
} else
|
|
SSM_DEBUG("SelectCertKeywordHandler: Bad request\n");
|
|
|
|
/* get format */
|
|
fmt = (char *) SSM_At(cx->m_params, PARAM_FORMAT);
|
|
rv = SSM_HTTPParamValue(cx->m_request, "content", &value);
|
|
if (!fmt || !value) {
|
|
SSM_DEBUG("SelectCertKeywordHandler: can't get format or nickname!\n");
|
|
goto loser;
|
|
}
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, fmt, &fmt);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
SSM_DebugUTF8String("cert selection format <%s>", fmt);
|
|
|
|
|
|
rv = ssm_select_cert(cx, &cx->m_result, fmt, certType, certKey, value);
|
|
goto done;
|
|
|
|
loser:
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = NULL;
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
done:
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
ssm_select_cert(SSMTextGenContext * cx, char ** result, char * fmt,
|
|
PRIntn type, PRIntn key,char *nickname)
|
|
{
|
|
CERTCertList * certList;
|
|
CERTCertListNode * node;
|
|
CERTCertificate * cert;
|
|
char * tmpStr = NULL, * checked = NULL;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
PRBool first = PR_TRUE;
|
|
|
|
PR_ASSERT(result);
|
|
PR_ASSERT(fmt);
|
|
PR_ASSERT(nickname);
|
|
|
|
if (!result || !fmt || !nickname) {
|
|
SSM_DEBUG("Bad parameters in ssm_select_cert_nick\n");
|
|
goto loser;
|
|
}
|
|
*result = NULL;
|
|
|
|
/* get a list of certs with the given nick or email address*/
|
|
switch (key) {
|
|
case NICKNAME:
|
|
certList = SSMControlConnection_CreateCertListByNickname(cx->m_request->ctrlconn,
|
|
nickname,
|
|
PR_FALSE);
|
|
break;
|
|
case EMAILADDR:
|
|
certList = SSMControlConnection_CreateCertListByNickname(cx->m_request->ctrlconn, nickname,
|
|
PR_TRUE);
|
|
break;
|
|
default:
|
|
SSM_DEBUG("select_cert: bad cert key, must be NICKNAME or EMAILADDR\n");
|
|
goto loser;
|
|
}
|
|
if (!certList) {
|
|
SSM_DEBUG("select_cert: no certificate with nick %s in the db\n",
|
|
nickname);
|
|
goto done;
|
|
}
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "text_checked", &checked);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("select_cert: can't get text for checked attribute\n");
|
|
goto done;
|
|
}
|
|
|
|
/* traverse the list */
|
|
node = CERT_LIST_HEAD(certList);
|
|
while (!CERT_LIST_END(node, certList))
|
|
{
|
|
cert = node->cert;
|
|
node = CERT_LIST_NEXT(node);
|
|
/* make sure it's correct type of cert */
|
|
if (ssm_cert_belongs_type(cert, type) != SSM_SUCCESS)
|
|
continue;
|
|
|
|
rv = ssm_create_select_cert_entry(cx, cert, &tmpStr, fmt, first?checked:"");
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("Could not create select_cert_entry\n");
|
|
goto loser;
|
|
}
|
|
rv = SSM_ConcatenateUTF8String(result, tmpStr);
|
|
if (rv != SSM_SUCCESS)
|
|
goto loser;
|
|
PR_Free(tmpStr);
|
|
tmpStr = NULL;
|
|
first = PR_FALSE;
|
|
}/* end of loop on certs in the certList */
|
|
goto done;
|
|
|
|
loser:
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
if (result && *result)
|
|
PR_Free(*result);
|
|
*result = NULL;
|
|
|
|
done:
|
|
if (certList)
|
|
CERT_DestroyCertList(certList);
|
|
if (tmpStr)
|
|
PR_Free(tmpStr);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
ssm_create_select_cert_entry(SSMTextGenContext * cx, CERTCertificate * cert,
|
|
char **result, char *fmt, char *checked)
|
|
{
|
|
char * validNotBefore = NULL, * validNotAfter = NULL;
|
|
char * purposeStr = NULL;
|
|
char * valueStr = NULL, * serialNum = NULL;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
|
|
PR_ASSERT(result);
|
|
PR_ASSERT(fmt);
|
|
PR_ASSERT(cert);
|
|
if (!result || !fmt || !cert) {
|
|
SSM_DEBUG("Bad params in ssm_create_select_cert_entry!\n");
|
|
return SSM_FAILURE;
|
|
}
|
|
*result = NULL;
|
|
/* now find info about this certificate */
|
|
validNotBefore = DER_UTCDayToAscii(&cert->validity.notBefore);
|
|
validNotAfter = DER_UTCDayToAscii(&cert->validity.notAfter);
|
|
|
|
if ((cert->keyUsage & KU_KEY_ENCIPHERMENT) == KU_KEY_ENCIPHERMENT)
|
|
SSM_GetUTF8Text(cx, "key_encipherment", &purposeStr);
|
|
else if ((cert->keyUsage & KU_DIGITAL_SIGNATURE) == KU_DIGITAL_SIGNATURE)
|
|
SSM_GetUTF8Text(cx, "digital_signature", &purposeStr);
|
|
else if ((cert->keyUsage & KU_KEY_AGREEMENT) == KU_KEY_AGREEMENT)
|
|
SSM_GetUTF8Text(cx, "key_agreement", &purposeStr);
|
|
else {
|
|
SSM_DEBUG("Can't find certificate usage!\n");
|
|
goto loser;
|
|
}
|
|
rv = (SSMStatus) cert_GetKeyID(cert);
|
|
if (rv != SECSuccess)
|
|
goto loser;
|
|
valueStr = PR_smprintf("%s", CERT_Hexify(&(cert->subjectKeyID),
|
|
PR_FALSE));
|
|
serialNum = CERT_Hexify(&cert->serialNumber, 0);
|
|
if (!serialNum)
|
|
serialNum = PL_strdup("--");
|
|
|
|
/* string ?
|
|
* <input type="radio" name="selectItem" value=keyusage> keyusage, etc.
|
|
*/
|
|
*result = PR_smprintf(fmt, valueStr, purposeStr, validNotBefore,
|
|
validNotAfter, checked, serialNum);
|
|
goto done;
|
|
loser:
|
|
if (*result)
|
|
PR_Free(result);
|
|
*result = NULL;
|
|
done:
|
|
if (purposeStr)
|
|
PR_Free(purposeStr);
|
|
if (valueStr)
|
|
PR_Free(valueStr);
|
|
if (validNotBefore)
|
|
PR_Free(validNotBefore);
|
|
if (validNotAfter)
|
|
PR_Free(validNotAfter);
|
|
PR_FREEIF(serialNum);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
ssm_cert_belongs_type(CERTCertificate * cert, PRIntn type)
|
|
{
|
|
PR_ASSERT(cert);
|
|
/* cert is not in perm database */
|
|
if (!cert->trust)
|
|
goto loser;
|
|
|
|
switch (type) {
|
|
case USER_CERT:
|
|
if ((cert->trust->sslFlags & CERTDB_USER) ||
|
|
(cert->trust->emailFlags & CERTDB_USER) ||
|
|
(cert->trust->objectSigningFlags & CERTDB_USER) )
|
|
goto done;
|
|
break;
|
|
case EMAIL_CERT:
|
|
if (cert->emailAddr &&
|
|
(ssm_cert_belongs_type(cert, USER_CERT) != SSM_SUCCESS ) &&
|
|
(cert->trust->emailFlags & CERTDB_VALID_PEER))
|
|
goto done;
|
|
break;
|
|
case WEBSITE_CERT:
|
|
if (cert->trust->sslFlags & CERTDB_VALID_PEER)
|
|
goto done;
|
|
break;
|
|
case CA_CERT:
|
|
if ((cert->trust->sslFlags & CERTDB_VALID_CA) ||
|
|
(cert->trust->emailFlags & CERTDB_VALID_CA) ||
|
|
(cert->trust->objectSigningFlags & CERTDB_VALID_CA)) {
|
|
/* it is a CA cert, make sure it's not invisible cert */
|
|
if (!((cert->trust->sslFlags & CERTDB_INVISIBLE_CA) ||
|
|
(cert->trust->emailFlags & CERTDB_INVISIBLE_CA) ||
|
|
(cert->trust->objectSigningFlags & CERTDB_INVISIBLE_CA)))
|
|
goto done;
|
|
}
|
|
break;
|
|
default:
|
|
PR_ASSERT(0);
|
|
}
|
|
goto loser;
|
|
done:
|
|
return SSM_SUCCESS;
|
|
loser:
|
|
return SSM_FAILURE;
|
|
}
|
|
|
|
|
|
|
|
SSMStatus
|
|
SSM_ViewCertInfoKeywordHandler(SSMTextGenContext * cx)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char* pattern = NULL;
|
|
char* key = NULL;
|
|
char * style = NULL, *commentString = NULL;
|
|
const PRIntn CERT_WRAPPER = (PRIntn)1;
|
|
const PRIntn CERT_WRAPPER_NO_COMMENT = (PRIntn)2;
|
|
const PRIntn STYLE_PARAM = (PRIntn)0;
|
|
PRIntn wrapper;
|
|
CERTCertificate * cert = NULL;
|
|
|
|
PR_ASSERT(cx != NULL);
|
|
PR_ASSERT(cx->m_request != NULL);
|
|
PR_ASSERT(cx->m_params != NULL);
|
|
PR_ASSERT(cx->m_result != NULL);
|
|
PR_ASSERT(SSM_IsAKindOf(cx->m_request->target, SSM_RESTYPE_CERTIFICATE));
|
|
|
|
if (cx == NULL || cx->m_request == NULL || cx->m_params == NULL ||
|
|
cx->m_result == NULL) {
|
|
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
|
goto loser;
|
|
}
|
|
/* get cert */
|
|
cert = ((SSMResourceCert *)cx->m_request->target)->cert;
|
|
if (!cert)
|
|
goto loser;
|
|
|
|
/* get the correct wrapper */
|
|
commentString = CERT_GetCertCommentString(cert);
|
|
if (commentString)
|
|
wrapper = CERT_WRAPPER;
|
|
else wrapper = CERT_WRAPPER_NO_COMMENT;
|
|
key = (char *) SSM_At(cx->m_params, wrapper);
|
|
PR_FREEIF(commentString);
|
|
|
|
/* second, grab and expand the keyword objects */
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, key, &pattern);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
SSM_DebugUTF8String("ca cert info pattern <%s>", pattern);
|
|
|
|
style = (char *) SSM_At(cx->m_params, STYLE_PARAM);
|
|
PR_FREEIF(cx->m_result);
|
|
if (!strcmp(style, "pretty"))
|
|
rv = SSM_PrettyFormatCert(cert, pattern, &cx->m_result, PR_TRUE);
|
|
else
|
|
rv = SSM_FormatCert(cert, pattern, &cx->m_result);
|
|
goto done;
|
|
|
|
loser:
|
|
if (rv == SSM_SUCCESS)
|
|
rv = SSM_FAILURE;
|
|
done:
|
|
PR_FREEIF(pattern);
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
SSM_CertListCount(CERTCertList *certList)
|
|
{
|
|
int numCerts = 0;
|
|
CERTCertListNode *node;
|
|
|
|
node = CERT_LIST_HEAD(certList);
|
|
while (!CERT_LIST_END(node, certList)) {
|
|
numCerts++;
|
|
node = CERT_LIST_NEXT(node);
|
|
}
|
|
return numCerts;
|
|
}
|
|
|
|
/* ### mwelch - PKCS11 private function? Need prototype for Mac */
|
|
#ifdef XP_MAC
|
|
CERTCertList *
|
|
PK11_FindCertsFromNickname(char *nickname, void *wincx);
|
|
#endif
|
|
|
|
CERTCertList *
|
|
SSMControlConnection_CreateCertListByNickname(SSMControlConnection * ctrl,
|
|
char * nick, PRBool email)
|
|
{
|
|
CERTCertList * certListDB = NULL, * certListExternal = NULL;
|
|
|
|
certListDB = CERT_NewCertList();
|
|
if (email)
|
|
certListDB = CERT_CreateEmailAddrCertList(certListDB,ctrl->m_certdb,
|
|
nick, PR_Now(), PR_FALSE);
|
|
else
|
|
certListDB = CERT_CreateNicknameCertList(certListDB, ctrl->m_certdb,
|
|
nick, PR_Now(), PR_FALSE);
|
|
if (!certListDB && !email)
|
|
certListExternal = PK11_FindCertsFromNickname(nick, ctrl);
|
|
|
|
if (certListExternal)
|
|
return certListExternal;
|
|
else
|
|
return certListDB;
|
|
}
|
|
|
|
CERTCertificate *
|
|
SSMControlConnection_FindCertByNickname(SSMControlConnection * ctrl,
|
|
char * nick, PRBool email)
|
|
{
|
|
CERTCertificate * cert = NULL;
|
|
|
|
if (email)
|
|
cert = CERT_FindCertByEmailAddr(ctrl->m_certdb, nick);
|
|
else
|
|
cert = CERT_FindCertByNickname(ctrl->m_certdb, nick);
|
|
|
|
if (!cert && !email)
|
|
cert = PK11_FindCertFromNickname(nick, ctrl);
|
|
|
|
return cert;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_OCSPOptionsKeywordHandler(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv;
|
|
PRBool prefBool;
|
|
char *fmt = NULL, *ocspURL;
|
|
char *noOCSP = NULL, *noDefaultResponder = NULL, *useDefaultResponder = NULL;
|
|
PrefSet *prefs;
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "ocsp_options_template",
|
|
&fmt);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
prefs = cx->m_request->ctrlconn->m_prefs;
|
|
rv = PREF_GetStringPref(prefs, "security.OCSP.URL", &ocspURL);
|
|
if (rv != SSM_SUCCESS) {
|
|
ocspURL = "";
|
|
}
|
|
rv = PREF_GetBoolPref(prefs, "security.OCSP.enabled", &prefBool);
|
|
/*
|
|
* Since the CHECKED is part of the HTML parsed by the broswer,
|
|
* We don't have to localize it. If the user were going to see
|
|
* it, then we would have to localize it.
|
|
*/
|
|
if (rv != SSM_SUCCESS || !prefBool) {
|
|
noOCSP = "CHECKED";
|
|
noDefaultResponder = "";
|
|
useDefaultResponder = "";
|
|
} else {
|
|
rv = PREF_GetBoolPref(prefs, "security.OCSP.useDefaultResponder",
|
|
&prefBool);
|
|
if (rv != SSM_SUCCESS) {
|
|
noOCSP = "CHECKED";
|
|
noDefaultResponder = "";
|
|
useDefaultResponder = "";
|
|
} else if (prefBool) {
|
|
noOCSP = "";
|
|
noDefaultResponder = "";
|
|
useDefaultResponder = "CHECKED";
|
|
} else {
|
|
noOCSP = "";
|
|
noDefaultResponder = "CHECKED";
|
|
useDefaultResponder = "";
|
|
}
|
|
}
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = PR_smprintf(fmt, noOCSP,noDefaultResponder,
|
|
useDefaultResponder, ocspURL);
|
|
PR_Free(fmt);
|
|
return SSM_SUCCESS;
|
|
loser:
|
|
PR_FREEIF(fmt);
|
|
return SSM_FAILURE;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_OCSPDefaultResponderKeywordHandler(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv;
|
|
char *defaultResponder = NULL, *fmt = NULL;
|
|
|
|
rv = PREF_GetStringPref(cx->m_request->ctrlconn->m_prefs,
|
|
"security.OCSP.signingCA",
|
|
&defaultResponder);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "default_responder_template",
|
|
&fmt);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = PR_smprintf(fmt, defaultResponder);
|
|
if (cx->m_result == NULL) {
|
|
goto loser;
|
|
}
|
|
PR_Free(fmt);
|
|
return SSM_SUCCESS;
|
|
|
|
loser:
|
|
cx->m_result = PL_strdup("");
|
|
PR_FREEIF(fmt);
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_ObtainNewCertSite(SSMTextGenContext * cx)
|
|
{
|
|
char * newCertURL = NULL;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
|
|
rv = PREF_GetStringPref(cx->m_request->ctrlconn->m_prefs, "obtainCertURL",
|
|
&newCertURL);
|
|
if (rv == SSM_SUCCESS)
|
|
goto done;
|
|
|
|
rv = SSM_GetAndExpandText(cx, "new_cert_URL", &newCertURL);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("NewCertSite: can't find URL for obtaining new certs!\n");
|
|
goto loser;
|
|
}
|
|
SSM_DEBUG("NewCertSite: no customized URL provided using default:%s",
|
|
newCertURL);
|
|
|
|
done:
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = newCertURL;
|
|
newCertURL = NULL;
|
|
loser:
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus SSM_ProcessLDAPWindow(HTTPRequest * req)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
SSMResource * target = NULL;
|
|
char **ldap_servers, **ptr, *params = NULL;
|
|
SSMHTTPParamMultValues emailAddresses={NULL, NULL, 0};
|
|
int i;
|
|
|
|
if (!req || !req->ctrlconn)
|
|
goto loser;
|
|
|
|
rv = PREF_CreateChildList(req->ctrlconn->m_prefs,
|
|
"ldap_2.servers", &ldap_servers);
|
|
if (rv != SSM_SUCCESS || !ldap_servers) {
|
|
SSMControlConnection_SendUIEvent(req->ctrlconn, "get",
|
|
"show_followup", NULL,
|
|
"result=no_ldap_setup",
|
|
&((SSMResource *)req->ctrlconn)->m_clientContext,
|
|
PR_TRUE);
|
|
goto loser;
|
|
}
|
|
|
|
target = (req->target ? req->target : (SSMResource *) req->ctrlconn);
|
|
/*
|
|
* Let's see if there were some email addresses passed along to this
|
|
* dialog that we should pre-fill the window with.
|
|
*/
|
|
rv = SSM_HTTPParamValueMultiple(req, "emailAddresses", &emailAddresses);
|
|
if (rv == SSM_SUCCESS && emailAddresses.numValues > 0) {
|
|
char *tmp;
|
|
|
|
/* There are some email addresses that need to be passed on. */
|
|
for (i=0; i<emailAddresses.numValues; i++) {
|
|
tmp = PR_smprintf("%s%s%s", (params)?params:"", (params)?",":"",
|
|
emailAddresses.values[i]);
|
|
PR_FREEIF(params);
|
|
params = tmp;
|
|
}
|
|
tmp = SSM_ConvertStringToHTMLString(params);
|
|
PR_Free(params);
|
|
params = PR_smprintf("emailAddresses=%s", tmp);
|
|
PR_Free(tmp);
|
|
}
|
|
/* send UI event to bring up the dialog */
|
|
SSM_LockUIEvent(target);
|
|
rv = SSMControlConnection_SendUIEvent(req->ctrlconn, "get",
|
|
"ldap_request", target,
|
|
params, &target->m_clientContext,
|
|
PR_TRUE);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_UnlockUIEvent(target);
|
|
goto loser;
|
|
}
|
|
SSM_WaitUIEvent(target, PR_INTERVAL_NO_TIMEOUT);
|
|
/* if (req->ctrlconn->super.super.m_buttonType == SSM_BUTTON_CANCEL) {
|
|
SSM_HTTPReportError(req, HTTP_NO_CONTENT);
|
|
goto loser;
|
|
}
|
|
*/
|
|
/* free memory from ChildList */
|
|
ptr = ldap_servers;
|
|
while (*ptr) {
|
|
PR_Free(*ptr);
|
|
ptr++;
|
|
}
|
|
PR_Free(ldap_servers);
|
|
|
|
loser:
|
|
if (req) {
|
|
if (req->target->m_buttonType == SSM_BUTTON_CANCEL) {
|
|
SSM_HTTPReportError(req, HTTP_NO_CONTENT);
|
|
} else {
|
|
SSM_RefreshRefererPage(req);
|
|
}
|
|
}
|
|
/* Don't free the values stored in the individual array because
|
|
* those are owned by the request structure.
|
|
*/
|
|
PR_FREEIF(emailAddresses.values);
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus SSM_ProcessLDAPRequestHandler(HTTPRequest * req)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char * tmpStr = NULL, *emailaddr, *ldapserver;
|
|
char* key = NULL, *currEmail, *cursor;
|
|
PRBool updateList = PR_FALSE;
|
|
|
|
/* make sure you got the right baseRef */
|
|
rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
|
|
if (rv != SSM_SUCCESS ||
|
|
PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
|
|
goto loser;
|
|
}
|
|
/* Close the window */
|
|
rv = SSM_HTTPDefaultCommandHandler(req);
|
|
if (rv != SSM_SUCCESS)
|
|
SSM_DEBUG("UI_ProcessLDAPRequest: can't close the window !\n");
|
|
|
|
|
|
rv = SSM_HTTPParamValue(req, "do_cancel", &tmpStr);
|
|
if (rv == SSM_SUCCESS && tmpStr) {
|
|
req->target->m_buttonType = SSM_BUTTON_CANCEL;
|
|
goto loser;
|
|
}
|
|
req->target->m_buttonType = SSM_BUTTON_OK;
|
|
|
|
rv = SSM_HTTPParamValue(req, "emailaddress", &emailaddr);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("UI_ProcessLDAPRequest: no email address supplied!\n");
|
|
goto loser;
|
|
}
|
|
|
|
rv = SSM_HTTPParamValue(req, "ldapServer", &ldapserver);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("UI_ProcessLDAPRequest: can't find ldap server parameter!\n");
|
|
goto loser;
|
|
}
|
|
|
|
/* create a complete key part */
|
|
key = PR_smprintf("ldap_2.servers.%s", ldapserver);
|
|
if (key == NULL) {
|
|
goto loser;
|
|
}
|
|
/*
|
|
* Now let's loop over the each entry looking for the certs.
|
|
*/
|
|
cursor = currEmail = emailaddr;
|
|
while (cursor != NULL && *cursor != '\0') {
|
|
char oldCursorVal;
|
|
|
|
cursor = PL_strpbrk(currEmail, " ,");
|
|
if (cursor != NULL) {
|
|
oldCursorVal = *cursor;
|
|
*cursor = '\0';
|
|
}
|
|
rv = SSM_CompleteLDAPLookup(req->ctrlconn, key, currEmail);
|
|
if (rv == SSM_SUCCESS) {
|
|
updateList = PR_TRUE;
|
|
}
|
|
if (cursor != NULL) {
|
|
*cursor = oldCursorVal;
|
|
cursor++;
|
|
}
|
|
/*
|
|
* Jump over all of the white space and commas.
|
|
*/
|
|
while (cursor && *cursor && isspace(*cursor))
|
|
cursor++;
|
|
while (cursor && *cursor == ',') {
|
|
cursor++;
|
|
while (cursor && *cursor && isspace(*cursor))
|
|
cursor++;
|
|
}
|
|
currEmail = cursor;
|
|
}
|
|
if (updateList)
|
|
SSM_ChangeCertSecAdvisorList(req, emailaddr, certHashAdd);
|
|
else
|
|
SSM_DEBUG("UI_ProcessLDAPRequest: can't import new cert into the db!\n");
|
|
|
|
loser:
|
|
SSM_NotifyUIEvent(req->target);
|
|
PR_FREEIF(key);
|
|
return rv;
|
|
}
|
|
|
|
|
|
SSMStatus
|
|
SSM_CompleteLDAPLookup(SSMControlConnection *ctrl, char * ldapserver,
|
|
char *emailaddr)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char * tmpStr, * servername, *baseDN, *mailAttribs;
|
|
SECItem newCert = { siBuffer, NULL, 0};
|
|
CERTCertificate * cert = NULL;
|
|
SECStatus secrv;
|
|
int port = 0;
|
|
char cert_attribs[] = "userSMIMECertificate,usercertificate;binary";
|
|
cert_struct * certs[2] = {NULL, NULL}; /* one for ea cert_attrib */
|
|
|
|
if (!ctrl || !ldapserver)
|
|
goto loser;
|
|
PR_ASSERT(SSM_IsA((SSMResource *)ctrl, SSM_RESTYPE_CONTROL_CONNECTION));
|
|
|
|
tmpStr = PR_smprintf("%s.serverName", ldapserver);
|
|
rv = PREF_GetStringPref(ctrl->m_prefs,tmpStr,
|
|
&servername);
|
|
PR_FREEIF(tmpStr);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("CompleteLDAPLookup: can't find LDAP server %s!\n",ldapserver);
|
|
goto loser;
|
|
}
|
|
|
|
/* DN, mail attribs and port are not supplied from UI, look up in prefs */
|
|
tmpStr = PR_smprintf("%s.searchBase",ldapserver);
|
|
rv = PREF_GetStringPref(ctrl->m_prefs, tmpStr, &baseDN);
|
|
PR_FREEIF(tmpStr);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("CompleteLDAPLookup: can't find baseDN for %s!\n",ldapserver);
|
|
goto loser;
|
|
}
|
|
|
|
tmpStr = PR_smprintf("%s.attributes.mail",ldapserver);
|
|
rv = PREF_GetStringPref(ctrl->m_prefs, tmpStr, &mailAttribs);
|
|
PR_FREEIF(tmpStr);
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("CompleteLDAPLookup:can't find mail attributes for %s!\n",
|
|
ldapserver);
|
|
goto loser;
|
|
}
|
|
|
|
tmpStr = PR_smprintf("%s.port",ldapserver);
|
|
rv = PREF_GetIntPref(ctrl->m_prefs, tmpStr, &port);
|
|
PR_FREEIF(tmpStr);
|
|
if (rv != SSM_SUCCESS)
|
|
port = 0;
|
|
|
|
#ifndef XP_MAC
|
|
rv = LDAPCertSearch(emailaddr, servername, baseDN, port, 1, NULL, NULL,
|
|
NULL, mailAttribs, cert_attribs, certs);
|
|
#else
|
|
rv = SSM_FAILURE; /* don't yet support LDAP on the Mac */
|
|
#endif
|
|
|
|
if (rv != SSM_SUCCESS) {
|
|
SSM_DEBUG("CompleteLDAPLookup: ldap search did not find anything!\n");
|
|
goto loser;
|
|
}
|
|
|
|
/* Go thru the possible multiple Certs retrieved from LDAP */
|
|
rv = SSM_FAILURE; /* default case - no good Certs found */
|
|
|
|
/* first check any userSMIMECerts found */
|
|
if (certs[0]) {
|
|
PRBool ret;
|
|
SEC_PKCS7ContentInfo *ci;
|
|
SECItem digest;
|
|
unsigned char nullsha1[SHA1_LENGTH];
|
|
struct cert_struct_def * cert_ptr;
|
|
|
|
cert_ptr = certs[0];
|
|
while (cert_ptr->cert_len) {
|
|
newCert.len = cert_ptr->cert_len;
|
|
newCert.data = (unsigned char *) cert_ptr->cert;
|
|
ci = SEC_PKCS7DecodeItem(&newCert, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
if ( ci != NULL ) {
|
|
if ( SEC_PKCS7ContentIsSigned(ci) ) {
|
|
rv = SHA1_HashBuf(nullsha1, nullsha1, 0);
|
|
if ( rv != SECSuccess ) {
|
|
break;
|
|
}
|
|
digest.len = SHA1_LENGTH;
|
|
digest.data = nullsha1;
|
|
|
|
ret = SEC_PKCS7VerifyDetachedSignature(ci,
|
|
certUsageEmailRecipient,
|
|
&digest,
|
|
HASH_AlgSHA1,
|
|
PR_TRUE);
|
|
if (ret == PR_TRUE) {
|
|
rv = SSM_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
PR_Free(cert_ptr->cert);
|
|
*cert_ptr++;
|
|
}
|
|
PR_Free(certs[0]);
|
|
}
|
|
|
|
/* If no valid Certs found yet, try userCertificate;binary */
|
|
if (rv == SSM_FAILURE && certs[1]) {
|
|
struct cert_struct_def * cert_ptr;
|
|
|
|
cert_ptr = certs[1];
|
|
while (cert_ptr->cert_len) {
|
|
newCert.len = cert_ptr->cert_len;
|
|
newCert.data = (unsigned char *) cert_ptr->cert;
|
|
/* memcpy(newCert.data, cert_ptr->cert, newCert.len); */
|
|
|
|
/* Okay, got a Cert - so try to store in CertDB */
|
|
cert = CERT_NewTempCertificate(ctrl->m_certdb, &newCert, NULL,
|
|
PR_FALSE, PR_TRUE);
|
|
if (cert != NULL) {
|
|
secrv = CERT_SaveImportedCert(cert, certUsageEmailRecipient,
|
|
PR_FALSE, NULL);
|
|
if (secrv == SECSuccess) {
|
|
secrv = CERT_SaveSMimeProfile(cert, NULL, NULL);
|
|
rv = SSM_SUCCESS;
|
|
}
|
|
}
|
|
/* and free LDAP cert memory for this cert */
|
|
PR_Free(cert_ptr->cert);
|
|
*cert_ptr++;
|
|
}
|
|
PR_Free(certs[1]);
|
|
}
|
|
|
|
#if 0
|
|
/* Store the cert in the certdb */
|
|
cert = CERT_NewTempCertificate(ctrl->m_certdb, &newCert,
|
|
NULL, PR_FALSE, PR_TRUE);
|
|
if ( cert != NULL ) {
|
|
secrv = CERT_SaveImportedCert(cert, certUsageEmailRecipient,
|
|
PR_FALSE, NULL);
|
|
if ( secrv == SECSuccess )
|
|
secrv = CERT_SaveSMimeProfile(cert, NULL, NULL);
|
|
} else {
|
|
SSM_DEBUG("CompleteLDAPLookup: couldn't import cert into DB!\n");
|
|
rv = SSM_FAILURE;
|
|
}
|
|
#endif
|
|
|
|
loser:
|
|
return rv;
|
|
}
|
|
|
|
|
|
SSMStatus SSM_LDAPServerListKeywordHandler(SSMTextGenContext * cx)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
char * tmpStr = NULL, * desc_key = NULL;
|
|
char ** ldap_servers = NULL, ** ptr, * server = NULL;
|
|
char * wrapper = NULL;
|
|
|
|
cx->m_result = NULL;
|
|
/* get all the ldap servers available and present them in a list */
|
|
rv = PREF_CreateChildList(cx->m_request->ctrlconn->m_prefs,
|
|
"ldap_2.servers", &ldap_servers);
|
|
if (rv != SSM_SUCCESS || !ldap_servers)
|
|
goto done;
|
|
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "ldap_server_list_prefix",
|
|
&cx->m_result);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
rv = SSM_GetAndExpandTextKeyedByString(cx, "ldap_server_list_item",
|
|
&wrapper);
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
ptr = ldap_servers;
|
|
while (*ptr) {
|
|
desc_key = PR_smprintf("ldap_2.servers.%s.description", *ptr);
|
|
rv = PREF_GetStringPref(cx->m_request->ctrlconn->m_prefs,
|
|
desc_key, &server);
|
|
PR_FREEIF(desc_key); desc_key = NULL;
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
tmpStr = PR_smprintf(wrapper, *ptr, server);
|
|
PR_Free(*ptr);
|
|
rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
|
|
PR_FREEIF(tmpStr); tmpStr = NULL;
|
|
if (rv != SSM_SUCCESS)
|
|
goto done;
|
|
ptr++;
|
|
}
|
|
PR_Free(ldap_servers); ldap_servers = NULL;
|
|
SSM_GetAndExpandTextKeyedByString(cx, "ldap_server_list_suffix",
|
|
&tmpStr);
|
|
rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
|
|
done:
|
|
PR_FREEIF(wrapper);
|
|
PR_FREEIF(tmpStr);
|
|
if (rv != SSM_SUCCESS)
|
|
PR_FREEIF(cx->m_result);
|
|
return rv;
|
|
}
|
|
|
|
char * SSM_GetCAPolicyString(char * org, unsigned long noticeNum, void * arg)
|
|
{
|
|
SSMControlConnection * ctrl = (SSMControlConnection *)arg;
|
|
char * alphaorg = NULL, * ptr, *aptr, * key = NULL, * value = NULL;
|
|
int c;
|
|
|
|
if (!ctrl || !org)
|
|
goto loser;
|
|
PR_ASSERT(ctrl && SSM_IsAKindOf((SSMResource *)ctrl,SSM_RESTYPE_CONTROL_CONNECTION));
|
|
|
|
alphaorg = (char *) PORT_ZAlloc(sizeof(org) + 1);
|
|
if (!alphaorg)
|
|
goto loser;
|
|
|
|
ptr = org; aptr = alphaorg;
|
|
while ( (c=*ptr) != '\0') {
|
|
if ( isalpha(c) ) {
|
|
* aptr = c;
|
|
aptr++;
|
|
}
|
|
ptr++;
|
|
}
|
|
*aptr = '\0';
|
|
|
|
key = PR_smprintf("security.canotices.%s.notice%ld", alphaorg, noticeNum);
|
|
if (!key)
|
|
goto loser;
|
|
PREF_GetStringPref(ctrl->m_prefs, key, &value);
|
|
|
|
loser:
|
|
PR_FREEIF(alphaorg);
|
|
PR_FREEIF(key);
|
|
return value?PL_strdup(value):NULL;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_FillTextWithEmails(SSMTextGenContext *cx)
|
|
{
|
|
SSMStatus rv;
|
|
char *emails;
|
|
|
|
rv = SSM_HTTPParamValue(cx->m_request, "emailAddresses", &emails);
|
|
PR_FREEIF(cx->m_result);
|
|
if (rv == SSM_SUCCESS) {
|
|
cx->m_result = PL_strdup(emails);
|
|
} else {
|
|
cx->m_result = PL_strdup("");
|
|
}
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_GetWindowOffset(SSMTextGenContext *cx)
|
|
{
|
|
char *offset=NULL;
|
|
SSMStatus rv;
|
|
int offsetVal;
|
|
|
|
rv = SSM_HTTPParamValue(cx->m_request, "windowOffset", &offset);
|
|
if (rv != SSM_SUCCESS) {
|
|
offsetVal = 0;
|
|
} else {
|
|
offsetVal = atoi (offset);
|
|
}
|
|
offsetVal += 20;
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = PR_smprintf("%d", offsetVal);
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_MakeUniqueNameForIssuerWindow(SSMTextGenContext *cx)
|
|
{
|
|
SSMResourceCert *certres;
|
|
CERTCertificate *issuer, *serverCert;
|
|
char *certHex=NULL, *issuerHex=NULL;
|
|
SSMSSLDataConnection *sslConn;
|
|
|
|
if (SSM_IsAKindOf(cx->m_request->target, SSM_RESTYPE_CERTIFICATE)) {
|
|
certres = (SSMResourceCert*)cx->m_request->target;
|
|
serverCert = certres->cert;
|
|
} else if (SSM_IsAKindOf(cx->m_request->target,
|
|
SSM_RESTYPE_SSL_DATA_CONNECTION)) {
|
|
sslConn = (SSMSSLDataConnection*)cx->m_request->target;
|
|
serverCert = SSL_PeerCertificate(sslConn->socketSSL);
|
|
if (serverCert == NULL) {
|
|
goto loser;
|
|
}
|
|
} else {
|
|
goto loser;
|
|
}
|
|
issuer = CERT_FindCertIssuer(serverCert,PR_Now(),certUsageAnyCA);
|
|
certHex = CERT_Hexify(&serverCert->serialNumber,0);
|
|
if (issuer != NULL) {
|
|
issuerHex = CERT_Hexify(&issuer->serialNumber,0);
|
|
CERT_DestroyCertificate(issuer);
|
|
}
|
|
PR_FREEIF(cx->m_result);
|
|
cx->m_result = PR_smprintf("%s%s", certHex, (issuerHex) ? issuerHex : "");
|
|
PR_FREEIF(issuerHex);
|
|
PR_Free(certHex);
|
|
return SSM_SUCCESS;
|
|
loser:
|
|
return SSM_FAILURE;
|
|
}
|
|
|
|
SSMStatus
|
|
SSM_ShowCertIssuer(HTTPRequest *req)
|
|
{
|
|
SSMResourceCert *certres;
|
|
SSMResource *issuerRes=NULL;
|
|
CERTCertificate *issuer=NULL;
|
|
char *tmpl = NULL, *finalText=NULL;
|
|
SSMTextGenContext *cx=NULL;
|
|
SSMStatus rv;
|
|
SSMResourceID issuerResID;
|
|
char *htmlString=NULL, *params = NULL, *offsetString;
|
|
int offset;
|
|
|
|
if (!SSM_IsAKindOf(req->target, SSM_RESTYPE_CERTIFICATE)) {
|
|
goto loser;
|
|
}
|
|
certres = (SSMResourceCert*)req->target;
|
|
issuer = CERT_FindCertIssuer(certres->cert, PR_Now(), certUsageAnyCA);
|
|
if (issuer == NULL) {
|
|
/*
|
|
* Instead of bailing out entirely, pop up a dialog that let's the
|
|
* user know the issuer was not found.
|
|
*/
|
|
|
|
params = PR_smprintf("get?baseRef=issuer_not_found&target=%d",
|
|
req->target->m_id);
|
|
} else {
|
|
|
|
rv = (SSMStatus) SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, (void*)issuer,
|
|
req->ctrlconn, &issuerResID, &issuerRes);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
|
|
rv = SSM_HTTPParamValue(req, "windowOffset", &offsetString);
|
|
if (rv != SSM_SUCCESS) {
|
|
offset = 0;
|
|
} else {
|
|
offset = atoi (offsetString);
|
|
}
|
|
|
|
/* Now let's build up the URL*/
|
|
htmlString = SSM_ConvertStringToHTMLString(issuer->nickname);
|
|
params = PR_smprintf("get?baseRef=cert_view&target=%1$d&windowOffset=%2$d",
|
|
issuerResID, offset);
|
|
PR_Free(htmlString);
|
|
htmlString = NULL;
|
|
}
|
|
rv =SSMTextGen_NewTopLevelContext(req, &cx);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
rv = SSM_GetAndExpandText(cx, "refresh_window_content", &tmpl);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
finalText = PR_smprintf(tmpl, params);
|
|
SSM_HTTPSendOKHeader(req, NULL, "text/html");
|
|
SSM_HTTPSendUTF8String(req, finalText);
|
|
PR_FREEIF(tmpl);
|
|
PR_Free(finalText);
|
|
SSMTextGen_DestroyContext(cx);
|
|
req->sentResponse = PR_TRUE;
|
|
return SSM_SUCCESS;
|
|
loser:
|
|
PR_FREEIF(tmpl);
|
|
PR_FREEIF(finalText);
|
|
if (cx != NULL) {
|
|
SSMTextGen_DestroyContext(cx);
|
|
}
|
|
return SSM_FAILURE;
|
|
}
|
|
|
|
SSMStatus SSM_PrettyPrintCert(HTTPRequest *req)
|
|
{
|
|
SSMResource *res;
|
|
SSMResourceCert *certres;
|
|
SSMStatus rv;
|
|
char *prefix=NULL, *suffix=NULL, *certName;
|
|
SSMTextGenContext *cx=NULL;
|
|
|
|
res = req->target;
|
|
if (!SSM_IsAKindOf(res, SSM_RESTYPE_CERTIFICATE)) {
|
|
return SSM_FAILURE;
|
|
}
|
|
certres = (SSMResourceCert*)res;
|
|
rv = SSMTextGen_NewTopLevelContext(req, &cx);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
rv = SSM_GetAndExpandText(cx, "certPrettyPrefix", &prefix);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
rv = SSM_GetAndExpandText(cx, "certPrettySuffix", &suffix);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
rv = SSM_HTTPSendOKHeader(req, NULL, "text/html");
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
rv = SSM_HTTPSendUTF8String(req, prefix);
|
|
if (rv != SSM_SUCCESS) {
|
|
goto loser;
|
|
}
|
|
certName = (certres->cert->nickname) ? certres->cert->nickname :
|
|
certres->cert->emailAddr;
|
|
SSM_HTTPSendUTF8String(req, certName);
|
|
SSM_HTTPSendUTF8String(req, "\n\n");
|
|
SSM_PrettyPrintDER(req->sock, &certres->cert->derCert, 0);
|
|
SSM_HTTPSendUTF8String(req, suffix);
|
|
req->sentResponse = PR_TRUE;
|
|
return SSM_SUCCESS;
|
|
loser:
|
|
if (cx != NULL) {
|
|
SSMTextGen_DestroyContext(cx);
|
|
}
|
|
PR_FREEIF(prefix);
|
|
PR_FREEIF(suffix);
|
|
return SSM_FAILURE;
|
|
}
|
|
|