Initial checkin of the PSM server

This commit is contained in:
ddrinan%netscape.com 2000-04-12 00:05:55 +00:00
Родитель f03ff8d62c
Коммит 89611b5b5b
79 изменённых файлов: 35809 добавлений и 0 удалений

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

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

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,165 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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.
*/
#ifndef __ADVISOR_H__
#define __ADVISOR_H__
/*
Security advisor object. We create this in order to determine what to show
in the generic "Security Info" pane, and to convey the right URL back to
the client for loading.
Created by mwelch 1999 February
*/
#include "resource.h"
#include "ctrlconn.h"
#include "certres.h"
#include "p7cinfo.h"
#include "slist.h"
#include "sslskst.h"
typedef struct InfoSecAdvisor
{
PRInt32 infoContext;
PRInt32 resID;
char *hostname;
char *senderAddr;
PRUint32 encryptedP7CInfo;
PRUint32 signedP7CInfo;
PRInt32 decodeError;
PRInt32 verifyError;
PRInt32 encryptthis;
PRInt32 signthis;
PRInt32 numRecipients;
char **recipients;
} InfoSecAdvisor;
typedef struct SSMSecurityAdvisorContext
{
SSMResource super;
/* Reference to Cartman object which we use to display
"Security Info" pane */
SSMResource *m_infoSource;
/* Width and height of the security advisor window,
loaded from resource file */
PRUint32 m_width, m_height;
/* Cached URL which we send back to client upon request */
char *m_url;
SSMSortedList *m_certhash;
PRIntn m_certsIncluded;
char *m_nickname;
PRInt32 infoContext;
PRInt32 resID;
char *hostname;
char *senderAddr;
PRUint32 encryptedP7CInfo;
PRUint32 signedP7CInfo;
PRInt32 decodeError;
PRInt32 verifyError;
PRInt32 encryptthis;
PRInt32 signthis;
PRInt32 numRecipients;
char **recipients;
char *selectedItemPage;
PRInt32 encrypted_b;
PRInt32 signed_b;
SSMP7ContentInfo * encryptedP7CInfoRes;
SSMP7ContentInfo * signedP7CInfoRes;
SSMSSLSocketStatus * socketStatus;
#if 0
/* data for Java principals */
char* m_principalsData;
#endif
} SSMSecurityAdvisorContext;
SSMStatus SSMSecurityAdvisorContext_Create(SSMControlConnection *ctrl,
InfoSecAdvisor *info,
SSMResource **res);
SSMStatus SSMSecurityAdvisorContext_Destroy(SSMResource *res, PRBool doFree);
void SSMSecurityAdvisorContext_Invariant(SSMSecurityAdvisorContext *ct);
SSMStatus SSMSecurityAdvisorContext_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMSecurityAdvisorContext_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMSecurityAdvisorContext_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
SSMStatus SSMSecurityAdvisorContext_FormSubmitHandler(SSMResource *res,
HTTPRequest *req);
SSMStatus SSMSecurityAdvisorContext_Print(SSMResource *res,
char *fmt, PRIntn numParam,
char **value, char **resultStr);
SSMStatus SSMSecurityAdvisorContext_DoPKCS12Response(HTTPRequest *req,
const char *responseKey);
SSMStatus SSMSecurityAdvisorContext_DoPKCS12Restore(SSMSecurityAdvisorContext *res,
HTTPRequest *req);
SSMStatus SSMSecurityAdvisorContext_DoPKCS12Backup(SSMSecurityAdvisorContext *cx,
HTTPRequest *req);
SSMStatus SSMSecurityAdvisorContext_Process_cert_mine_form(SSMSecurityAdvisorContext *res,
HTTPRequest *req);
SSMStatus SSMSecurityAdvisorContext_sa_selected_item(SSMTextGenContext* cx);
SSMStatus SSM_FreeTarget(SSMTextGenContext *cx);
SSMStatus
SSMSecurityAdvisorContext_GetPrefListKeywordHandler(SSMTextGenContext* cx);
SSMStatus SSM_SetDBPasswordHandler(HTTPRequest * req);
#if 0
SSMStatus SSM_JavaPrincipalsKeywordHandler(SSMTextGenContext* cx);
void SSM_HandleGetJavaPrincipalsReply(SSMControlConnection* ctrl,
SECItem* message);
#endif
SSMStatus SSM_RemovePrivilegesHandler(HTTPRequest* req);
SSMStatus SSM_OCSPResponderList(SSMTextGenContext* cx);
char* SSM_GetOCSPURL(CERTCertificate *cert, PrefSet *prefs);
PRBool SSM_IsOCSPEnabled(SSMControlConnection *connection);
#endif

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

@ -0,0 +1,548 @@
/*
* 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 "ctrlconn.h"
#include "cert.h"
#include "secasn1.h"
#include "secder.h"
#include "xconst.h"
#include "secerr.h"
#include "newproto.h"
#include "messages.h"
#include "certres.h"
#include "pk11func.h"
#include "secoid.h"
typedef struct CERTRenewalWindow {
SECItem begin;
SECItem end;
} CERTRenewalWindow;
const static SEC_ASN1Template CERT_RenewalWindowTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(CERTRenewalWindow) },
{ SEC_ASN1_GENERALIZED_TIME,
offsetof(CERTRenewalWindow,begin) },
{ SEC_ASN1_OPTIONAL | SEC_ASN1_GENERALIZED_TIME,
offsetof(CERTRenewalWindow,end) },
{ 0 }
};
PRBool CERT_HasRenewalExtension(CERTCertificate *cert)
{
int rv;
SECItem *derWindow = NULL;
PRBool ret = PR_FALSE;
/* Allocate from the heap, so that we can free eveything later */
derWindow = SECITEM_AllocItem(NULL, NULL, 0);
if (derWindow == NULL) {
goto loser;
}
/* Get the renewal window extension */
rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME,
derWindow);
if (rv == SECSuccess) {
ret = PR_TRUE;
}
loser:
if (derWindow) {
SECITEM_FreeItem(derWindow, PR_TRUE);
}
return ret;
}
PRBool CERT_InRenewalWindow(CERTCertificate *cert, int64 t)
{
int rv;
int64 begin, end;
CERTRenewalWindow *window = NULL;
SECItem *derWindow = NULL;
PRArenaPool *arena = NULL;
PRBool ret = PR_FALSE;
/* Allocate from the heap, so that we can free eveything later */
derWindow = SECITEM_AllocItem(NULL, NULL, 0);
if (derWindow == NULL) {
goto loser;
}
/* Get the renewal window extension */
rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME,
derWindow);
if (rv == SECFailure) {
goto loser;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
goto loser;
window = (CERTRenewalWindow*)PORT_ArenaZAlloc(arena,
sizeof(CERTRenewalWindow));
if (window == NULL) {
goto loser;
}
/* Decode the extension */
rv = SEC_ASN1DecodeItem(arena, window, CERT_RenewalWindowTemplate, derWindow);
if (rv) {
goto loser;
}
/* Decode the times */
rv = DER_GeneralizedTimeToTime(&begin, &window->begin);
if (window->end.data) {
rv = DER_GeneralizedTimeToTime(&end, &window->end);
} else {
rv = DER_UTCTimeToTime(&end, &cert->validity.notAfter);
}
/* Is this cert in the renewal window */
if (LL_CMP(t,>,begin) && LL_CMP(t,<,end)) {
ret = PR_TRUE;
} else {
ret = PR_FALSE;
}
loser:
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
if (derWindow) {
SECITEM_FreeItem(derWindow, PR_TRUE);
}
return ret;
}
PRBool CERT_RenewalWindowExpired(CERTCertificate *cert, int64 t)
{
int rv;
int64 begin, end;
CERTRenewalWindow *window = NULL;
SECItem *derWindow = NULL;
PRArenaPool *arena = NULL;
PRBool ret = PR_FALSE;
/* Allocate from the heap, so that we can free eveything later */
derWindow = SECITEM_AllocItem(NULL, NULL, 0);
if (derWindow == NULL) {
goto loser;
}
/* Get the renewal window extension */
rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME,
derWindow);
if (rv == SECFailure) {
goto loser;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
goto loser;
window = (CERTRenewalWindow*)PORT_ArenaZAlloc(arena,
sizeof(CERTRenewalWindow));
if (window == NULL) {
goto loser;
}
/* Decode the extension */
rv = SEC_ASN1DecodeItem(arena, window, CERT_RenewalWindowTemplate, derWindow);
if (rv) {
goto loser;
}
/* Decode the times */
rv = DER_GeneralizedTimeToTime(&begin, &window->begin);
if (window->end.data) {
rv = DER_GeneralizedTimeToTime(&end, &window->end);
} else {
rv = DER_UTCTimeToTime(&end, &cert->validity.notAfter);
}
/* Has the renewal window expired */
if (LL_CMP(t,>,end)) {
ret = PR_TRUE;
} else {
ret = PR_FALSE;
}
loser:
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
if (derWindow) {
SECITEM_FreeItem(derWindow, PR_TRUE);
}
return ret;
}
char * CERT_GetAuthorityInfoAccessLocation(CERTCertificate *cert, int method)
{
CERTGeneralName *locname = NULL;
SECItem *location = NULL;
SECItem *encodedAuthInfoAccess = NULL;
CERTAuthInfoAccess **authInfoAccess = NULL;
char *locURI = NULL;
PRArenaPool *arena = NULL;
SECStatus rv;
int i;
/*
* Allocate this one from the heap because it will get filled in
* by CERT_FindCertExtension which will also allocate from the heap,
* and we can free the entire thing on our way out.
*/
encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
if (encodedAuthInfoAccess == NULL)
goto loser;
rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
encodedAuthInfoAccess);
if (rv == SECFailure)
goto loser;
/*
* The rest of the things allocated in the routine will come out of
* this arena, which is temporary just for us to decode and get at the
* AIA extension. The whole thing will be destroyed on our way out,
* after we have copied the location string (url) itself (if found).
*/
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
goto loser;
authInfoAccess = cert_DecodeAuthInfoAccessExtension(arena,
encodedAuthInfoAccess);
if (authInfoAccess == NULL)
goto loser;
for (i = 0; authInfoAccess[i] != NULL; i++) {
if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == method)
locname = authInfoAccess[i]->location;
}
/*
* If we found an AIA extension, but it did not include an OCSP method,
* that should look to our caller as if we did not find the extension
* at all, because it is only an OCSP method that we care about.
* So set the same error that would be set if the AIA extension was
* not there at all.
*/
if (locname == NULL) {
PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
goto loser;
}
/*
* The following is just a pointer back into locname (i.e. not a copy);
* thus it should not be freed.
*/
location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE);
if (location == NULL) {
/*
* XXX Appears that CERT_GetGeneralNameByType does not set an
* error if there is no name by that type. For lack of anything
* better, act as if the extension was not found. In the future
* this should probably be something more like the extension was
* badly formed.
*/
PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
goto loser;
}
/*
* That location is really a string, but it has a specified length
* without a null-terminator. We need a real string that does have
* a null-terminator, and we need a copy of it anyway to return to
* our caller -- so allocate and copy.
*/
locURI = PORT_Alloc(location->len + 1);
if (locURI == NULL) {
goto loser;
}
PORT_Memcpy(locURI, location->data, location->len);
locURI[location->len] = '\0';
loser:
if (arena != NULL)
PORT_FreeArena(arena, PR_FALSE);
if (encodedAuthInfoAccess != NULL)
SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE);
return locURI;
}
SSMStatus
SendRenewalUIEvent(SSMControlConnection *conn,
char *url)
{
SECItem event;
SSMStatus rv = PR_SUCCESS;
SSMResourceID rid = 0;
UIEvent reply;
if (!conn->m_doesUI) {
return SSM_FAILURE;
}
/* Generate the actual message to send to the client. */
reply.resourceID = rid;
reply.width = 715;
reply.height = 545;
reply.isModal = CM_FALSE;
reply.url = url;
reply.clientContext.len = 0;
reply.clientContext.data = NULL;
if (CMT_EncodeMessage(UIEventTemplate, (CMTItem*)&event, &reply) != CMTSuccess) {
goto loser;
}
/* Post the message on the outgoing control channel. */
rv = SSM_SendQMessage(conn->m_controlOutQ, SSM_PRIORITY_NORMAL,
SSM_EVENT_MESSAGE | SSM_UI_EVENT,
(int) event.len, (char *) event.data, PR_FALSE);
if (rv != PR_SUCCESS) goto loser;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
PR_FREEIF(event.data);
return rv;
}
SECStatus CheckCertificate(CERTCertificate * cert, void * arg)
{
char *url = NULL;
SSMControlConnection *ctrl = (SSMControlConnection *)arg;
SSMStatus rv;
SSMResourceID certID;
SSMResourceCert * certRes = NULL;
CERTCertificate *otherCert = NULL;
CERTCertList *certs = NULL;
CERTCertListNode *node;
/* Is this cert in the renewal window */
if (CERT_InRenewalWindow(cert, PR_Now()) == PR_FALSE) {
goto done;
}
/* Get the AIA */
url = CERT_GetAuthorityInfoAccessLocation(cert, SEC_OID_CERT_RENEWAL_LOCATOR);
if (!url) {
goto done;
}
/* Should we renew this cert? Check the case where it has already been renewed */
/* but the old cert is still there waith a valid renewal window */
certs = PK11_FindCertsFromNickname(cert->nickname, ctrl);
if (!cert) {
goto done;
}
/* Interate through the certs */
node = CERT_LIST_HEAD(certs);
while (!CERT_LIST_END(node, certs)) {
otherCert = node->cert;
/* This is the cert we are renewing */
if (otherCert == cert) {
goto endloop;
}
/* This cert has expired */
if (CERT_CheckCertValidTimes(otherCert, PR_Now(), PR_FALSE) != secCertTimeValid) {
goto endloop;
}
/* This cert has different key usage */
if (cert->keyUsage != otherCert->keyUsage) {
goto endloop;
}
/* This cert renewal window has not expired - don't renew our cert */
if (CERT_HasRenewalExtension(otherCert) && !CERT_RenewalWindowExpired(otherCert, PR_Now())) {
goto done;
}
endloop:
node = CERT_LIST_NEXT(node);
}
/* Create a resource for this cert and get an id */
rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
cert,
ctrl,
&certID,
(SSMResource**)&certRes);
if (rv != PR_SUCCESS) {
goto done;
}
SSM_LockUIEvent((SSMResource*)certRes);
/* Send a UI event to client */
rv = SSMControlConnection_SendUIEvent(ctrl, "get",
"cert_renewal",
&(certRes->super), NULL, &(&(ctrl->super.super))->m_clientContext);
if (rv != SSM_SUCCESS) {
goto loser;
}
SSM_WaitUIEvent((SSMResource*)certRes, PR_INTERVAL_NO_TIMEOUT);
if ((certRes->super.m_buttonType == SSM_BUTTON_OK) && (certRes->m_renewCert == PR_TRUE)) {
/* Send a UI event asking about renewal */
/* Send UI prompting the user */
SendRenewalUIEvent(ctrl, url);
}
loser:
done:
if (certs) {
CERT_DestroyCertList(certs);
}
if (certRes) {
SSM_FreeResource(certRes);
}
PR_FREEIF(url);
return SECSuccess;
}
void SSM_CertificateRenewalThread(void * arg)
{
int series, slotSeries[255], i = 0;
PK11SlotList * slots = NULL;
PK11SlotListElement * le = NULL;
SSMControlConnection *ctrl = (SSMControlConnection *)arg;
/* Initialize slot series array to zero */
memset(slotSeries, 0, sizeof(slotSeries));
/* Get a list of tokens installed */
slots = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, ctrl);
if (!slots) {
return;
}
while (1) {
/* Interate over the list of slots */
for (le = slots->head, i= 0; le; le = le->next, i++) {
/* If there is no token present then we are no interested */
if (!PK11_IsPresent(le->slot)) {
continue;
}
/* If token not logged in, then we are not interested */
if (!PK11_IsLoggedIn(le->slot, ctrl)) {
continue;
}
/* If token is read-only, then we are not interested */
if (PK11_IsReadOnly(le->slot)) {
continue;
}
/* Get the series and mark as checked */
series = PK11_GetSlotSeries(le->slot);
if (slotSeries[i] == series) {
continue;
}
slotSeries[i] = series;
/* Interate all the certs on the token */
PK11_TraverseCertsInSlot(le->slot, CheckCertificate, ctrl);
}
/* Sleep for one minute */
PR_Sleep(PR_TicksPerSecond()*60);
}
if (slots) {
PK11_FreeSlotList(slots);
}
}
SSMStatus SSM_RenewalCertInfoHandler(SSMTextGenContext* cx)
{
SSMStatus rv;
SSMResource* target = NULL;
SSMResourceCert* renewalCertRes = NULL;
CERTCertificate* renewalCert = NULL;
char *fmt = NULL, *issuerCN = NULL;
char *validNotBefore = NULL, *validNotAfter = NULL;
PR_ASSERT(cx != NULL);
PR_ASSERT(cx->m_request != NULL);
PR_ASSERT(cx->m_params != NULL);
PR_ASSERT(cx->m_result != NULL);
/* retrieve the renewal cert */
target = SSMTextGen_GetTargetObject(cx);
renewalCertRes = (SSMResourceCert*)target;
renewalCert = renewalCertRes->cert;
if (renewalCert == NULL) {
goto loser;
}
/* Get the info */
/* This is: Name, issuer, valid from and valid to */
issuerCN = CERT_GetCommonName(&renewalCert->issuer),
validNotBefore = DER_UTCDayToAscii(&renewalCert->validity.notBefore);
validNotAfter = DER_UTCDayToAscii(&renewalCert->validity.notAfter);
rv = SSM_GetAndExpandTextKeyedByString(cx, "cert_renewal_cert_info", &fmt);
if (rv != SSM_SUCCESS) {
goto loser;
}
cx->m_result = PR_smprintf(fmt, renewalCert->nickname, validNotBefore, validNotAfter, issuerCN);
PR_FREEIF(fmt);
PR_FREEIF(issuerCN);
PR_FREEIF(validNotBefore);
PR_FREEIF(validNotAfter);
return SSM_SUCCESS;
loser:
PR_FREEIF(fmt);
PR_FREEIF(issuerCN);
PR_FREEIF(validNotBefore);
PR_FREEIF(validNotAfter);
return SSM_FAILURE;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,134 @@
/*
* 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.
*/
#ifndef __NSM_CERTRES_H__
#define __NSM_CERTRES_H__
#include "servimpl.h"
#include "resource.h"
#include "cert.h"
#include "certdb.h"
#include "secder.h"
#include "ctrlconn.h"
#include "minihttp.h"
#include "textgen.h"
struct _ssm_resource_cert;
typedef SSMStatus (*SSMCertResourceVerifyFunc)
(struct _ssm_resource_cert * resource,
SECCertUsage certUsage);
typedef SSMStatus (*SSMCertResourceDeleteCertFunc)
(struct _ssm_resource_cert * resource);
typedef struct _ssm_resource_cert
{
SSMResource super;
CERTCertificate * cert;
SSMCertResourceVerifyFunc m_verify_func;
SSMCertResourceDeleteCertFunc m_deletecert_func;
PRBool m_markedForDeletion;
PRBool m_renewCert;
} SSMResourceCert;
/*
* Cert resource can be created from a CERTCertificate or when unpickling.
*/
typedef enum {
SSM_RESOURCE_CERT_CREATE_NEW = 0L,
SSM_RESOURCE_CERT_CREATE_UNPICKLE
} SSMResourceCertCreate;
/* Functions of the certResource class */
SSMStatus SSMResourceCert_Create(void * arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMResourceCert_Init(SSMResourceCert * certResource,
SSMControlConnection * conn,
void * arg);
SSMStatus SSMResourceCert_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMResourceCert_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMResourceCert_Destroy(SSMResource *res, PRBool doFree);
SSMStatus SSMResourceCert_Pickle(SSMResource *res, PRIntn *len, void ** rdata);
SSMStatus SSMResourceCert_Verify(SSMResourceCert * resource,
SECCertUsage certUsage);
SSMStatus SSMResourceCert_DeleteCert(SSMResourceCert * resource);
SSMStatus SSMResourceCert_Unpickle(SSMResource ** resource,
SSMControlConnection * conn, PRInt32 len,
void * value);
SSMStatus SSMResourceCert_HTML(SSMResource *res, PRIntn * len, void ** value);
SSMStatus SSMResourceCert_FormSubmitHandler(SSMResource *res, HTTPRequest *req);
/* Other cert resource functions */
SSMStatus SSM_VerifyCert(SSMResourceCert * resource,
SECCertUsage certUsage);
SSMStatus SSM_DeleteCert(SSMResourceCert * resource);
SSMStatus SSM_DeleteCertHandler(HTTPRequest * req);
SSMStatus SSM_HTTPCertListHandler(HTTPRequest * req);
SSMStatus SSM_ViewCertInfoKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_VerifyCertKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_SelectCertKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_ChooseCertUsageHandler(HTTPRequest * req);
SSMStatus SSM_EditCertKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_EditCertificateTrustHandler(HTTPRequest * req);
SSMStatus SSM_DeleteCertHelpKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_DeleteCertWarnKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_ObtainNewCertSite(SSMTextGenContext * cx);
SSMStatus SSM_ProcessLDAPRequestHandler(HTTPRequest * req);
SSMStatus SSM_LDAPServerListKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_ProcessLDAPWindow(HTTPRequest * req);
SSMStatus
SSM_ProcessCertUIAction(HTTPRequest * req, CERTCertificate * cert);
SSMStatus SSM_ProcessCertDeleteButton(HTTPRequest * req);
int SSM_CertListCount(CERTCertList *certList);
SSMStatus SSM_OCSPOptionsKeywordHandler(SSMTextGenContext *cx);
SSMStatus SSM_OCSPDefaultResponderKeywordHandler(SSMTextGenContext *cx);
SSMStatus
SSM_CompleteLDAPLookup(SSMControlConnection *ctrl, char * ldapserver,
char * emailaddr);
char * SSM_GetCAPolicyString(char * org, unsigned long noticeNum, void * arg);
#endif

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

@ -0,0 +1,251 @@
/*
* 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.
*/
/* LDAP Cert Search */
#include <ldap.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "certsearch.h"
/* XXX TRUE & FALSE is not defined (on Unix): get by for now by using this
* macro */
#define SSM_LDAP_TRUE 1
#define SSM_LDAP_FALSE 0
int LDAPCertSearch (const char * rcpt_address, const char * server_name,
const char * baseDN, int port, int connect_type,
const char * certdb_path, const char * auth_dn,
const char * auth_password, const char * mail_attribs,
const char * cert_attribs, cert_struct * certs[])
{
int rtnval;
LDAP * ld;
char *filter, *tstr, *tmpstr, *tmpstr1;
int addr_len, attr_count = 0, filter_length = 0;
char mail_array[3][80];
char **cert_attrib_array, **tmp_cert_array;
LDAPMessage *reslt, *entry;
int attrib_name_count, entry_count;
void * cert;
/* First some simple param checking */
if (!server_name || !*server_name)
return 1;
if (!rcpt_address || !*rcpt_address)
return 2;
if (connect_type < CLEAR_ANON || connect_type > SSL_CERTAUTH)
return 3;
if (!cert_attribs || !*cert_attribs)
return 2;
/* Okay, try to init connection to LDAP Server */
if (connect_type == CLEAR_ANON || connect_type == CLEAR_AUTH)
ld = ldap_init(server_name, 389);
#if 0
/* don't bother with SSL yet */
else { /* SSL Connection */
/* First init Client connection to db files needed */
if (connect_type == SSL_CERTAUTH) {
/* don't bother yet. keydbpath is full path of key3.db file (e.g. ...users/bruces)
if (ldapssl_clientauth_init(certdb_path, NULL, needkeydb, keydbpath,
NULL) < 0)
return 4; */
} else {
if (ldapssl_client_init(certdb_path, NULL) < 0)
return 4;
}
/* Now attempt SSL connection to LDAP Server */
ld = ldapssl_init(server_name, port, 1);
}
#endif
if (!ld) /* failed to init connection to LDAP server */
return 4;
/* Now bind to server (NULL/Anon bind if not AUTH type connection) */
if (connect_type == CLEAR_ANON || connect_type == SSL_ANON)
rtnval = ldap_simple_bind_s(ld, NULL, NULL);
else if (connect_type == CLEAR_AUTH || connect_type == SSL_AUTH)
rtnval = ldap_simple_bind_s(ld, auth_dn, auth_password);
/* else if (connect_type == SSL_CERTAUTH)
rtnval = ldap_sasl_bind_s(ld, auth_dn, [mechanism], [cred], NULL,
NULL, servercredp) */
if (rtnval != LDAP_SUCCESS)
return 5;
/*
// Now ready to search
*/
/* First create the filter from attrib(s) and rcpt_address */
/* first compute size of filter to create, and collect mail attribs */
addr_len = strlen(rcpt_address);
tmpstr1 = (char *)PR_Malloc(strlen(mail_attribs)+1);
strcpy(tmpstr1, mail_attribs);
tmpstr = tmpstr1;
while (tstr = strchr(tmpstr, ',')) {
*tstr = '\0';
filter_length += addr_len + strlen(tmpstr) + 5;
strcpy(mail_array[attr_count++], tmpstr);
tmpstr = tstr+1;
}
/* and get last mail attribute */
filter_length += addr_len + strlen(tmpstr) + 5;
strcpy(mail_array[attr_count++], tmpstr);
filter = (char *)PR_Malloc(filter_length);
PR_Free(tmpstr1);
/* should figure out way to generalize this :-( */
if (attr_count == 1)
sprintf(filter, "(%s=%s)", mail_array[0], rcpt_address);
else if (attr_count == 2)
sprintf(filter, "(|(%s=%s)(%s=%s))", mail_array[0], rcpt_address,
mail_array[1], rcpt_address);
else if (attr_count == 3)
sprintf(filter, "(|(%s=%s)(%s=%s)(%s=%s))", mail_array[0], rcpt_address,
mail_array[1], rcpt_address, mail_array[2], rcpt_address);
else
return 6; /* too many mail attribs (should fix this eventually) */
/* Also get list of Cert attribs */
cert_attrib_array = (char **)PR_Malloc(50); /* space for array of ptrs */
tmp_cert_array = cert_attrib_array;
tmpstr = (char *)PR_Malloc(strlen(cert_attribs)+1);
strcpy(tmpstr, cert_attribs);
tmpstr1 = tmpstr;
while (tstr = strchr(tmpstr, ',')) {
*tstr = '\0';
*tmp_cert_array = (char *)PR_Malloc(strlen(tmpstr)+1);
strcpy(*tmp_cert_array, tmpstr);
*tmp_cert_array++;
tmpstr = tstr+1;
}
/* get last attribute, and put in NULL entry as end */
*tmp_cert_array = (char *)PR_Malloc(strlen(tmpstr)+1);
strcpy(*tmp_cert_array, tmpstr);
*tmp_cert_array++;
*tmp_cert_array = NULL;
PR_Free(tmpstr1);
/* Now perform the search and check response */
rtnval = ldap_search_s(ld, baseDN, LDAP_SCOPE_SUBTREE, filter,
cert_attrib_array, SSM_LDAP_FALSE, &reslt);
PR_Free(filter);
if (rtnval != LDAP_SUCCESS) {
for (tmp_cert_array = cert_attrib_array; *tmp_cert_array;
tmp_cert_array++)
PR_Free(*tmp_cert_array);
PR_Free(cert_attrib_array);
return 7; /* LDAP Failure */
}
entry_count = ldap_count_entries(ld, reslt);
if (entry_count == 0) {
for (tmp_cert_array = cert_attrib_array; *tmp_cert_array;
tmp_cert_array++)
PR_Free(*tmp_cert_array);
PR_Free(cert_attrib_array);
ldap_msgfree(reslt);
ldap_unbind(ld);
return -1; /* no entry found for rcpt */
}
if (entry_count > 1) {
for (tmp_cert_array = cert_attrib_array; *tmp_cert_array;
tmp_cert_array++)
PR_Free(*tmp_cert_array);
PR_Free(cert_attrib_array);
ldap_msgfree(reslt);
ldap_unbind(ld);
return 8; /* multiple entries found for rcpt */
}
/*
*Okay, got an entry, check for Cert
*/
rtnval = 9; /* default is to return no attrib found */
/* Now check each cert attribute type */
entry = ldap_first_entry(ld, reslt);
attrib_name_count = 0;
tmp_cert_array = cert_attrib_array;
while (*tmp_cert_array) {
struct berval cert_attrib_struct;
struct berval **cert_out_list;
struct cert_struct_def * cert_ptr;
int valcount=0;
cert_out_list = ldap_get_values_len(ld, entry, *tmp_cert_array);
if (cert_out_list) { /* Values found for this cert attr */
while (SSM_LDAP_TRUE) { /* just get count for malloc first */
if (!cert_out_list[valcount++])
break;
}
certs[attrib_name_count] = PR_Malloc(valcount * sizeof(cert_struct));
cert_ptr = certs[attrib_name_count];
valcount =0;
while (SSM_LDAP_TRUE) {
if (!cert_out_list[valcount])
break;
cert_attrib_struct = *cert_out_list[valcount++];
cert = PR_Malloc(cert_attrib_struct.bv_len);
memcpy(cert, cert_attrib_struct.bv_val,
cert_attrib_struct.bv_len);
cert_ptr->cert = cert;
cert_ptr->cert_len = cert_attrib_struct.bv_len;
cert_ptr++;
rtnval = 0; /* found at least one Cert */
}
cert_ptr->cert_len = 0; /* end list */
}
ldap_value_free_len(cert_out_list);
*tmp_cert_array++;
attrib_name_count++;
}
for (tmp_cert_array = cert_attrib_array; *tmp_cert_array;
tmp_cert_array++)
PR_Free(*tmp_cert_array);
PR_Free(cert_attrib_array);
ldap_msgfree(reslt);
ldap_unbind(ld);
return rtnval;
}

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

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

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

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

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

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,255 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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.
*/
#ifndef __SSM_CTRLCONN_H__
#define __SSM_CTRLCONN_H__
#include "connect.h"
#include "cert.h"
#include "key.h"
#include "hashtbl.h"
#include "obscure.h"
#include "prefs.h"
/*
Control connections.
*/
extern SSMHashTable * ctrlConnections;
struct SSMControlConnection
{
SSMConnection super;
/*
---------------------------------------------
Control connection-specific fields
---------------------------------------------
*/
PRUint32 m_version; /* Protocol version supported by client */
char * m_nonce; /* Nonce used for verifying data connections */
PRFileDesc * m_socket; /* Socket serviced by this connection object */
PRThread * m_writeThread;/* Write Control thread (writes m_socket) */
PRThread * m_frontEndThread; /* Front end thread - reads m_socket */
PRThread * m_certRenewalThread; /* Front end thread - reads m_socket */
char * m_profileName; /* Name of user profile (where to find
certs etc) */
char * m_dirRoot; /* Path to directory for certs for control connection */
/* Queue for outgoing messages */
SSMCollection *m_controlOutQ; /* Control msg queue: from readMsg thread
to writeMsg thread */
CERTCertDBHandle *m_certdb;
SECKEYKeyDBHandle *m_keydb;
/* Fields used for out-of-band password requests */
SSMHashTable * m_passwdTable;
PRMonitor * m_passwdLock;
SSMHashTable * m_encrPasswdTable;
PRMonitor * m_encrPasswdLock;
PRInt32 m_waiting;
SSMHashTable *m_resourceDB;
SSMHashTable *m_classRegistry;
SSMHashTable * m_resourceIdDB;
SSMResourceID m_lastRID;
SSMHashTable * m_certIdDB;
SECItem * m_secAdvisorList;
PRInt32 m_certNext;
/* Data socket and port */
PRFileDesc * m_dataSocket;
PRIntn m_dataPort;
PRBool m_doesUI;
PrefSet* m_prefs;
PRBool m_pkcs11Init;
};
SSMStatus SSM_InitPolicyHandler(void);
SSMStatus SSMControlConnection_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMControlConnection_Init(SSMControlConnection *res,
SSMResourceType type,
PRFileDesc *socket);
SSMStatus SSMControlConnection_Shutdown(SSMResource *conn, SSMStatus status);
SSMStatus SSMControlConnection_Destroy(SSMResource *res, PRBool doFree);
SSMStatus SSMControlConnection_GetAttrIDs(SSMResource* res, SSMAttributeID** ids,
PRIntn* count);
SSMStatus SSMControlConnection_GetAttr(SSMResource *res, SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
void SSMControlConnection_Invariant(SSMControlConnection *conn);
SSMStatus SSMControlConnection_ProcessMessage(SSMControlConnection* control,
SECItem* msg);
void SSM_WriteCtrlThread(void * arg);
void SSM_FrontEndThread(void * arg);
void SSM_CertificateRenewalThread(void * arg);
SSMStatus SSMControlConnection_Authenticate(SSMConnection *arg, char *nonce);
void SSMControlConnection_CertLookUp(SSMControlConnection * connection,
void * arg, SSMResource ** res);
SSMStatus SSMControlConnection_SendUIEvent(SSMControlConnection *conn,
char *command,
char *baseRef,
SSMResource *target, /* can pass NULL */
char *otherParams /* can pass NULL */,
CMTItem * clientContext /* can pass NULL */);
/*
* NOTES
* These functions save the pref change properly in memory and in client file.
* They check first whether the value has changed and perform saving
* operations.
* These functions do not belong to the prefs API because these specifically
* send the changes to the plugin. Once we have our own prefs library ready
* and complete the migration, these functions should be called only when
* application-specific prefs are saved back to client pref file.
* Since these functions pack one item only, if you have to send a lot of
* pref changes and performance is critical, it is not recommended to call
* these functions repeatedly.
*
*/
SSMStatus SSMControlConnection_SaveStringPref(SSMControlConnection* ctrl,
char* key, char* value);
SSMStatus SSMControlConnection_SaveBoolPref(SSMControlConnection* ctrl,
char* key, PRBool value);
SSMStatus SSMControlConnection_SaveIntPref(SSMControlConnection* ctrl,
char* key, PRIntn value);
void SSMControlConnection_CertLookUp(SSMControlConnection * connection,
void * arg, SSMResource ** res);
void SSM_LockPasswdTable(SSMConnection * conn);
SSMStatus SSM_UnlockPasswdTable(SSMConnection *conn);
SSMStatus SSM_WaitPasswdTable(SSMConnection * conn);
SSMStatus SSM_NotifyAllPasswdTable(SSMConnection * conn);
SSMStatus SSMControlConnection_AddResource(SSMResource * res, SSMResourceID rid);
SSMStatus SSMControlConnection_GetResource(SSMControlConnection * connection,
SSMResourceID rid,
SSMResource ** res);
SSMStatus SSMControlConnection_GetGlobalResourceID(SSMControlConnection
*connection,
SSMResource * res,
SSMResourceID * rid);
SSMResourceID SSMControlConnection_GenerateResourceID(SSMControlConnection *conn);
SSMStatus SSM_GetControlConnection(SSMResourceID rid,
SSMControlConnection **connection);
SSMStatus SSMControlConnection_FormSubmitHandler(SSMResource* res,
HTTPRequest* req);
void SSMControlConnection_RecycleItem(SECItem* msg);
SSMStatus SSMControlConnection_GenerateNonce(SSMControlConnection *conn);
/* from processmsg.c */
SSMStatus
SSMControlConnection_ProcessVerifyCertRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessImportCertRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessConserveRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessPickleRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessUnpickleRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessCertRequest(SSMControlConnection * ctrl,
SECItem * msg);
PRStatus
SSMControlConnection_ProcessKeygenTag(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessPKCS11Request(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessCRMFRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessMiscRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessFormSigningRequest(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessTLSRequest(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessProxyStepUpRequest(SSMControlConnection* ctrl,
SECItem* msg);
SSMStatus
SSMControlConnection_ProcessSecCfgRequest(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessGenKeyOldStyleToken(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessGenKeyPassword(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSM_CertCAImportCommandHandler2(HTTPRequest * req);
void
ssm_ShutdownNSS(SSMControlConnection *ctrl);
SSMStatus
SSM_UseAsDefaultEmailIfNoneSet(SSMControlConnection *ctrl,
CERTCertificate *cert, PRBool onFrontEndThread);
CERTCertList *
SSMControlConnection_CreateCertListByNickname(SSMControlConnection * ctrl,
char * nick, PRBool email);
SSMStatus
ssmcontrolconnection_encode_err_reply(SECItem *msg, SSMStatus rv);
SSMStatus
ssmcontrolconnection_send_message_to_client(SSMControlConnection *ctrl,
SECItem *msg);
#endif /* __SSM_CTRLCONN_H__ */

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

@ -0,0 +1,439 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 "connect.h"
#include "dataconn.h"
#include "ctrlconn.h"
#include "servimpl.h"
#include "serv.h"
#include "ssmerrs.h"
#define SSMCONNECTION(p) (&(p)->super)
#define SSMRESOURCE(p) (&(p)->super.super)
/* How many milliseconds to wait for client input */
#define SSM_READCLIENT_POKE_INTERVAL 30000
SSMStatus SSMDataConnection_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMDataConnection *conn;
*res = NULL; /* in case we fail */
conn = (SSMDataConnection *) PR_CALLOC(sizeof(SSMDataConnection));
if (!conn) goto loser;
rv = SSMDataConnection_Init(conn, (SSMControlConnection *) arg,
SSM_RESTYPE_DATA_CONNECTION);
if (rv != PR_SUCCESS) goto loser;
SSMDataConnection_Invariant(conn);
*res = SSMRESOURCE(conn);
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (conn)
{
SSM_ShutdownResource(SSMRESOURCE(conn), rv);
SSM_FreeResource(SSMRESOURCE(conn));
}
return rv;
}
SSMStatus SSMDataConnection_Init(SSMDataConnection *conn,
SSMControlConnection *parent,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
SSMResourceType parentType = RESOURCE_CLASS(parent);
PR_ASSERT(parent != NULL);
PR_ASSERT((parentType == SSM_RESTYPE_CONTROL_CONNECTION) || (parentType == SSM_RESTYPE_CONNECTION));
if (!parent) goto loser;
rv = SSMConnection_Init(parent, SSMCONNECTION(conn), type);
if (rv != PR_SUCCESS) goto loser;
/* Initialize data shutdown queue. */
conn->m_shutdownQ = SSM_NewCollection();
if (conn->m_shutdownQ == NULL) {
goto loser;
}
/* Hang our shutdown func. */
SSMCONNECTION(conn)->m_auth_func = SSMDataConnection_Authenticate;
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
return rv;
}
SSMStatus SSMDataConnection_Destroy(SSMResource *res, PRBool doFree)
{
SSMDataConnection *conn = (SSMDataConnection *) res;
/* We should be shut down. */
PR_ASSERT(res->m_threadCount == 0);
/* Drain and destroy the queue. */
if (conn->m_shutdownQ) {
ssm_DrainAndDestroyQueue(&(conn->m_shutdownQ));
}
/* Destroy superclass fields. */
SSMConnection_Destroy(&(conn->super.super), PR_FALSE);
/* Free the connection object if asked. */
if (doFree)
PR_DELETE(conn);
return PR_SUCCESS;
}
void
SSMDataConnection_Invariant(SSMDataConnection *conn)
{
if (conn)
{
SSMConnection_Invariant(&conn->super);
SSM_LockResource(SSMRESOURCE(conn));
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn), SSM_RESTYPE_DATA_CONNECTION));
PR_ASSERT(conn->m_shutdownQ != NULL);
SSM_UnlockResource(SSMRESOURCE(conn));
}
}
SSMStatus
SSMDataConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMConnection_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 1) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_CONN_DATA_PENDING;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMDataConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMStatus rv = PR_SUCCESS;
/* see what it is */
switch(attrID)
{
case SSM_FID_CONN_DATA_PENDING:
/* this is not used: will set it to zero for now */
*(PRUint32*)value->u.numeric = (PRUint32)0;
value->type = SSM_NUMERIC_ATTRIBUTE;
break;
default:
rv = SSMConnection_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS) goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
done:
return rv;
}
SSMStatus SSMDataConnection_SetupClientSocket(SSMDataConnection* conn)
{
SSMControlConnection* parent = NULL;
char* pNonce;
char* temp = NULL; /* for nonce verification */
PRFileDesc* socket = NULL; /* client socket */
PRNetAddr clientAddr;
SSMStatus status = PR_FAILURE;
PRIntn read;
PR_ASSERT(conn != NULL);
/* Allocate a nonce-sized chunk of memory to read into.
(See below.) */
parent = (SSMControlConnection*)(conn->super.m_parent);
PR_ASSERT(parent != NULL);
pNonce = parent->m_nonce;
PR_ASSERT(pNonce != NULL);
SSM_DEBUG("I think my parent's nonce is `%s'.\n", pNonce);
temp = (char*)PORT_ZAlloc(strlen(pNonce));
while ((socket == NULL) && (SSMRESOURCE(conn)->m_status == PR_SUCCESS)) {
SSM_DEBUG("accepting next connect.\n");
/* Wait forever for a connection. (for now) */
socket = PR_Accept(SSMRESOURCE(conn)->m_connection->m_dataSocket,
&clientAddr, PR_INTERVAL_NO_TIMEOUT);
SSM_DEBUG("accepted connection.\n");
if ((SSMRESOURCE(conn)->m_status != PR_SUCCESS) && socket) {
/* May have gotten a socket, but we're shutting down.
Close and zero out the socket. */
PR_Close(socket);
SSM_LockResource(SSMRESOURCE(conn));
socket = conn->m_clientSocket = NULL;
SSM_UnlockResource(SSMRESOURCE(conn));
}
if (socket && !SSM_SocketPeerCheck(socket, PR_FALSE))
{
/*
Failed peer check. Close socket and listen again.
### mwelch - Could have a denial of service attack here if
someone keeps trying to connect to this port.
*/
PR_Close(socket);
socket = NULL;
continue;
}
if (socket) {
SSM_LockResource(SSMRESOURCE(conn));
conn->m_clientSocket = socket;
SSM_UnlockResource(SSMRESOURCE(conn));
SSM_DEBUG("reading/verifying nonce.\n");
status = PR_SUCCESS;
/* Read the nonce from the client. If we didn't get the right
nonce, reject the connection. */
if ((temp) && (pNonce != NULL)) {
read = SSM_ReadThisMany(socket, temp, strlen(pNonce));
if ((unsigned int)read != strlen(pNonce)) {
status = PR_GetError();
}
}
if ((status != PR_SUCCESS) || (memcmp(temp, pNonce,
strlen(pNonce)))) {
#ifdef DEBUG
char thing1[255];
char thing2[255];
strncpy(thing1, temp, strlen(pNonce));
strncpy(thing2, temp, strlen(pNonce));
/* Bad nonce, no biscuit! Shut down connection
and wait for another on the data port. */
SSM_DEBUG("Bad nonce, no biscuit!\n");
SSM_DEBUG("(`%s' != `%s')\n", thing1, thing2);
#endif
SSM_LockResource(SSMRESOURCE(conn));
PR_Close(conn->m_clientSocket);
conn->m_clientSocket = socket = NULL;
SSM_UnlockResource(SSMRESOURCE(conn));
}
}
else {
/* Tear everything down, didn't get a connection. */
SSM_DEBUG("Shutdown during connection setup.\n");
goto loser;
}
}
SSM_DEBUG("Nonce is valid.\n");
/* We have a socket. Close the data port. */
SSM_LockResource(SSMRESOURCE(conn));
SSM_DEBUG("Socket is %ld.\n", socket);
SSM_UnlockResource(SSMRESOURCE(conn));
loser:
if (temp != NULL) {
PR_Free(temp);
}
return status;
}
SSMStatus SSMDataConnection_ReadFromSocket(SSMDataConnection* conn,
PRInt32* read,
char* buffer)
{
SSMStatus status;
#if 0
SSMStatus osStat;
char statBuf[256];
#endif
PR_ASSERT(conn != NULL);
PR_ASSERT(buffer != NULL);
/* Attempt to read LINESIZE bytes from the socket. */
do {
SSM_DEBUG("Attempting to read %ld bytes.\n", *read);
*read = PR_Recv(conn->m_clientSocket, buffer, *read, 0,
PR_MillisecondsToInterval(SSM_READCLIENT_POKE_INTERVAL));
if (*read < 0) {
status = PR_GetError(); /* save status for later use */
#if 0
osStat = PR_GetOSError(); /* just for fun */
PR_GetErrorText(statBuf);
#endif
}
SSM_DEBUG("Got %ld bytes of data, status == %ld.\n", (long)(*read),
(long)status);
}
while ((*read == -1) && (status == PR_IO_TIMEOUT_ERROR) &&
SSMRESOURCE(conn)->m_status == PR_SUCCESS);
/* Don't mask an error if we got one, but set it if we didn't get any
* data (because that indicates a socket closure).
*/
if ((*read < 0) && (status == PR_SUCCESS)) {
status = PR_FAILURE;
}
else if (*read >= 0) {
status = PR_SUCCESS; /* clear the error from when we waited */
}
#if 0
/* Null terminate the buffer so that we can dump it. */
if (*read >= 0) {
buffer[*read] = '\0';
}
#endif
if (*read > 0) {
SSM_DEBUG("got %ld bytes of data: <%s>\n", *read, buffer);
}
return status;
}
SSMStatus
SSMDataConnection_Shutdown(SSMResource *res, SSMStatus status)
{
SSMStatus rv, trv;
PRThread *closer = PR_GetCurrentThread();
SSMDataConnection *conn = (SSMDataConnection *) res;
/* SSMDataConnection_Invariant(conn); -- could be called from loser */
/* Lock down the resource before shutting it down */
SSM_LockResource(SSMRESOURCE(conn));
/* If we're called from a service thread, clear that thread's
place in the connection object so it doesn't get interrupted */
if ((closer == conn->m_dataServiceThread) && (closer != NULL)) {
conn->m_dataServiceThread = NULL;
/* Decrement living thread counter */
SSMRESOURCE(conn)->m_threadCount--;
}
/* shut down base class */
rv = SSMConnection_Shutdown(res, status);
if ((SSMRESOURCE(conn)->m_status != PR_SUCCESS) &&
(rv != SSM_ERR_ALREADY_SHUT_DOWN) &&
(conn->m_clientSocket != NULL))
{
SSM_DEBUG("Shutting down data connection abnormally (rv == %d).\n",
SSMRESOURCE(conn)->m_status);
SSM_DEBUG("shutting down client socket.\n");
PR_Shutdown(conn->m_clientSocket, PR_SHUTDOWN_SEND);
/* if this is called by a control thread, send a message to the
* data service thread to shut down
*/
if ((closer != conn->m_dataServiceThread) &&
(conn->m_shutdownQ != NULL)) {
SSM_DEBUG("Send shutdown msg to data Q.\n");
trv = SSM_SendQMessage(conn->m_shutdownQ, SSM_PRIORITY_SHUTDOWN,
SSM_DATA_PROVIDER_SHUTDOWN, 0, NULL,
PR_TRUE);
}
if (conn->m_dataServiceThread) {
PR_Interrupt(conn->m_dataServiceThread);
}
}
/* If the client sockets is/are now unused, close them. */
if (SSMRESOURCE(conn)->m_threadCount == 0)
{
/* Close the client socket with linger */
if (conn->m_clientSocket)
{
SSM_DEBUG("Close data socket.\n");
trv = PR_Close(conn->m_clientSocket);
conn->m_clientSocket = NULL;
SSM_DEBUG("Closed client socket (rv == %d).\n",trv);
}
}
SSM_UnlockResource(SSMRESOURCE(conn));
return rv; /* so that subclasses know to perform shutdown */
}
SSMStatus
SSMDataConnection_Authenticate(SSMConnection *arg, char *nonce)
{
SSMStatus rv = SSM_FAILURE;
SSMConnection *parent = arg->m_parent;
/* Parent has the nonce, so authenticate there. */
if (parent &&
SSM_IsAKindOf(&(parent->super), SSM_RESTYPE_CONTROL_CONNECTION))
rv = SSMControlConnection_Authenticate(parent, nonce);
return rv;
}

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

@ -0,0 +1,141 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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.
*/
#ifndef __SSM_DATACONN_H__
#define __SSM_DATACONN_H__
#include "connect.h"
#include "ctrlconn.h"
/*
Cartman data connection/thread architecture:
Data connections are opened by the control connection in response
to a Request {SSL,etc.} Data message. There is one thread per data
connection that handles the data traffic, and there is one queue that
receives a shutdown message from a control thread.
If an exception or other termination occurs on either side, the
m_status flag is changed to the specific exception code, and sockets
are closed on either side (after final thread shutdown).
(### mwelch This has the effect of setting SO_LINGER on the outgoing
data stream, is this an issue?)
*/
/*
Data connection objects.
*/
typedef struct SSMDataConnection
{
SSMConnection super;
/*
---------------------------------------------
Data connection-specific fields - need to
merge with control fields or do something more
elegant in the long term.
---------------------------------------------
*/
PRUint32 m_dataType; /* What type of service are we
providing to client? */
PRThread* m_dataServiceThread; /* one and only data thread */
SSMCollection* m_shutdownQ; /* data queue that delivers a shutdown
message to the data service thread */
PRFileDesc *m_clientSocket; /* Client socket */
PRBool m_sendResult; /* When this connection shuts down,
send a result back to the client
(usage depends on subclass) */
} SSMDataConnection;
SSMStatus SSMDataConnection_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMDataConnection_Init(SSMDataConnection *conn,
SSMControlConnection *parent,
SSMResourceType type);
SSMStatus SSMDataConnection_Destroy(SSMResource *res, PRBool doFree);
void SSMDataConnection_Invariant(SSMDataConnection *conn);
SSMStatus SSMDataConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMDataConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMDataConnection_Shutdown(SSMResource *arg, SSMStatus status);
SSMStatus SSMDataConnection_Authenticate(SSMConnection *arg, char *nonce);
/*
* Function: SSMStatus SSMDataConnection_SetupClientSocket()
* Purpose: sets up the client data socket and authenticates the connection.
* (blocking I/O)
* Arguments and return values:
* - conn: data connection object
* - returns: PR_SUCCESS if successful, error code otherwise
*/
SSMStatus SSMDataConnection_SetupClientSocket(SSMDataConnection* conn);
/*
* Function: SSMStatus SSMDataConnection_ReadFromSocket()
* Purpose: reads data from the client data socket and fill the buffer. When
* particular write target threads read data from the data socket,
* it is recommended that they use this function with the notable
* exception of SSL connections.
* Arguments and return values:
* - conn: data connection object
* - read: this is a value-result argument. It should be set to the data
* chunk size. One should always use LINESIZE unless there is a
* compelling reason to do otherwise. On return, this value will be
* filled with the actual size of the data (or 0 if EOF or < 0 if
* error).
* - buffer: data buffer. The memory should have been allocated before this
* function is called. The buffer size should be at least equal to
* the read size (thus the reason for specifying read value upon
* input).
* - returns: PR_SUCCESS if successful, error code otherwise
*
* Note: this is a blocking I/O operation.
*/
SSMStatus SSMDataConnection_ReadFromSocket(SSMDataConnection* conn,
PRInt32* read,
char* buffer);
#endif

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

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

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

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

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

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

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

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

@ -0,0 +1,65 @@
/*
* 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.
*/
// ===========================================================================
// CCompleteApp.h ©1994-1998 Metrowerks Inc. All rights reserved.
// ===========================================================================
#pragma once
#include <PP_Prefix.h>
#include <LApplication.h>
class CBasicApp : public PP_PowerPlant::LApplication {
public:
CBasicApp(); // constructor registers PPobs
virtual ~CBasicApp(); // stub destructor
// this overriding method handles application commands
virtual Boolean ObeyCommand(PP_PowerPlant::CommandT inCommand, void* ioParam);
// this overriding method returns the status of menu items
virtual void FindCommandStatus(PP_PowerPlant::CommandT inCommand,
Boolean &outEnabled, Boolean &outUsesMark,
PP_PowerPlant::Char16 &outMark, Str255 outName);
protected:
virtual void StartUp(); // override startup functions
};
extern CBasicApp *gTheApp;

611
security/psm/server/main.c Normal file
Просмотреть файл

@ -0,0 +1,611 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 "serv.h"
#include "secport.h"
#include "dataconn.h"
#include "ctrlconn.h"
#include "minihttp.h"
#include "ciferfam.h"
#include "secmime.h"
#include "messages.h"
#include "textgen.h"
#include "oldfunc.h"
#include "nss.h"
#include "p12plcy.h"
#include "nlslayer.h"
void SSM_InitLogging(void);
#ifdef TIMEBOMB
#include "timebomb.h"
#endif
#ifdef WIN32
#include <wtypes.h>
#include <winreg.h>
#include <winerror.h>
#endif
#ifdef XP_UNIX
#include <signal.h>
#include <unistd.h>
#ifndef SIG_ERR
#define SIG_ERR -1
#endif /*SIG_ERR*/
#endif /*XP_UNIX*/
#define POLICY_TYPE_INDEX 0
SSMCollection * connections = NULL;
SSMHashTable * tokenList = NULL;
PRMonitor * tokenLock = NULL;
SSMHashTable * ctrlConnections = NULL;
SSMPolicyType policyType = ssmDomestic;
/*
* The following is a quick write of enabling various ciphers. This code is
* essentially moved from the server core code. Eventually we will need to
* place this data and functionality in a more modular way.
*/
#define SSM_POLICY_END 0 /* end of table */
#define SSM_POLICY_SSL 1 /* SSL ciphersuites: not really used */
#define SSM_POLICY_PK12 2 /* PKCS #12 ciphersuites */
#define SSM_POLICY_SMIME 3 /* S/MIME ciphersuites */
typedef struct {
PRInt32 policy;
PRInt32 key;
PRInt32 value;
} SSMPolicyEntry;
static SSMPolicyEntry ssmPK12PolicyTable[] =
{
{SSM_POLICY_PK12, PKCS12_RC4_40, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_RC4_128, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_RC2_CBC_40, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_RC2_CBC_128, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_DES_56, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_DES_EDE3_168, (PRInt32)PR_TRUE},
{SSM_POLICY_END, 0, 0}
};
static SSMPolicyEntry ssmSMIMEPolicyTable[] =
{
{SSM_POLICY_SMIME, SMIME_RC2_CBC_40, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC2_CBC_64, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC2_CBC_128, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_DES_CBC_56, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_DES_EDE3_168, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_40, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_64, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_128, (PRInt32)PR_TRUE},
{SSM_POLICY_END, 0, 0}
};
static SSMStatus SSM_InstallPK12Policy(void)
{
const SSMPolicyEntry* entry = ssmPK12PolicyTable;
int i;
for (i = 0; entry[i].policy != SSM_POLICY_END; i++) {
if (SEC_PKCS12EnableCipher(entry[i].key, entry[i].value) !=
SECSuccess) {
return SSM_FAILURE;
}
}
return SSM_SUCCESS;
}
static SSMStatus SSM_InstallSMIMEPolicy(void)
{
const SSMPolicyEntry* entry = ssmSMIMEPolicyTable;
int i;
for (i = 0; entry[i].policy != SSM_POLICY_END; i++) {
if (SECMIME_SetPolicy(entry[i].key, entry[i].value) != SECSuccess) {
return SSM_FAILURE;
}
}
return SSM_SUCCESS;
}
/* XXX sjlee: we don't need to do a similar thing for SSL as we can call an
* NSS function to do it
*/
#if 0
/*
* This function is required by svrplcy to set the
* utility policy. This will tell us what kind of
* policy we are running.
*/
SECStatus Utility_SetPolicy(long which, int policy)
{
if (which == POLICY_TYPE_INDEX) {
switch (policy) {
case SVRPLCYDomestic:
policyType = ssmDomestic;
break;
case SVRPLCYExport:
policyType = ssmExport;
break;
case SVRPLCYFrance:
policyType = ssmFrance;
break;
default:
/* This is an unknown policy type. */
PR_ASSERT(0);
break;
}
}
return SECSuccess;
}
#endif
void SSM_SetPolicy(void)
{
#if 0
SVRPLCY_InstallSSLPolicy();
SVRPLCY_InstallPK12Policy();
SVRPLCY_InstallSMIMEPolicy();
SVRPLCY_InstallUtilityPolicy();
#else
/* Always domestic policy now */
NSS_SetDomesticPolicy();
SSM_InstallPK12Policy();
SSM_InstallSMIMEPolicy();
#endif
}
SSMPolicyType
SSM_GetPolicy(void)
{
return policyType;
}
static void
enable_SMIME_cipher_prefs(void)
{
SSMPolicyType policy;
policy = SSM_GetPolicy();
switch (policy)
{
case ssmDomestic:
SECMIME_EnableCipher(SMIME_DES_EDE3_168, 1);
SECMIME_EnableCipher(SMIME_RC2_CBC_128, 1);
SECMIME_EnableCipher(SMIME_RC2_CBC_64, 1);
SECMIME_EnableCipher(SMIME_DES_CBC_56, 1);
#if 0
SECMIME_EnableCipher(SMIME_RC5PAD_64_16_128, 1);
SECMIME_EnableCipher(SMIME_RC5PAD_64_16_64, 1);
SECMIME_EnableCipher(SMIME_FORTEZZA, 1);
#endif
case ssmExport:
SECMIME_EnableCipher(SMIME_RC2_CBC_40, 1);
#if 0
SECMIME_EnableCipher(SMIME_RC5PAD_64_16_40, 1);
#endif
case ssmFrance:
default:
break;
}
/* now tell secmime that we've sent it the last preference */
SECMIME_EnableCipher(CIPHER_FAMILYID_MASK, 0);
}
SECStatus
ssm_InitializePKCS11Strings(void)
{
char *manufacturerID = NULL;
char *libraryDescription = NULL;
char *tokenDescription = NULL;
char *privateTokenDescription = NULL;
char *slotDescription = NULL;
char *privateSlotDescription = NULL;
char *fipsSlotDescription = NULL;
char *fipsPrivateSlotDescription = NULL;
SSMTextGenContext *cx;
SSMStatus rv;
rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "manufacturerID", &manufacturerID);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "libraryDescription",
&libraryDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "tokenDescription",
&tokenDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "privateTokenDescription",
&privateTokenDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "slotDescription", &slotDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "privateSlotDescription",
&privateSlotDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "fipsSlotDescription",
&fipsSlotDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "fipsPrivateSlotDescription",
&fipsPrivateSlotDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
if (cx != NULL) {
SSMTextGen_DestroyContext(cx);
}
PK11_ConfigurePKCS11(manufacturerID, libraryDescription, tokenDescription,
privateTokenDescription, slotDescription,
privateSlotDescription, fipsSlotDescription,
fipsPrivateSlotDescription, 0, 0);
return SECSuccess;
loser:
PR_FREEIF(manufacturerID);
PR_FREEIF(libraryDescription);
PR_FREEIF(tokenDescription);
PR_FREEIF(privateTokenDescription);
PR_FREEIF(slotDescription);
PR_FREEIF(privateSlotDescription);
if (cx != NULL) {
SSMTextGen_DestroyContext(cx);
}
return SECFailure;
}
#ifdef XP_UNIX
#define CATCH_SIGNAL_DEFAULT(SIGNAL) \
if (((int)signal(SIGNAL, psm_signal_handler_default)) == ((int)SIG_ERR)) \
goto loser;
#define CATCH_SIGNAL_IGNORE(SIGNAL) \
if (((int)signal(SIGNAL, psm_signal_handler_ignore)) == ((int)SIG_ERR)) \
goto loser;
static void
psm_signal_handler_default(int sig)
{
#ifdef DEBUG
printf ("Trapping the signal %d\n", sig);
#endif
SSM_ReleaseLockFile();
kill(getpid(),SIGKILL);
}
static void
psm_signal_handler_ignore(int sig)
{
#ifdef DEBUG
printf ("Ignoring the signal %d\n", sig);
#endif
signal(sig,psm_signal_handler_ignore);
}
static SSMStatus
psm_catch_signals(void)
{
CATCH_SIGNAL_IGNORE(SIGHUP);
CATCH_SIGNAL_DEFAULT(SIGINT);
CATCH_SIGNAL_DEFAULT(SIGQUIT);
CATCH_SIGNAL_DEFAULT(SIGILL);
CATCH_SIGNAL_DEFAULT(SIGTRAP);
CATCH_SIGNAL_DEFAULT(SIGABRT);
CATCH_SIGNAL_DEFAULT(SIGIOT);
#ifdef SIGEMT
CATCH_SIGNAL_DEFAULT(SIGEMT);
#endif
CATCH_SIGNAL_DEFAULT(SIGFPE);
CATCH_SIGNAL_DEFAULT(SIGBUS);
CATCH_SIGNAL_DEFAULT(SIGSEGV);
#ifdef SIGSYS
CATCH_SIGNAL_DEFAULT(SIGSYS);
#endif
CATCH_SIGNAL_IGNORE(SIGPIPE);
CATCH_SIGNAL_DEFAULT(SIGTERM);
#ifndef LINUX
CATCH_SIGNAL_DEFAULT(SIGUSR1);
#endif
CATCH_SIGNAL_DEFAULT(SIGUSR2);
#ifdef SIGXCPU
CATCH_SIGNAL_DEFAULT(SIGXCPU);
#endif
#ifdef SIGDANGER
CATCH_SIGNAL_DEFAULT(SIGDANGER);
#endif
return SSM_SUCCESS;
loser:
return SSM_FAILURE;
}
#endif
#if defined(XP_PC) && !defined(DEBUG)
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
LPSTR lpszLine, int nShow)
#else
#ifdef macintosh
/*
We run RunMacPSM in a separate thread off the main thread.
This is because we can't do any blocking I/O routines on the main
thread, because Mac NSPR doesn't own the original thread used to
run the app.
*/
void RunMacPSM(void *arg)
#else
int main(int argc, char ** argv)
#endif
#endif
{
#ifdef macintosh
#pragma unused(arg)
#endif
#if (defined(XP_PC) && !defined(DEBUG)) || (defined(macintosh))
/* substitute argc and argv for NSPR */
int argc = 0;
char *argv[] = {"", NULL};
#endif
PRIntn result = 0;
#ifdef DEBUG
PR_STDIO_INIT();
#endif
#ifdef DEBUG
/* Initialize logging. */
SSM_InitLogging();
#endif
#ifdef TIMEBOMB
SSM_CheckTimebomb();
#endif
#ifdef XP_UNIX
if (psm_catch_signals() != SSM_SUCCESS) {
SSM_DEBUG("Couldn't set signal handlers. Quitting\n");
exit(1);
}
#endif
SSM_SetPolicy();
enable_SMIME_cipher_prefs();
if (SSM_GetPolicy() == ssmDomestic) {
SSM_EnableHighGradeKeyGen();
}
/* Initialize NLS layer */
if (nlsInit() != PR_TRUE) {
SSM_DEBUG("Failed to initialize the NLS layer\n");
exit(1);
}
/* Initialize global list of control connections. */
connections = SSM_NewCollection();
if (connections == NULL)
{
SSM_DEBUG("Can't initialize! (%ld)\n", (long) result);
exit(1);
}
/* Initialize global list of tokens */
result = SSM_HashCreate(&tokenList);
if (result != PR_SUCCESS || !tokenList) {
SSM_DEBUG("Can't initialize - tokenList \n");
exit(result);
}
tokenLock = PR_NewMonitor();
if (!tokenLock) {
SSM_DEBUG("Can't initialize - tokenLock\n");
exit(1);
}
/* Initialize hash table of control connections */
result = SSM_HashCreate(&ctrlConnections);
if (result != PR_SUCCESS || !ctrlConnections) {
SSM_DEBUG("Can't initialize global table for control connections \n");
exit(result);
}
/* Initialize resource table */
SSM_ResourceInit();
if (SSM_InitPolicyHandler() != PR_SUCCESS) {
SSM_DEBUG("Couldn't initialize the Policy Handler.\n");
exit (1);
}
/* initialize random number generator */
SSM_DEBUG("Initializing random number generator.\n");
RNG_RNGInit();
RNG_SystemInfoForRNG();
/*
* All the ciphers except SSL_RSA_WITH_NULL_MD5 are on by default.
* Enable encryption, enable NULL cipher.
*/
#ifdef XP_MAC
result = mainLoop(argc, argv);
#else
result = PR_Initialize(mainLoop, argc, argv, 0);
#endif
#ifdef DEBUG
printf("main: Finishing (%ld)\n", (long) result);
#endif
#ifdef XP_UNIX
SSM_ReleaseLockFile();
#endif
#ifndef XP_MAC
return result;
#endif
}
#ifdef XP_MAC
void *
psm_malloc(unsigned long numbytes)
{
return NewPtrClear(numbytes);
}
void
psm_free(void *ptr)
{
DisposePtr((char *) ptr);
}
#endif
PRIntn mainLoop(PRIntn argc, char ** argv)
{
PRFileDesc *socket, *respsocket;
PRNetAddr clientaddr;
SSMControlConnection *curconnect;
SSMResourceID ctrlID;
SSMStatus status = PR_FAILURE;
PRBool alive = PR_TRUE;
/* Register ourselves so that logs, etc can identify us */
SSM_RegisterThread("main", NULL);
/* Open NLS stuff */
SSM_DEBUG("Initializing NLS.\n");
#ifdef XP_MAC
SSM_InitNLS(":ui:");
#else
SSM_InitNLS("ui");
#endif
ssm_InitializePKCS11Strings();
/* Initialize the protocol */
#ifdef XP_MAC
CMT_Init(malloc, free);
#else
CMT_Init(PR_Malloc, PR_Free);
#endif
/* Open the HTTP listener */
SSM_DEBUG("Opening HTTP thread.\n");
status = SSM_InitHTTP();
if (status != SSM_SUCCESS)
{
SSM_DEBUG("Couldn't open web port. Exiting.\n");
goto loser;
}
/* open a port for control connections, with well-known port# */
socket = SSM_OpenControlPort();
if (!socket)
{
SSM_DEBUG("Couldn't open control port. Exiting.\n");
goto loser;
}
while (alive)
{
/* wait until there is incoming request */
respsocket = PR_Accept(socket, &clientaddr, PR_INTERVAL_NO_TIMEOUT);
/* while (respsocket == NULL)
{
if (PR_GetError() != PR_WOULD_BLOCK_ERROR)
goto loser;
PR_Sleep(CARTMAN_SPINTIME);
#ifdef DEBUG
printf("master: Still ready for client connection on port %d\n", CARTMAN_PORT); fflush(stdout);
#endif
respsocket = PR_Accept(socket, &clientaddr,
PR_SecondsToInterval(2));
} */
if (!respsocket) {
/* accept failed: abort */
status = PR_GetError();
SSM_DEBUG("Error %d accepting control connection. Exiting.\n",
status);
goto loser;
}
if (SSM_SocketPeerCheck(respsocket, PR_TRUE)) {
SSM_DEBUG("creating control connection.\n");
status = SSM_CreateResource(SSM_RESTYPE_CONTROL_CONNECTION,
respsocket,
NULL,
&ctrlID,
(SSMResource **) &curconnect);
if (status != PR_SUCCESS)
break;
PR_ASSERT(RESOURCE_CLASS(curconnect) == SSM_RESTYPE_CONTROL_CONNECTION);
}
else {
/* connection did not come from localhost: shut down the
* connection and continue to loop
*/
SSM_DEBUG("Connection attempt from a non-local host!\n");
status = PR_Shutdown(respsocket, PR_SHUTDOWN_BOTH);
respsocket = NULL;
}
} /* end while(true) */
loser:
/* Shut down the HTTP thread. */
if (httpListenThread != NULL){
PR_Interrupt(httpListenThread);
}
exit(1);
/* ### mwelch - should we return meaningful error code? */
return 0;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,219 @@
/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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.
*/
#ifndef __SSM_MINIHTTP_H__
#define __SSM_MINIHTTP_H__
#include "ssmerrs.h"
#include "ssmdefs.h"
#include "serv.h"
#include "prthread.h"
#include "ctrlconn.h"
#include "nlsutil.h"
/* Result codes; see
http://info.internet.isi.edu:80/in-notes/rfc/files/rfc2068.txt
for more information */
typedef enum
{
HTTP_OK = (PRInt32) 200,
HTTP_NO_CONTENT = 204,
HTTP_BAD_REQUEST = 400,
HTTP_UNAUTHORIZED = 401,
HTTP_FORBIDDEN = 403,
HTTP_NOT_FOUND = 404,
HTTP_METHOD_NOT_ALLOWED = 405,
HTTP_INTERNAL_ERROR = 500,
HTTP_NOT_IMPLEMENTED = 501,
HTTP_SERVICE_UNAVAILABLE = 503,
HTTP_GATEWAY_TIMEOUT = 504,
HTTP_VERSION_UNSUPPORTED = 505
} HTTPErrorCode;
/* ### mwelch - This has to be done better after the 11/1998 demo. */
typedef enum
{
SSM_UI_NULL = (PRUint32) 0,
SSM_UI_KEYGEN_PROGRESS, /* Frameset containing keygen components */
SSM_UI_DIALOG_FRAMESET, /* Generic frameset for dialogs */
SSM_UI_DIALOG_FB, /* Dialogs: NSM -> client feedback, kept open */
SSM_UI_DIALOG_CANCEL /* A "cancel" command invokable by the client */
} SSMDialogSelector;
struct HTTPRequest
{
PRFileDesc *sock; /* Socket with which we talk to client */
char *rawreqbuf; /* Copy of the raw request we got */
char *reqbuf; /* The HTTP request we got,
which is later parsed */
char **paramNames; /* Names of parameters passed to the URL */
char **paramValues; /* Values of parameters passed to the URL */
PRUint32 numParams; /* How many parameters were passed */
PRUint32 slen; /* The amount of actual text in the buffer(s) */
PRUint32 len; /* The allocated length of the buffer(s) */
char *hdrbuf; /* Response header */
SSMStatus rv; /* Internal result code (used if an
internal error occurred) */
HTTPErrorCode httprv; /* HTTP result code (200, 401, 404, etc) */
char *errormsg; /* if a problem occurs, send this string back
to the client. */
char *filename; /* Canned file to fetch from data, if any */
/* These point to chars within (reqbuf). */
char *handlerName; /* Command requested by client */
char *params; /* Parameters passed to GET */
char *agent; /* User-Agent value */
char *ctrlrid; /* Authorization: RID of control connection */
char *password; /* Authorization: RID of nonce */
char *referer; /* The URL for the referer */
SSMControlConnection *ctrlconn;
/* Control connection owning this connection */
SSMResource *target; /* Target resource, if any */
char *language; /* Accept-Language value */
char *charset; /* Accept-Charset value */
PRBool sentResponse; /* Have we already sent a response to the user? */
PRBool keepSock; /* Are we keeping this socket (eg for logging)? */
PRBool processText; /* Should we interpret files we send out as text? */
SSMResourceID rid; /* ID of requested resource */
};
/* Typedef for a command handler. */
typedef SSMStatus (*SSMCommandHandlerFunc)(HTTPRequest *req);
/* Register a command handler. */
SSMStatus SSM_HTTPRegisterCommandHandler(const char *name,
SSMCommandHandlerFunc func);
/* function to parse the request and submit html */
SSMStatus SSM_HTTPGetGenericLump(HTTPRequest *req, PRBool binary);
/* The default handler, which uses baseRef as a prefix for two strings
to use in processing and returning HTTP headers and content. Can be
called by other handlers if no special header/content processing
for the user is necessary. */
SSMStatus SSM_HTTPDefaultCommandHandler(HTTPRequest *req);
/* ### sjlee: This function is called when you need to sleep one second
* before closing the window due to collision of dialog windows
* this is really the default command handler with a sleep
*/
SSMStatus SSM_HTTPCloseAndSleep(HTTPRequest* req);
/* Handler for getting binary data. This should be consolidated with
the default handler. */
SSMStatus SSM_HTTPGetBinaryHandler(HTTPRequest *req);
/* Handler for monitoring resources. */
SSMStatus SSM_HTTPMonitorResourceHandler(HTTPRequest *req);
/* Handler which shuts down a resource. */
SSMStatus SSM_HTTPShutdownResourceHandler(HTTPRequest *req);
/* Hello World example */
SSMStatus SSM_HTTPHelloWorld(HTTPRequest *req);
/* NLS Hello World example */
SSMStatus SSM_HTTPHelloWorldWithNLS(HTTPRequest *req);
/* SSM_HTTPThread listens to the HTTP socket for connections from
one or more clients. (arg) should be an open socket (PRFileDesc*),
therefore the port needs to have been created before being passed
to this thread. */
void SSM_HTTPThread(void *arg);
/* Open the HTTP listener. */
SSMStatus SSM_InitHTTP(void);
/* Get the port on which we're listening for HTTP connections. */
PRUint32 SSM_GetHTTPPort(void);
/* Construct a URL and size info based on a known page/access point
and control connection. */
SSMStatus SSM_GenerateURL(SSMControlConnection *conn,
char *command,
char *baseRef,
SSMResource *targetRes, /* can pass NULL for this */
char *otherParams,
PRUint32 *width, PRUint32 *height,
char **url);
/* Main listening thread for HTTP requests */
extern PRThread *httpListenThread;
extern PRUint32 httpListenPort;
/* Command handler utilities */
SSMStatus SSM_HTTPParamByName(HTTPRequest *req,
const char *key, const char **value);
SSMStatus SSM_RIDTextToResource(HTTPRequest *req, const char *ridText,
SSMResource **res);
SSMStatus SSM_HTTPReportError(HTTPRequest *req, HTTPErrorCode statusCode);
void SSM_HTTPReportSpecificError(HTTPRequest *req, char *fmt, ...);
SSMStatus SSM_HTTPParamValue(HTTPRequest *req, const char *key, char **value);
SSMStatus SSM_HTTPAddParamValue(HTTPRequest *req, const char * key,
const char * value);
SSMStatus
SSM_HTTPSendOKHeader(HTTPRequest *req,
char * addtlHeaders,
char * contentType);
SSMStatus
SSM_HTTPSendUTF8String(HTTPRequest *req, char * str);
SSMStatus
SSM_HTTPCloseWindow(HTTPRequest *req);
char * SSM_ConvertStringToHTMLString(char * string);
SSMStatus SSM_ProcessPasswordWindow(HTTPRequest * req);
#endif

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

@ -0,0 +1,406 @@
/*
* 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 "resource.h"
#include "kgenctxt.h"
#include "nlsutil.h"
#include "base64.h"
#include "pk11func.h"
#include "textgen.h"
#include "minihttp.h"
#include "connect.h"
#include "messages.h"
/* lock to wait for UI */
typedef struct {
PRMonitor * lock;
PRBool UIComplete;
} SSMTokenUI_Monitor;
#define SSM_PARENT_CONN(x) &((x)->m_parent->super)
#if 0 /* XXX not used? */
static SSMTokenUI_Monitor UIlock;
#endif
PK11SlotListElement * PK11_GetNextSafe(PK11SlotList *list,
PK11SlotListElement *le,
PRBool restart);
SSMStatus SSMTokenUI_GetNames(SSMResource * res, PRBool start, char ** name);
SSMStatus SSM_SetUserPasswordCommunicator(PK11SlotInfo * slot,
SSMKeyGenContext *ct);
CK_MECHANISM_TYPE
SSMKeyGenContext_GenMechToAlgMech(CK_MECHANISM_TYPE mechanism)
{
CK_MECHANISM_TYPE searchMech;
/* We are interested in slots based on the ability to perform
a given algorithm, not on their ability to generate keys usable
by that algorithm. Therefore, map keygen-specific mechanism tags
to tags for the corresponding crypto algorthm. */
switch(mechanism)
{
case CKM_RSA_PKCS_KEY_PAIR_GEN:
searchMech = CKM_RSA_PKCS;
break;
case CKM_DSA_KEY_PAIR_GEN:
searchMech = CKM_DSA;
break;
case CKM_RC4_KEY_GEN:
searchMech = CKM_RC4;
break;
case CKM_DH_PKCS_KEY_PAIR_GEN:
searchMech = CKM_DH_PKCS_DERIVE; /* ### mwelch is this right? */
break;
case CKM_DES_KEY_GEN:
/* What do we do about DES keygen? Right now, we're just using
DES_KEY_GEN to look for tokens, because otherwise we'll have
to search the token list three times. */
default:
searchMech = mechanism;
break;
}
return searchMech;
}
SSMStatus SSMKeyGenContext_GetSlot(SSMKeyGenContext * keyctxt,
CK_MECHANISM_TYPE mechanism)
{
SSMStatus rv = SSM_SUCCESS;
PK11SlotList * slotList = NULL;
CK_MECHANISM_TYPE searchMech;
PRBool reLock;
searchMech = SSMKeyGenContext_GenMechToAlgMech(mechanism);
if (!keyctxt->slot ||
!PK11_DoesMechanism(keyctxt->slot, searchMech)) {
slotList = PK11_GetAllTokens(searchMech, PR_TRUE, PR_TRUE,
keyctxt->super.m_connection);
if (!keyctxt)
goto loser;
if (!slotList || !slotList->head)
goto loser;
if (!slotList->head->next) {
/* only one slot available, just return it */
keyctxt->slot = slotList->head->slot;
keyctxt->m_slotName = strdup(PK11_GetSlotName(keyctxt->slot));
} else {
char * mech = PR_smprintf("mech=%d&task=keygen&unused=unused", searchMech);
if (keyctxt->m_ctxtype == SSM_OLD_STYLE_KEYGEN) {
CMTItem msg;
GenKeyOldStyleTokenRequest request;
char ** tokenNames = NULL;
int numtokens = 0;
PK11SlotListElement * slotElement;
slotElement = PK11_GetFirstSafe(slotList);
while(slotElement) {
numtokens++;
tokenNames = (char **) PR_REALLOC(tokenNames, numtokens*sizeof(*tokenNames));
tokenNames[numtokens - 1] = strdup(PK11_GetTokenName(slotElement->slot));
slotElement = PK11_GetNextSafe(slotList, slotElement, PR_FALSE);
}
/* send message to plugin: use native UI for select token dialog */
SSM_LockUIEvent(&keyctxt->super);
request.rid = keyctxt->super.m_id;
request.numtokens = numtokens;
request.tokenNames = tokenNames;
msg.type = SSM_REPLY_OK_MESSAGE | SSM_KEYGEN_TAG | SSM_KEYGEN_TOKEN;
if (CMT_EncodeMessage(GenKeyOldStyleTokenRequestTemplate, &msg,
&request) != CMTSuccess)
goto loser;
SSM_SendQMessage(keyctxt->super.m_connection->m_controlOutQ,
SSM_PRIORITY_NORMAL,
msg.type, msg.len, (char *)msg.data, PR_TRUE);
SSM_WaitUIEvent(&keyctxt->super, PR_INTERVAL_NO_TIMEOUT);
SSM_UnlockUIEvent(&keyctxt->super);
keyctxt->slot = (PK11SlotInfo*)keyctxt->super.m_uiData;
} else /* post UI event */ {
/* post a UI event to ask user for the slot */
SSM_LockUIEvent(&keyctxt->super);
/* Release the lock on the resource temporarily while
* the UI happens.
*/
rv = SSM_UnlockResource(&keyctxt->super);
reLock = (rv == PR_SUCCESS) ? PR_TRUE : PR_FALSE;
rv = SSMControlConnection_SendUIEvent(keyctxt->super.m_connection,
"get",
"select_token",
(SSMResource *)keyctxt,
mech,
&((SSMResource*)keyctxt)->m_clientContext);
if (rv != SSM_SUCCESS) {
if (keyctxt->super.m_UILock != NULL) {
PR_ExitMonitor(keyctxt->super.m_UILock);
}
goto loser;
}
/* wait until the UI dialog box is done */
SSM_WaitUIEvent(&keyctxt->super, PR_INTERVAL_NO_TIMEOUT);
if (reLock) {
/* Get the lock back. */
SSM_LockResource(&keyctxt->super);
}
SSM_UnlockUIEvent(&keyctxt->super);
PR_Free(mech);
/* ok, the return from UI is processed in command handler */
/* Make sure password prompt doesn't get sucked away by
* the disappearing dialog
*/
PR_Sleep(PR_TicksPerSecond());
keyctxt->slot = (PK11SlotInfo*)keyctxt->super.m_uiData;
if (keyctxt->slot != NULL) {
keyctxt->m_slotName = strdup(PK11_GetSlotName(keyctxt->slot));
}
} /* end of post UI event */
} /* end of multiple tokens available */
/* Get a slot reference so it doesn't disappear */
if (keyctxt->slot) {
PK11_ReferenceSlot(keyctxt->slot);
}
}
/* we should have a slot now */
if (keyctxt->slot == NULL)
goto loser;
/* Before we authenticate, make sure the user initialized the DB. */
if (PK11_NeedUserInit(keyctxt->slot))
rv = SSM_SetUserPasswordCommunicator(keyctxt->slot, keyctxt);
rv = PK11_Authenticate(keyctxt->slot, PR_FALSE, keyctxt);
if (rv != SECSuccess) {
goto loser;
}
goto done;
loser:
if (rv == SSM_SUCCESS)
rv = SSM_FAILURE;
keyctxt->slot = NULL;
done:
if (slotList)
PK11_FreeSlotList(slotList);
return rv;
}
/* send a message to communicator to display UI for setting slot password */
SSMStatus
SSM_SetUserPasswordCommunicator(PK11SlotInfo * slot,
SSMKeyGenContext *ct)
{
CMTItem msg;
GenKeyOldStylePasswordRequest passwdmsg;
SSMStatus rv = SSM_FAILURE;
PRBool reLock = PR_FALSE;
PR_ASSERT(SSM_IsAKindOf(&ct->super, SSM_RESTYPE_KEYGEN_CONTEXT));
switch (ct->m_ctxtype) {
case (SSM_CRMF_KEYGEN):
rv = SSM_SetUserPassword(slot, &ct->super);
break;
case (SSM_OLD_STYLE_KEYGEN):
SSM_LockUIEvent(&ct->super);
passwdmsg.rid = ct->super.m_id;
passwdmsg.tokenName = PK11_GetTokenName(slot);
passwdmsg.internal = (CMBool) PK11_IsInternal(slot);
passwdmsg.minpwdlen = PR_MAX(SSM_MIN_PWD_LEN,PK11_GetMinimumPwdLength(slot));
passwdmsg.maxpwdlen = slot->maxPassword;
msg.type = SSM_REPLY_OK_MESSAGE | SSM_KEYGEN_TAG | SSM_KEYGEN_PASSWORD;
if (CMT_EncodeMessage(GenKeyOldStylePasswordRequestTemplate, &msg,
&passwdmsg) != CMTSuccess)
goto loser;
rv = SSM_SendQMessage(ct->super.m_connection->m_controlOutQ,
SSM_PRIORITY_NORMAL,
msg.type, msg.len, (char *)msg.data, PR_TRUE);
if (rv != SSM_SUCCESS)
SSM_UnlockUIEvent(&ct->super);
else
SSM_WaitUIEvent(&ct->super, PR_INTERVAL_NO_TIMEOUT);
break;
default:
SSM_DEBUG("Unknown keygen type!\n");
goto loser;
}
loser:
if (rv != SSM_SUCCESS)
SSM_DEBUG("SetUserPasswordComm: can't send password request msg!\n");
return rv;
}
SSMStatus
ssmpkcs11_convert_slot(SSMTextGenContext *cx,
PRInt32 slotIndex,
PK11SlotInfo *slot,
char *fmt,
PRBool accumulate);
SSMStatus SSMTokenUI_KeywordHandler(SSMTextGenContext * cx)
{
SSMResource *ctxt = NULL;
SSMStatus rv;
char * tempUStr = NULL;
char * wrapper = NULL;
CK_MECHANISM_TYPE searchMech;
char *searchMechStr;
static PK11SlotList * slotList;
static PK11SlotListElement * slotElement;
PRIntn i = 0;
if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
goto loser;
ctxt = SSMTextGen_GetTargetObject(cx);
/* Get the wrapper string from the properties file. */
wrapper = (char *) SSM_At(cx->m_params, 0);
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapper, &tempUStr);
if (rv != PR_SUCCESS)
goto loser;
rv = SSM_HTTPParamValue(cx->m_request, "action", &searchMechStr);
if (rv != SSM_SUCCESS)
goto loser;
searchMech = atoi(searchMechStr);
slotList = PK11_GetAllTokens(searchMech, PR_TRUE, PR_TRUE,
ctxt->m_connection);
if (!slotList)
goto loser;
slotElement = PK11_GetFirstSafe(slotList);
while(slotElement)
{
rv = ssmpkcs11_convert_slot(cx, i++, slotElement->slot, tempUStr,
PR_TRUE);
if (rv != SSM_SUCCESS)
goto loser;
slotElement = PK11_GetNextSafe(slotList, slotElement, PR_FALSE);
}
rv = SSM_SUCCESS;
goto done;
loser:
SSM_DEBUG("Errors creating token list!\n");
SSMTextGen_UTF8StringClear(&cx->m_result);
if (rv==SSM_SUCCESS)
rv = SSM_FAILURE;
done:
PR_FREEIF(tempUStr);
return rv;
}
PK11SlotInfo *
SSMPKCS11_FindSlotByID(SECMODModuleID modID,
CK_SLOT_ID slotID);
SSMStatus
figure_out_token_selection(char *str,
SECMODModuleID *modID,
CK_SLOT_ID *slotID)
{
char *walk;
walk = PL_strchr(str, '+');
if (!walk)
return SSM_FAILURE;
*walk++ = '\0';
*modID = atoi(str);
*slotID = atoi(walk);
return SSM_SUCCESS;
}
SSMStatus
SSMTokenUI_CommandHandler(HTTPRequest * req)
{
SSMStatus rv;
char * tokenName = NULL;
SSMResource *res;
SECMODModuleID modID;
CK_SLOT_ID slotID;
PK11SlotInfo *slot;
if (!req->target)
goto loser;
res = req->target;
res->m_uiData = NULL;
/* check the parameter values */
if (res->m_buttonType == SSM_BUTTON_CANCEL)
{
slot = NULL;
goto done; /* return the closing javascript */
}
/* Determine what token the user selected. */
rv = SSM_HTTPParamValue(req, "token", &tokenName);
if (rv != SSM_SUCCESS)
{
req->httprv = HTTP_BAD_REQUEST;
goto loser;
}
rv = figure_out_token_selection(tokenName, &modID, &slotID);
if (rv != SSM_SUCCESS)
goto loser;
slot = SSMPKCS11_FindSlotByID(modID, slotID);
if (!slot)
goto loser;
done:
/* Tell the keygen context what token was selected. */
res->m_uiData = slot;
SSM_NotifyUIEvent(res);
/* Done with our part, so pass back whatever the dialog wants in
order to close the window. */
return SSM_HTTPCloseAndSleep(req);
loser:
res->m_uiData = NULL;
SSM_NotifyUIEvent(res);
SSM_DEBUG("Can't get input from token_select dialog!\n");
return SSM_FAILURE;
}

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

@ -0,0 +1,55 @@
/*
* 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.
*/
#ifndef _NLSLAYER_H_
#define _NLSLAYER_H_
PRBool nlsInit();
char* nlsGetUTF8String(const char *name);
void * nlsNewDateFormat();
void nlsFreeDateFormat(void * p);
char * nslPRTimeToUTF8String(void* p, PRInt64 t);
PRBool nlsUnicodeToUTF8(unsigned char * inBuf, unsigned int inBufBytes,
unsigned char * outBuf, unsigned int maxOutBufLen,
unsigned int * outBufLen);
PRBool nlsUTF8ToUnicode(unsigned char * inBuf, unsigned int inBufBytes,
unsigned char * outBuf, unsigned int maxOutBufLen,
unsigned int * outBufLen);
PRBool nlsUnicodeToASCII(unsigned char * inBuf, unsigned int inBufBytes,
unsigned char * outBuf, unsigned int maxOutBufLen,
unsigned int * outBufLen);
PRBool nlsASCIIToUnicode(unsigned char * inBuf, unsigned int inBufBytes,
unsigned char * outBuf, unsigned int maxOutBufLen,
unsigned int * outBufLen);
#endif /* _NLSLAYER_H_ */

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

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

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

@ -0,0 +1,954 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 "p12res.h"
#include "minihttp.h"
#include "pk11func.h"
#include "secmod.h"
#include "p12.h"
#include "p12plcy.h"
#include "secerr.h"
#include "newproto.h"
#include "messages.h"
#include "advisor.h"
#include "nlslayer.h"
#define SSMRESOURCE(object) (&object->super)
#define PKCS12_IN_BUFFER_SIZE 2048
static SSMStatus
ssmpkcs12context_createpkcs12file(SSMPKCS12Context *cx,
PRBool forceAuthenticate,
CERTCertificate **certArr,
PRIntn numCerts);
SECStatus
SSM_UnicodeConversion(SECItem *dest, SECItem *src,
PRBool toUnicode, PRBool swapBytes)
{
unsigned int allocLen;
if(!dest || !src) {
return SECFailure;
}
allocLen = ((toUnicode) ? (src->len << 2) : src->len);
if (allocLen == 0) {
/* empty string: we need to pad it by 2 bytes */
allocLen = 2;
}
dest->data = SSM_ZNEW_ARRAY(unsigned char, allocLen);
if(!SSM_UCS2_ASCIIConversion(toUnicode, src->data, src->len,
dest->data, allocLen, &dest->len,
swapBytes)) {
PR_Free(dest->data);
dest->data = NULL;
return SECFailure;
}
return SECSuccess;
}
SSMStatus
SSMPKCS12Context_Create(void *arg, SSMControlConnection *ctrl,
SSMResource **res)
{
SSMPKCS12Context *cxt = NULL;
SSMPKCS12CreateArg *createArg = (SSMPKCS12CreateArg*)arg;
SSMStatus rv;
cxt = SSM_ZNEW(SSMPKCS12Context);
if (cxt == NULL) {
return SSM_ERR_OUT_OF_MEMORY;
}
rv = SSMPKCS12Context_Init(ctrl,cxt,SSM_RESTYPE_PKCS12_CONTEXT ,
createArg->isExportContext);
if (rv != PR_SUCCESS) {
goto loser;
}
*res = SSMRESOURCE(cxt);
return PR_SUCCESS;
loser:
if (cxt != NULL) {
SSM_FreeResource(SSMRESOURCE(cxt));
}
*res = NULL;
return rv;
}
SSMStatus
SSMPKCS12Context_Init(SSMControlConnection *ctrl, SSMPKCS12Context *res,
SSMResourceType type, PRBool isExportContext)
{
res->m_isExportContext = isExportContext;
res->m_password = NULL;
res->m_inputProcessed = PR_FALSE;
res->m_file = NULL;
res->m_digestFile = NULL;
res->m_error = PR_FALSE;
return SSMResource_Init(ctrl, SSMRESOURCE(res), type);
}
SSMStatus
SSMPKCS12Context_Destroy(SSMResource *res, PRBool doFree)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context*)res;
SSMResource_Destroy(res, PR_FALSE);
if (cxt->m_password != NULL) {
PR_Free(cxt->m_password);
cxt->m_password = NULL;
}
if (cxt->m_cert != NULL) {
CERT_DestroyCertificate(cxt->m_cert);
cxt->m_cert = NULL;
}
if (doFree) {
PR_Free(res);
}
return PR_SUCCESS;
}
static SSMStatus
SSMPKCS12Context_HandlePasswordRequest(SSMResource *res,
HTTPRequest *req)
{
char *password, *confirmPassword;
SSMPKCS12Context *p12Cxt = (SSMPKCS12Context*)res;
SSMStatus rv = SSM_FAILURE;
/* Let's get the password out of the dialog. */
if (res->m_buttonType != SSM_BUTTON_OK) {
goto loser;
}
rv = SSM_HTTPParamValue(req, "passwd", &password);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_HTTPParamValue(req, "confirmPasswd", &confirmPassword);
if (rv != SSM_SUCCESS) {
goto loser;
}
if (strcmp(password, confirmPassword) != 0) {
/* Should re-prompt, but for now we fail. */
rv = SSM_FAILURE;
goto loser;
}
p12Cxt->m_password = PL_strdup(password);
goto done;
loser:
p12Cxt->m_password = NULL;
done:
SSM_LockResource(res);
SSM_NotifyResource(res);
SSM_UnlockResource(res);
SSM_HTTPDefaultCommandHandler(req);
p12Cxt->m_inputProcessed = PR_TRUE;
return rv;
}
SSMStatus
SSMPKCS12Context_FormSubmitHandler(SSMResource *res, HTTPRequest *req)
{
char *formName;
SSMStatus rv=SSM_FAILURE;
rv = SSM_HTTPParamValue(req, "formName", &formName);
if (rv != SSM_SUCCESS) {
goto loser;
}
if (!strcmp(formName, "cert_backup_form")) {
rv = SSMPKCS12Context_HandlePasswordRequest(res, req);
} else if (!strcmp(formName, "set_db_password")) {
rv = SSM_SetDBPasswordHandler(req);
} else {
goto loser;
}
return rv;
loser:
SSM_HTTPDefaultCommandHandler(req);
return SSM_FAILURE;
}
static void
ssmpkcs12context_writetoexportfile(void *arg, const char *buf,
unsigned long len)
{
SSMPKCS12Context *p12Cxt = (SSMPKCS12Context*)arg;
PRInt32 bytesWritten;
if (p12Cxt == NULL) {
return;
}
if (p12Cxt->m_file == NULL) {
p12Cxt->m_error = PR_TRUE;
return;
}
bytesWritten = PR_Write(p12Cxt->m_file, buf, len);
if (bytesWritten != len) {
p12Cxt->m_error = PR_TRUE;
}
}
SSMStatus
SSMPKCS12Context_CreatePKCS12FileForMultipleCerts(SSMPKCS12Context *p12Cxt,
PRBool forceAuthenticate,
CERTCertificate **certArr,
PRIntn numCerts)
{
return ssmpkcs12context_createpkcs12file(p12Cxt, forceAuthenticate,
certArr, numCerts);
}
SSMStatus
SSMPKCS12Context_CreatePKCS12File(SSMPKCS12Context *cxt,
PRBool forceAuthenticate)
{
return ssmpkcs12context_createpkcs12file(cxt, forceAuthenticate,
&cxt->m_cert, 1);
}
static SSMStatus
ssmpkcs12context_createpkcs12file(SSMPKCS12Context *cxt,
PRBool forceAuthenticate,
CERTCertificate **certArr,
PRIntn numCerts)
{
SEC_PKCS12ExportContext *p12ecx = NULL;
SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
SECItem pwitem = { siBuffer, NULL, 0 };
PK11SlotInfo *slot = NULL;
PK11SlotInfo *slotToUse = NULL;
SSMControlConnection *ctrl;
SSMStatus rv=SSM_FAILURE;
int i;
if (cxt == NULL || certArr == NULL || numCerts == 0) {
return SSM_ERR_BAD_REQUEST;
}
/*
* We're about to send the UI event requesting the password to use
* when encrypting
*/
SSM_LockResource(&cxt->super);
cxt->m_inputProcessed = PR_FALSE;
rv = SSMControlConnection_SendUIEvent(SSMRESOURCE(cxt)->m_connection,
"get", "cert_backup",
SSMRESOURCE(cxt),
(numCerts > 1) ? "multipleCerts=1" :
NULL,
&SSMRESOURCE(cxt)->m_clientContext);
if (rv != SSM_SUCCESS) {
SSM_UnlockResource(SSMRESOURCE(cxt));
goto loser;
}
/*
* Wait until the form is submitted to proceed. We'll get notified.
*/
SSM_WaitResource(SSMRESOURCE(cxt), PR_INTERVAL_NO_TIMEOUT);
SSM_UnlockResource(SSMRESOURCE(cxt));
if (cxt->m_password == NULL ||
cxt->super.m_buttonType == SSM_BUTTON_CANCEL) {
rv = SSM_ERR_NO_PASSWORD;
goto loser;
}
/* Wait for the dialog box to go down so that when it disappears,
* the window doesn't take away the password prompt.
*/
PR_Sleep(PR_TicksPerSecond());
ctrl = SSMRESOURCE(cxt)->m_connection;
pwitem.data = (unsigned char *) cxt->m_password;
pwitem.len = strlen(cxt->m_password);
PK11_FindObjectForCert(certArr[0], ctrl, &slot);
if (slot == NULL) {
rv = SSM_FAILURE;
goto loser;
}
slotToUse = slot;
if (forceAuthenticate && PK11_NeedLogin(slot)) {
PK11_Logout(slot);
}
if (PK11_Authenticate(slot, PR_TRUE, ctrl) != SECSuccess) {
rv = SSM_ERR_BAD_DB_PASSWORD;
goto loser;
}
p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, ctrl);
if (p12ecx == NULL) {
rv = SSM_FAILURE;
goto loser;
}
if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
!= SECSuccess) {
rv = SSM_ERR_BAD_PASSWORD;
goto loser;
}
for (i=0; i <numCerts; i++) {
PK11_FindObjectForCert(certArr[i], ctrl, &slot);
if (slot != slotToUse) {
continue;
}
keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
if (!SEC_PKCS12IsEncryptionAllowed() || PK11_IsFIPS()) {
certSafe = keySafe;
} else {
certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, &pwitem,
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
}
if (certSafe == NULL || keySafe == NULL) {
rv = SSM_FAILURE;
goto loser;
}
if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, certArr[i],
SSMRESOURCE(cxt)->m_connection->m_certdb,
keySafe, NULL, PR_TRUE, &pwitem,
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
!= SECSuccess) {
rv = SSM_FAILURE;
goto loser;
}
}
/* Done with the password, free it */
PR_Free(cxt->m_password);
cxt->m_password = NULL;
rv = SSM_RequestFilePathFromUser(SSMRESOURCE(cxt),
"pkcs12_export_file_prompt",
"*.p12",
PR_FALSE);
if (rv != SSM_SUCCESS || cxt->super.m_fileName == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
cxt->m_file = PR_Open (cxt->super.m_fileName,
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
0600);
if (cxt->m_file == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
if (SEC_PKCS12Encode(p12ecx, ssmpkcs12context_writetoexportfile, cxt)
!= SECSuccess) {
rv = SSM_FAILURE;
goto loser;
}
PR_Close(cxt->m_file);
if (slotToUse) {
PK11_FreeSlot(slotToUse);
}
SEC_PKCS12DestroyExportContext(p12ecx);
return SSM_SUCCESS;
loser:
if (p12ecx != NULL) {
SEC_PKCS12DestroyExportContext(p12ecx);
}
if (slot && cxt->m_cert && (slot != cxt->m_cert->slot)) {
PK11_FreeSlot(slot);
}
PR_FREEIF(cxt->m_password);
cxt->m_password = NULL;
return rv;
}
/* This function converts ASCII strings to UCS2 strings in Network Byte Order.
** The "swapBytes" argument is ignored.
** The PKCS#12 code only makes it true on Little Endian systems,
** where it was intended to force the output into NBO.
*/
PRBool
SSM_UCS2_ASCIIConversion(PRBool toUnicode,
unsigned char *inBuf,
unsigned int inBufLen,
unsigned char *outBuf,
unsigned int maxOutBufLen,
unsigned int *outBufLen,
PRBool swapBytes)
{
if (!inBuf || !outBuf || !outBufLen) {
return PR_FALSE;
}
if (toUnicode) {
PRBool rv;
#ifdef DEBUG
unsigned int outLen;
int i;
fprintf(stderr,"\n---ssm_ConvertAsciiToUCS2---\nInput: inBuf= ");
for (i = 0; i < inBufLen; i++) {
fprintf(stderr, "%c", inBuf[i]);
}
fprintf(stderr,"\ninBufLen=%d\n", inBufLen);
#endif
rv = nlsASCIIToUnicode(inBuf, inBufLen,
outBuf, maxOutBufLen, outBufLen);
#ifdef DEBUG
outLen = *outBufLen;
fprintf(stderr,"output: outBuf= ");
for(i = 0; i < outLen; i++) {
fprintf(stderr, "%c ", outBuf[i]);
}
fprintf(stderr,"\noutBuf= ");
for(i = 0; i < outLen; i++) {
fprintf(stderr,"%2x ", outBuf[i]);
}
fprintf(stderr,"\noutLen = %d\n", outLen);
#endif /* DEBUG */
return rv;
}
PR_ASSERT(PR_FALSE); /* not supported yet */
return PR_FALSE;
}
PRBool
SSM_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
unsigned int inBufLen,unsigned char *outBuf,
unsigned int maxOutBufLen, unsigned int *outBufLen)
{
PRBool retval;
#ifdef DEBUG
unsigned int i;
#endif
if(!inBuf || !outBuf || !outBufLen) {
return PR_FALSE;
}
*outBufLen = 0;
#ifdef DEBUG
fprintf(stderr,"---UCS2_UTF8Conversion (%s) ---\nInput: \n",
(toUnicode?"to UCS2":"to UTF8"));
for(i=0; i< inBufLen; i++) {
fprintf(stderr,"%c", (char) inBuf[i]);
}
fprintf(stderr,"\n");
for(i=0; i< inBufLen; i++) {
fprintf(stderr,"%2x ", (char) inBuf[i]);
}
fprintf(stderr,"\n");
#endif
if(toUnicode) {
retval = nlsUTF8ToUnicode(inBuf, inBufLen, outBuf, maxOutBufLen,
outBufLen);
} else {
retval = nlsUnicodeToUTF8(inBuf, inBufLen, outBuf, maxOutBufLen,
outBufLen);
}
#ifdef DEBUG
fprintf(stderr,"Output: \n");
for(i=0; i< *outBufLen; i++) {
fprintf(stderr,"%c", (char) outBuf[i]);
}
fprintf(stderr,"\n");
for(i=0; i< *outBufLen; i++) {
fprintf(stderr,"%2x ", (char) outBuf[i]);
}
fprintf(stderr,"\n\n");
#endif
return retval;
}
static SECStatus
ssmpkcs12context_digestopen(void *arg, PRBool readData)
{
char *tmpFileName=NULL;
char filePathSep;
SSMPKCS12Context *cxt = (SSMPKCS12Context *)arg;
#if defined(XP_UNIX)
filePathSep = '/';
#elif defined(WIN32)
filePathSep = '\\';
#elif defined(XP_MAC)
filePathSep = ':';
#else
#error Tell me what the file path separator is of this platform.
#endif
tmpFileName = PR_smprintf("%s%c%s",
SSMRESOURCE(cxt)->m_connection->m_dirRoot,
filePathSep,
".nsm_p12_tmp");
if (tmpFileName == NULL) {
return SECFailure;
}
if (readData) {
cxt->m_digestFile = PR_Open(tmpFileName,
PR_RDONLY, 0400);
} else {
cxt->m_digestFile = PR_Open(tmpFileName,
PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE,
0600);
}
cxt->m_tempFilePath = tmpFileName;
if (cxt->m_digestFile == NULL) {
cxt->m_error = PR_TRUE;
return SECFailure;
}
return SECSuccess;
}
static SECStatus
ssmpkcs12context_digestclose(void *arg, PRBool removeFile)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context*)arg;
if (cxt == NULL || cxt->m_digestFile == NULL) {
return SECFailure;
}
PR_Close(cxt->m_digestFile);
cxt->m_digestFile = NULL;
if (removeFile) {
PR_Delete(cxt->m_tempFilePath);
PR_Free(cxt->m_tempFilePath);
cxt->m_tempFilePath = NULL;
}
return SECSuccess;
}
static int
ssmpkcs12context_digestread(void *arg, unsigned char *buf, unsigned long len)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context*)arg;
if (cxt == NULL || cxt->m_digestFile == NULL) {
return -1;
}
if (buf == NULL || len == 0) {
return -1;
}
return PR_Read(cxt->m_digestFile, buf, len);
}
static int
ssmpkcs12context_digestwrite(void *arg, unsigned char *buf, unsigned long len)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context *)arg;
if (cxt == NULL || cxt->m_digestFile == NULL) {
return -1;
}
if (buf == NULL || len == 0) {
return -1;
}
return PR_Write(cxt->m_digestFile, buf, len);
}
SECItem*
SSM_NicknameCollisionCallback(SECItem *old_nick, PRBool *cancel,
void *wincx)
{
/* We don't handle this yet */
*cancel = PR_TRUE;
return NULL;
}
static PK11SlotInfo*
SSMPKCS12Context_ChooseSlotForImport(SSMPKCS12Context *cxt,
PK11SlotList *slotList)
{
char mech[20];
SSMStatus rv;
PR_snprintf(mech, 20, "mech=%d&task=import&unused=unused", CKM_RSA_PKCS);
SSM_LockUIEvent(&cxt->super);
rv = SSMControlConnection_SendUIEvent(cxt->super.m_connection,
"get",
"select_token",
&cxt->super,
mech, &SSMRESOURCE(cxt)->m_clientContext);
if (rv != SSM_SUCCESS) {
SSM_UnlockResource(&cxt->super);
return NULL;
}
SSM_WaitUIEvent(&cxt->super, PR_INTERVAL_NO_TIMEOUT);
/* Wait so damn window goes away without swallowing up
* the password prompt that will come up next.
*/
PR_Sleep(PR_TicksPerSecond());
return (PK11SlotInfo*)cxt->super.m_uiData;
}
static PK11SlotInfo*
SSMPKCS12Context_GetSlotForImport(SSMPKCS12Context *cxt)
{
PK11SlotList *slotList;
PK11SlotInfo *slot = NULL;
slotList = PK11_GetAllTokens(CKM_RSA_PKCS, PR_TRUE, PR_TRUE,
cxt->super.m_connection);
if (slotList == NULL || slotList->head == NULL) {
/* Couldn't find a slot, let's try the internal slot
* and see what happens
*/
slot = PK11_GetInternalKeySlot();
} else if (slotList->head->next == NULL) {
/*
* Only one slot, return it.
*/
slot = PK11_ReferenceSlot(slotList->head->slot);
} else {
slot = SSMPKCS12Context_ChooseSlotForImport(cxt, slotList);
}
if (slotList)
PK11_FreeSlotList(slotList);
return slot;
}
SSMStatus
SSMPKCS12Context_RestoreCertFromPKCS12File(SSMPKCS12Context *cxt)
{
SSMStatus rv;
SECItem passwdReq;
char *prompt=NULL;
PK11SlotInfo *slot=NULL;
SEC_PKCS12DecoderContext *p12dcx=NULL;
PRBool swapUnicode = PR_FALSE;
unsigned char *buf=NULL;
SECItem pwItem = { siBuffer, NULL, 0 }, uniPwItem = { siBuffer, NULL, 0 };
SECStatus srv;
CERTCertList *certList=NULL;
CERTCertListNode *node=NULL;
PromptRequest request;
if (cxt == NULL || cxt->m_isExportContext) {
return SSM_FAILURE;
}
#ifdef IS_LITTLE_ENDIAN
swapUnicode = PR_TRUE;
#endif
rv = SSM_RequestFilePathFromUser(SSMRESOURCE(cxt),
"pkcs12_import_file_prompt",
"*.p12",
PR_TRUE);
if (rv != SSM_SUCCESS || cxt->super.m_fileName == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
prompt = SSM_GetCharFromKey("pkcs12_request_password_prompt",
"ISO-8859-1");
if (prompt == NULL) {
rv = SSM_FAILURE;
goto loser;
}
request.resID = SSMRESOURCE(cxt)->m_id;
request.prompt = prompt;
request.clientContext = SSMRESOURCE(cxt)->m_clientContext;
if (CMT_EncodeMessage(PromptRequestTemplate, (CMTItem*)&passwdReq, &request) != CMTSuccess) {
rv = SSM_FAILURE;
goto loser;
}
passwdReq.type = (SECItemType) (SSM_EVENT_MESSAGE | SSM_PROMPT_EVENT);
SSM_LockResource(SSMRESOURCE(cxt));
cxt->m_password = NULL;
rv = SSM_SendQMessage(SSMRESOURCE(cxt)->m_connection->m_controlOutQ,
20,
passwdReq.type,
passwdReq.len,
(char*)passwdReq.data,
PR_TRUE);
SSM_WaitResource(SSMRESOURCE(cxt), SSM_PASSWORD_WAIT_TIME);
SSM_UnlockResource(SSMRESOURCE(cxt));
if (cxt->m_password == NULL) {
rv = SSM_ERR_NO_PASSWORD;
goto loser;
}
cxt->m_file = PR_Open(SSMRESOURCE(cxt)->m_fileName,
PR_RDONLY, 0400);
if (cxt->m_file == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
slot = SSMPKCS12Context_GetSlotForImport(cxt);
if (slot == NULL) {
goto loser;
}
if (PK11_NeedLogin(slot)) {
/* we should log out only if the slot needs login */
PK11_Logout(slot);
}
/* User has not initialize DB, ask for a password. */
if (PK11_NeedUserInit(slot)) {
rv = SSM_SetUserPassword(slot, SSMRESOURCE(cxt));
if (rv != SSM_SUCCESS) {
rv = SSM_ERR_NEED_USER_INIT_DB;
goto loser;
}
}
if (PK11_Authenticate(slot, PR_FALSE, SSMRESOURCE(cxt)->m_connection)
!= SECSuccess) {
rv = SSM_ERR_BAD_DB_PASSWORD;
goto loser;
}
pwItem.data = (unsigned char *) cxt->m_password;
pwItem.len = strlen(cxt->m_password);
if (SSM_UnicodeConversion(&uniPwItem, &pwItem, PR_TRUE,
swapUnicode) != SECSuccess) {
rv = SSM_ERR_BAD_PASSWORD;
goto loser;
}
p12dcx = SEC_PKCS12DecoderStart(&uniPwItem, slot,
SSMRESOURCE(cxt)->m_connection,
ssmpkcs12context_digestopen,
ssmpkcs12context_digestclose,
ssmpkcs12context_digestread,
ssmpkcs12context_digestwrite,
cxt);
if (p12dcx == NULL) {
rv = SSM_FAILURE;
goto loser;
}
buf = SSM_NEW_ARRAY(unsigned char, PKCS12_IN_BUFFER_SIZE);
if (buf == NULL) {
rv = SSM_ERR_OUT_OF_MEMORY;
goto loser;
}
cxt->m_file = PR_Open(SSMRESOURCE(cxt)->m_fileName, PR_RDONLY, 0400);
if (cxt->m_file == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
while (PR_TRUE) {
int readLen = PR_Read(cxt->m_file, buf, PKCS12_IN_BUFFER_SIZE);
if (readLen < 0) {
rv = SSM_FAILURE;
goto loser;
}
srv = SEC_PKCS12DecoderUpdate(p12dcx, buf, readLen);
if (srv != SECSuccess || readLen != PKCS12_IN_BUFFER_SIZE) {
break;
}
}
if (srv != SECSuccess) {
rv = SSM_ERR_CANNOT_DECODE;
goto loser;
}
if (SEC_PKCS12DecoderVerify(p12dcx) != SECSuccess) {
rv = SSM_FAILURE;
goto loser;
}
if (SEC_PKCS12DecoderValidateBags(p12dcx, SSM_NicknameCollisionCallback)
!= SECSuccess) {
if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
rv = SSM_PKCS12_CERT_ALREADY_EXISTS;
} else {
rv = SSM_FAILURE;
}
goto loser;
}
if (SEC_PKCS12DecoderImportBags(p12dcx) != SECSuccess) {
rv = SSM_FAILURE;
goto loser;
}
PR_Close(cxt->m_file);
cxt->m_file = NULL;
PR_Free(prompt);
PK11_FreeSlot(slot);
certList = SEC_PKCS12DecoderGetCerts(p12dcx);
if (certList != NULL) {
for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
node = CERT_LIST_NEXT(node)) {
if ((node->cert->trust) &&
(node->cert->trust->emailFlags & CERTDB_USER) &&
CERT_VerifyCertNow(cxt->super.m_connection->m_certdb,
node->cert, PR_TRUE, certUsageEmailSigner,
cxt) == SSM_SUCCESS) {
rv = SSM_UseAsDefaultEmailIfNoneSet(cxt->super.m_connection,
node->cert, PR_FALSE);
if (rv == SSM_SUCCESS) {
/* We just made this cert the default new cert */
rv = SSM_ERR_NEW_DEF_MAIL_CERT;
break;
}
}
}
CERT_DestroyCertList(certList);
certList = NULL;
}
SEC_PKCS12DecoderFinish(p12dcx);
return (rv == SSM_ERR_NEW_DEF_MAIL_CERT) ? rv : SSM_SUCCESS;
loser:
if (cxt->m_file != NULL) {
PR_Close(cxt->m_file);
cxt->m_file = NULL;
}
if (prompt != NULL) {
PR_Free(prompt);
}
if (slot != NULL) {
PK11_FreeSlot(slot);
}
if (p12dcx != NULL) {
SEC_PKCS12DecoderFinish(p12dcx);
}
if (buf != NULL) {
PR_Free(buf);
}
cxt->m_error = PR_TRUE;
return rv;
}
SSMStatus
SSMPKCS12Context_ProcessPromptReply(SSMResource *res,
char *reply)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context*)res;
if (!SSM_IsAKindOf(res, SSM_RESTYPE_PKCS12_CONTEXT)) {
return PR_FAILURE;
}
cxt->m_password = reply?PL_strdup(reply):NULL;
SSM_LockResource(res);
SSM_NotifyResource(res);
SSM_UnlockResource(res);
return PR_SUCCESS;
}
SSMStatus
SSMPKCS12Context_Print(SSMResource *res,
char *fmt,
PRIntn numParams,
char **value,
char **resultStr)
{
char mechStr[48];
SSMStatus rv = SSM_FAILURE;
PR_ASSERT(resultStr != NULL);
if (resultStr == NULL) {
rv = SSM_FAILURE;
goto done;
}
if (numParams) {
rv = SSMResource_Print(res, fmt, numParams, value, resultStr);
goto done;
}
PR_snprintf(mechStr, 48, "%d", CKM_RSA_PKCS);
*resultStr = PR_smprintf(fmt, res->m_id, mechStr, "");
rv = (*resultStr == NULL) ? SSM_FAILURE : SSM_SUCCESS;
done:
return rv;
}
void SSMPKCS12Context_BackupMultipleCertsThread(void *arg)
{
SSMPKCS12Context *p12Cxt = (SSMPKCS12Context*)arg;
SSMStatus rv;
SSMControlConnection *connection = p12Cxt->super.m_connection;
PRIntn i;
SSM_RegisterThread("PKCS12", NULL);
SSM_DEBUG("About to backup some certs.\n");
rv = SSMControlConnection_SendUIEvent(connection,
"get", "backup_new_cert",
&p12Cxt->super, NULL,
&p12Cxt->super.m_clientContext);
PR_ASSERT(SSMRESOURCE(p12Cxt)->m_buttonType == SSM_BUTTON_NONE);
if (rv == SSM_SUCCESS) {
while (SSMRESOURCE(p12Cxt)->m_buttonType == SSM_BUTTON_NONE) {
SSM_WaitForOKCancelEvent(SSMRESOURCE(p12Cxt),
PR_INTERVAL_NO_TIMEOUT);
}
}
/*
* Eventhough we tell Nova to use a context it provided to us,
* it still tries to use the top-most window to bring up the
* next dialog. Meaning I still have to insert this freakin'
* sleep.
*
* XXX -javi
*/
PR_Sleep(PR_TicksPerSecond());
#if 0
/*
* Disable this for now, until we figure out how we're really gonna
* support putting multiple cert/key pairs in one P12 file.
*/
SSMPKCS12Context_CreatePKCS12FileForMultipleCerts(p12Cxt, PR_FALSE,
p12Cxt->arg->certs,
p12Cxt->arg->numCerts);
#endif
for (i=0; i<p12Cxt->arg->numCerts;i++) {
p12Cxt->m_cert = p12Cxt->arg->certs[i];
SSMPKCS12Context_CreatePKCS12File(p12Cxt, PR_FALSE);
/*
* ARGH!! If we do more than one, then Communicator crashes
* because it tries to use a window that no longer exists as
* the base for the next window.
*/
PR_Sleep(PR_TicksPerSecond());
}
PR_Free(p12Cxt->arg->certs);
PR_Free(p12Cxt->arg);
p12Cxt->arg = NULL;
p12Cxt->m_thread = NULL;
SSM_FreeResource(&p12Cxt->super);
SSM_DEBUG("Done backing up certs.\n");
}
SSMStatus
SSM_WarnPKCS12Incompatibility(SSMTextGenContext *cx)
{
SSMStatus rv;
char *value;
rv = SSM_HTTPParamValue(cx->m_request, "multipleCerts", &value);
PR_FREEIF(cx->m_result);
cx->m_result = NULL;
if (rv == SSM_SUCCESS) {
rv = SSM_FindUTF8StringInBundles(cx, "pkcs12_incompatible_warn",
&cx->m_result);
if (rv != SSM_SUCCESS) {
cx->m_result = PL_strdup("");
}
} else {
cx->m_result = PL_strdup("");
}
return SSM_SUCCESS;
}

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

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

@ -0,0 +1,280 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 "p7cinfo.h"
#include "ssmerrs.h"
/* Shorthand macros for inherited classes */
#define SSMRESOURCE(ci) (&(ci)->super)
SSMStatus
SSMP7ContentInfo_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMP7ContentInfo *ci;
*res = NULL; /* in case we fail */
ci = (SSMP7ContentInfo *) PR_CALLOC(sizeof(SSMP7ContentInfo));
if (!ci) goto loser;
SSMRESOURCE(ci)->m_connection = connection;
rv = SSMP7ContentInfo_Init(ci, connection, (SEC_PKCS7ContentInfo *) arg,
SSM_RESTYPE_PKCS7_CONTENT_INFO);
if (rv != PR_SUCCESS) goto loser;
SSMP7ContentInfo_Invariant(ci);
*res = SSMRESOURCE(ci);
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (ci)
{
SSMRESOURCE(ci)->m_refCount = 1; /* force destroy */
SSM_FreeResource(SSMRESOURCE(ci));
}
return rv;
}
SSMStatus
SSMP7ContentInfo_Init(SSMP7ContentInfo *ci, SSMControlConnection * conn,
SEC_PKCS7ContentInfo *cinfo,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
/* Initialize superclass */
rv = SSMResource_Init(conn, SSMRESOURCE(ci), type);
if (rv != PR_SUCCESS) goto loser;
/* Fill in the content info */
PR_ASSERT(cinfo != NULL);
ci->m_cinfo = cinfo;
/* Sanity check before returning */
SSMP7ContentInfo_Invariant(ci);
goto done;
loser:
/* member destruct, if any are allocated, will happen in the
_Destroy method */
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMP7ContentInfo_Destroy(SSMResource *res, PRBool doFree)
{
SSMP7ContentInfo *ci = (SSMP7ContentInfo *) res;
SSMP7ContentInfo_Invariant(ci);
/* Destroy our members. */
if (ci->m_cinfo)
{
SEC_PKCS7DestroyContentInfo(ci->m_cinfo);
ci->m_cinfo = NULL;
}
/* Destroy superclass. */
SSMResource_Destroy(res, PR_FALSE);
/* Free if asked. */
if (doFree)
PR_Free(res);
return PR_SUCCESS;
}
void
SSMP7ContentInfo_Invariant(SSMP7ContentInfo *ci)
{
/* Superclass invariant */
SSMResource_Invariant(SSMRESOURCE(ci));
SSM_LockResource(SSMRESOURCE(ci));
/* Class check */
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(ci), SSM_RESTYPE_PKCS7_CONTENT_INFO));
/* Member check */
PR_ASSERT(ci->m_cinfo != NULL);
if (ci->m_signerCert)
PR_ASSERT(SSM_IsAKindOf(&(ci->m_signerCert->super),SSM_RESTYPE_CERTIFICATE));
SSM_UnlockResource(SSMRESOURCE(ci));
}
SSMStatus
SSMP7ContentInfo_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMResource_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 3) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_P7CINFO_IS_SIGNED;
(*ids)[*count++] = SSM_FID_P7CINFO_IS_ENCRYPTED;
(*ids)[*count++] = SSM_FID_P7CINFO_SIGNER_CERT;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMP7ContentInfo_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMP7ContentInfo *cinfo = (SSMP7ContentInfo *) res;
SEC_PKCS7ContentInfo *info;
SSMStatus rv = SSM_SUCCESS;
SSMP7ContentInfo_Invariant(cinfo);
if (!cinfo)
{
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
SSM_LockResource(SSMRESOURCE(cinfo));
info = cinfo->m_cinfo;
if (!info)
{
rv = SSM_ERR_ATTRIBUTE_MISSING;
goto loser;
}
/* see what it is */
switch(attrID)
{
case SSM_FID_P7CINFO_IS_SIGNED:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = SEC_PKCS7ContentIsSigned(cinfo->m_cinfo);
rv = SSM_SUCCESS;
break;
case SSM_FID_P7CINFO_IS_ENCRYPTED:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = SEC_PKCS7ContentIsEncrypted(cinfo->m_cinfo);
rv = SSM_SUCCESS;
break;
case SSM_FID_P7CINFO_SIGNER_CERT:
/* Make sure we have a cert to return. */
rv = SSM_ERR_ATTRIBUTE_MISSING; /* by default */
/* want signed data */
if ((info->content.signedData) &&
/* want signer info */
(info->content.signedData->signerInfos) &&
/* 1 and only 1 signer
### mwelch what if we have more than one? */
(info->content.signedData->signerInfos[0]) &&
(info->content.signedData->signerInfos[1] == NULL))
{
/* Get the cert, wrap it in a resource, and return its ID. */
CERTCertificate *cert =
info->content.signedData->signerInfos[0]->cert;
SSMResourceID certID;
if (!cert) goto loser; /* we could still have a null cert */
rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
cert,
SSMRESOURCE(cinfo)->m_connection,
&certID,
(SSMResource **) &cinfo->m_signerCert);
SSMP7ContentInfo_Invariant(cinfo);
value->type = SSM_RID_ATTRIBUTE;
rv = SSM_ClientGetResourceReference(&cinfo->m_signerCert->super,
&certID);
if (rv != PR_SUCCESS)
goto loser;
rv = SSM_SUCCESS;
value->type = SSM_RID_ATTRIBUTE;
value->u.numeric = certID;
SSM_FreeResource(&cinfo->m_signerCert->super);
}
break;
default:
rv = SSMResource_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS) goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
if (cinfo)
SSM_UnlockResource(SSMRESOURCE(cinfo));
return rv;
}
SSMStatus SSMP7ContentInfo_VerifyDetachedSignature(SSMP7ContentInfo *ci,
SECCertUsage usage,
HASH_HashType hash,
PRBool keepCerts,
PRIntn digestLen,
char *detachedDigest)
{
SSMStatus rv = PR_FAILURE;
SECItem digest;
SSMP7ContentInfo_Invariant(ci);
digest.len = digestLen;
digest.data = (unsigned char*) detachedDigest;
if (ci->m_cinfo)
{
if (SEC_PKCS7VerifyDetachedSignature(ci->m_cinfo, usage,
&digest, hash, keepCerts))
rv = SSM_SUCCESS;
}
return rv;
}

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

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

@ -0,0 +1,513 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 "p7dconn.h"
#include "serv.h"
#include "servimpl.h"
#include "ssmerrs.h"
#include "newproto.h"
#include "messages.h"
#include "collectn.h"
#include "secmime.h"
/* Shorthand macros for inherited classes */
#define SSMRESOURCE(conn) (&(conn)->super.super.super)
#define SSMCONNECTION(conn) (&(conn)->super.super)
#define SSMDATACONNECTION(conn) (&(conn)->super)
#define SSM_PARENT_CONN(conn) ((SSMControlConnection*)((conn)->super.super.m_parent))
void SSMP7DecodeConnection_ServiceThread(void * arg);
SSMStatus SSMP7DecodeConnection_StartDecoding(SSMP7DecodeConnection *conn);
/* callbacks for PKCS7 decoder */
void SSMP7DecodeConnection_ContentCallback(void *arg,
const char *buf,
unsigned long len);
PK11SymKey * SSMP7DecodeConnection_GetDecryptKey(void *arg,
SECAlgorithmID *algid);
PRBool SSMP7DecodeConnection_DecryptionAllowed(SECAlgorithmID *algid,
PK11SymKey *bulkkey);
SECItem * SSMP7DecodeConnection_GetPasswordKey(void *arg,
SECKEYKeyDBHandle *handle);
SSMStatus SSMP7DecodeConnection_Create(void *arg,
SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMP7DecodeConnection *conn;
*res = NULL; /* in case we fail */
conn = (SSMP7DecodeConnection *) PR_CALLOC(sizeof(SSMP7DecodeConnection));
if (!conn) goto loser;
SSMRESOURCE(conn)->m_connection = connection;
rv = SSMP7DecodeConnection_Init(conn, (SSMInfoP7Decode*) arg,
SSM_RESTYPE_PKCS7_DECODE_CONNECTION);
if (rv != PR_SUCCESS) goto loser;
SSMP7DecodeConnection_Invariant(conn);
*res = SSMRESOURCE(conn);
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (conn)
{
SSM_ShutdownResource(SSMRESOURCE(conn), rv); /* force destroy */
SSM_FreeResource(SSMRESOURCE(conn));
}
return rv;
}
SSMStatus SSMP7DecodeConnection_Init(SSMP7DecodeConnection *conn,
SSMInfoP7Decode *info,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
rv = SSMDataConnection_Init(SSMDATACONNECTION(conn), info->ctrl, type);
if (rv != PR_SUCCESS) goto loser;
/* Start the decoder */
if (SSMP7DecodeConnection_StartDecoding(conn) != SSM_SUCCESS) {
goto loser;
}
/* Save the client UI context */
SSMRESOURCE(conn)->m_clientContext = info->clientContext;
/* Spin the service thread. */
SSM_DEBUG("Creating decoder service thread.\n");
SSM_GetResourceReference(SSMRESOURCE(conn));
SSMDATACONNECTION(conn)->m_dataServiceThread =
SSM_CreateThread(SSMRESOURCE(conn),
SSMP7DecodeConnection_ServiceThread);
if (SSMDATACONNECTION(conn)->m_dataServiceThread == NULL) {
goto loser;
}
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
return rv;
}
SSMStatus
SSMP7DecodeConnection_FinishDecoding(SSMP7DecodeConnection *conn)
{
SEC_PKCS7ContentInfo *p7info = NULL;
SSMResourceID resID;
SSMStatus rv = SSM_SUCCESS;
if (conn->m_cinfo)
{
SSM_FreeResource(&conn->m_cinfo->super);
conn->m_cinfo = NULL;
}
if (conn->m_context)
{
p7info = SEC_PKCS7DecoderFinish(conn->m_context);
if (!p7info) {
conn->m_error = PR_GetError();
}
conn->m_context = NULL;
if (p7info)
{
rv = SSM_CreateResource(SSM_RESTYPE_PKCS7_CONTENT_INFO,
p7info,
SSM_PARENT_CONN(conn),
&resID,
(SSMResource **) &conn->m_cinfo);
}
else
rv = PR_FAILURE;
SSM_LockResource(&conn->super.super.super);
SSM_NotifyResource(&conn->super.super.super);
SSM_UnlockResource(&conn->super.super.super);
}
return rv;
}
SSMStatus
SSMP7DecodeConnection_StartDecoding(SSMP7DecodeConnection *conn)
{
PR_ASSERT(conn->m_context == NULL);
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context)
SSMP7DecodeConnection_FinishDecoding(conn);
conn->m_context =
SEC_PKCS7DecoderStart(SSMP7DecodeConnection_ContentCallback,
conn,
SSMP7DecodeConnection_GetPasswordKey,
conn,
SSMP7DecodeConnection_GetDecryptKey,
conn,
SSMP7DecodeConnection_DecryptionAllowed);
SSM_UnlockResource(SSMRESOURCE(conn));
/* Did we get a context */
if (!conn->m_context) {
conn->m_error = PR_GetError();
return PR_FAILURE;
} else {
return PR_SUCCESS;
}
}
SSMStatus SSMP7DecodeConnection_Destroy(SSMResource *res, PRBool doFree)
{
SSMP7DecodeConnection *conn = (SSMP7DecodeConnection *) res;
if (doFree)
SSM_DEBUG("SSMP7DecodeConnection_Destroy called.\n");
/* We should be shut down. */
PR_ASSERT(res->m_threadCount == 0);
/* Destroy our fields. */
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context)
SSMP7DecodeConnection_FinishDecoding(conn);
if (conn->m_cinfo)
{
SSM_FreeResource(&conn->m_cinfo->super);
conn->m_cinfo = NULL;
}
SSM_UnlockResource(SSMRESOURCE(conn));
/* Destroy superclass fields. */
SSMDataConnection_Destroy(SSMRESOURCE(conn), PR_FALSE);
/* Free the connection object if asked. */
if (doFree)
PR_DELETE(conn);
return PR_SUCCESS;
}
void
SSMP7DecodeConnection_Invariant(SSMP7DecodeConnection *conn)
{
SSMDataConnection_Invariant(SSMDATACONNECTION(conn));
/* our specific invariants */
SSM_LockResource(SSMRESOURCE(conn));
/* check class */
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn), SSM_RESTYPE_PKCS7_DECODE_CONNECTION));
/* we should not be simultaneously decoded and decoding */
if (conn->m_context)
PR_ASSERT(conn->m_cinfo == NULL);
SSM_UnlockResource(SSMRESOURCE(conn));
}
SSMStatus
SSMP7DecodeConnection_Shutdown(SSMResource *arg, SSMStatus status)
{
SSMStatus rv = SSM_SUCCESS;
/* Call our superclass shutdown. */
rv = SSMDataConnection_Shutdown(arg, status);
return rv;
}
/*
PKCS7 decoding is performed by a single service thread. This thread
feeds data from the outgoing queue into the PKCS7 decoder.
*/
void SSMP7DecodeConnection_ServiceThread(void * arg)
{
SSMStatus rv = PR_SUCCESS;
SSMP7DecodeConnection* conn;
SSMControlConnection* ctrl;
SECItem* msg;
PRIntn read;
char buffer[LINESIZE+1] = {0};
SSM_RegisterNewThread("p7decode", (SSMResource *) arg);
conn = (SSMP7DecodeConnection *)arg;
SSM_DEBUG("initializing.\n");
if (!arg)
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto loser;
}
SSMDATACONNECTION(conn)->m_dataServiceThread = PR_GetCurrentThread();
/* set up the client data socket and authenticate it with nonce */
rv = SSMDataConnection_SetupClientSocket(SSMDATACONNECTION(conn));
if (rv != PR_SUCCESS) {
goto loser;
}
/* Start decoding */
SSM_DEBUG("Start updating decoder..\n");
while ((SSMRESOURCE(conn)->m_status == PR_SUCCESS) &&
(SSM_Count(SSMDATACONNECTION(conn)->m_shutdownQ) == 0) &&
(rv == PR_SUCCESS)) {
read = LINESIZE; /* set the read size to the default line size */
rv = SSMDataConnection_ReadFromSocket(SSMDATACONNECTION(conn),
(PRInt32*)&read, buffer);
if (read > 0) {
/* there is data, pass it along to PKCS7 */
SSM_DEBUG("Received %ld bytes of data for decoder.\n", read);
PR_ASSERT(conn->m_context);
if (SEC_PKCS7DecoderUpdate(conn->m_context, buffer, read) != SECSuccess) {
conn->m_error = PR_GetError();
goto finish;
}
} else {
/* either EOF or an error condition */
/* If we have a decoder in progress, stop it. */
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context) {
SSM_DEBUG("Stopping PKCS7 decoder, generating content info struct.\n");
SSMP7DecodeConnection_FinishDecoding(conn);
}
SSM_UnlockResource(SSMRESOURCE(conn));
break;
}
}
finish:
/* we have an EOF, shut down the client socket */
PR_ASSERT(SSMDATACONNECTION(conn)->m_clientSocket != NULL);
if (SSMDATACONNECTION(conn)->m_clientSocket != NULL) {
SSM_DEBUG("shutting down client socket.\n");
SSM_LockResource(SSMRESOURCE(conn));
PR_Shutdown(SSMDATACONNECTION(conn)->m_clientSocket,
PR_SHUTDOWN_SEND);
SSM_UnlockResource(SSMRESOURCE(conn));
}
/* If we've been asked to return the result, return it. */
if (SSMDATACONNECTION(conn)->m_sendResult) {
SSM_DEBUG("Responding to deferred content info request.\n");
msg = (SECItem*)PORT_ZAlloc(sizeof(SECItem));
PR_ASSERT(msg != NULL); /* need to have some preallocated
failure to send */
if (conn->m_cinfo) {
SSMAttributeValue value;
GetAttribReply reply;
value.type = SSM_RID_ATTRIBUTE;
rv = SSM_ClientGetResourceReference(&conn->m_cinfo->super,
&value.u.rid);
if (rv != PR_SUCCESS) {
goto loser;
}
msg->type = (SECItemType) (SSM_REPLY_OK_MESSAGE | SSM_RESOURCE_ACTION
| SSM_GET_ATTRIBUTE | SSM_RID_ATTRIBUTE);
reply.result = SSM_SUCCESS;
reply.value = value;
if (CMT_EncodeMessage(GetAttribReplyTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
goto loser;
}
SSM_DEBUG("Generated a reply (t %lx/l %ld/d %lx)\n",
msg->type, msg->len, msg->data);
/*
* We don't need the content info anymore since we sent it back
* Is it OK to release our reference?
*/
SSM_FreeResource(&conn->m_cinfo->super);
conn->m_cinfo = NULL;
}
else {
SingleNumMessage reply;
msg->type = (SECItemType) (SSM_REPLY_ERR_MESSAGE | SSM_RESOURCE_ACTION
| SSM_GET_ATTRIBUTE | SSM_STRING_ATTRIBUTE);
reply.value = SSM_ERR_ATTRIBUTE_MISSING;
if (CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
goto loser;
}
SSM_DEBUG("Generated error reply (t %lx/l %ld/d %lx)\n",
msg->type, msg->len, msg->data);
}
/* Post this message to the parent's control queue
for delivery back to the client. */
ctrl = (SSMControlConnection*)(SSMCONNECTION(conn)->m_parent);
PR_ASSERT(SSM_IsAKindOf(&ctrl->super.super, SSM_RESTYPE_CONTROL_CONNECTION));
rv = SSM_SendQMessage(ctrl->m_controlOutQ,
SSM_PRIORITY_NORMAL,
msg->type, msg->len,
(char*)msg->data, PR_TRUE);
SSM_FreeMessage(msg);
if (rv != PR_SUCCESS) goto loser;
}
loser:
SSM_DEBUG("** Thread shutting down ** (%ld)\n", rv);
if (conn != NULL) {
SSM_ShutdownResource(SSMRESOURCE(conn), rv);
SSM_FreeResource(SSMRESOURCE(conn));
}
}
SSMStatus
SSMP7DecodeConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMDataConnection_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 1) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_P7CONN_CONTENT_INFO;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMP7DecodeConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMStatus rv = PR_SUCCESS;
SSMP7DecodeConnection *dc = (SSMP7DecodeConnection *) res;
SSMP7DecodeConnection_Invariant(dc);
/* see what it is */
switch(attrID)
{
case SSM_FID_P7CONN_CONTENT_INFO:
if (!dc->m_cinfo) {
SSM_LockResource(res);
SSM_WaitResource(res, PR_TicksPerSecond());
SSM_UnlockResource(res);
/*
* If it's still NULL, then something really bad happened.
*/
if (!dc->m_cinfo)
goto loser;
}
/* Allocate a resource ID */
value->type = SSM_RID_ATTRIBUTE;
rv = SSM_ClientGetResourceReference(&dc->m_cinfo->super, &value->u.rid);
if (rv != PR_SUCCESS)
goto loser;
/* Let's get rid of our reference to it and let the client inherit it.
*/
SSM_LockResource(res);
SSM_FreeResource(&dc->m_cinfo->super);
dc->m_cinfo = NULL;
SSM_UnlockResource(res);
break;
case SSM_FID_RESOURCE_ERROR:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = dc->m_error;
break;
default:
rv = SSMDataConnection_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS)
goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
return rv;
}
/* Callback functions for decoder. For now, use empty/default functions. */
void SSMP7DecodeConnection_ContentCallback(void *arg,
const char *buf,
unsigned long len)
{
SSMStatus rv;
SSMP7DecodeConnection *conn = (SSMP7DecodeConnection *)arg;
PRIntn sent = 0;
SSM_DEBUG("writing data to socket.\n");
PR_ASSERT(SSMDATACONNECTION(conn)->m_clientSocket != NULL);
sent = PR_Send(SSMDATACONNECTION(conn)->m_clientSocket, (void*)buf,
(PRIntn)len, 0, PR_INTERVAL_NO_TIMEOUT);
if (sent != (PRIntn)len) {
rv = PR_GetError();
SSM_DEBUG("error writing data: %d \n", rv);
}
}
PK11SymKey * SSMP7DecodeConnection_GetDecryptKey(void *arg,
SECAlgorithmID *algid)
{
return NULL;
}
PRBool SSMP7DecodeConnection_DecryptionAllowed(SECAlgorithmID *algid,
PK11SymKey *bulkkey)
{
return SECMIME_DecryptionAllowed(algid, bulkkey);
}
SECItem * SSMP7DecodeConnection_GetPasswordKey(void *arg,
SECKEYKeyDBHandle *handle)
{
return NULL;
}

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

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

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

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

@ -0,0 +1,947 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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 "connect.h"
#include "ssmerrs.h"
#include "ctrlconn.h"
#include "prinrval.h"
#include "crmf.h"
#include "newproto.h"
#include "messages.h"
#include "minihttp.h"
#include "textgen.h"
#include "sechash.h"
#include "pk11func.h"
extern SSMHashTable * tokenList;
extern PRMonitor * tokenLock;
#define SSMRESOURCE(conn) (&(conn)->super)
/* Make these into functions? */
#if 0
#define SSM_PARENT_CONN(x) ((((SSMConnection *)(x))->m_parent) != NULL)? \
(((SSMControlConnection *)(((SSMConnection *)(x))->m_parent))):\
((SSMControlConnection *)x)
#define SSM_PWD_TABLE(x) (SSM_PARENT_CONN(x))->m_passwdTable
#define SSM_OUT_QUEUE(x) (SSM_PARENT_CONN(x))->m_controlOutQ
#endif
#if 1
SSMControlConnection * SSM_PARENT_CONN (SSMConnection * x)
{
return (((((SSMConnection *)(x))->m_parent) != NULL)?
(((SSMControlConnection *)(((SSMConnection *)(x))->m_parent))):
((SSMControlConnection *)x));
}
SSMHashTable * SSM_PWD_TABLE(SSMConnection * x)
{
return (SSM_PARENT_CONN(x)->m_passwdTable);
}
SSMCollection * SSM_OUT_QUEUE(SSMConnection * x)
{
return (SSM_PARENT_CONN(x)->m_controlOutQ);
}
#endif
PRInt32 SSM_GetTokenKey(PK11SlotInfo * slot)
{
return ((PK11_GetSlotID(slot)<<16) | PK11_GetModuleID(slot));
}
char * SSM_GetPasswdCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
{
return SSM_GetAuthentication(slot, retry, PR_FALSE, (SSMResource*)arg);
}
/* Do a couple of things in this functions:
* 1) Get a password from user, and authenticate to token.
* 2) Save this password encrypted in the global Cartman tokenList
* for future reference.
* Need to save password in case other users will need to authenticate
* to the same tokens, so we make sure they're using the correct
* passwords.
* 3) Save this password encrypted in the control connection table in
* case we will need to use it again.
*/
char * SSM_GetAuthentication(PK11SlotInfo * slot, PRBool retry, PRBool init,
SSMResource * res)
{
PRInt32 tokenKey;
SSMStatus rv = PR_SUCCESS;
char * passwd = NULL, * tmp = NULL;
PRBool first = PR_FALSE;
SSM_TokenInfo * info = NULL, * infoLocal = NULL;
SSMConnection *conn = &(res->m_connection->super);
tokenKey = SSM_GetTokenKey(slot);
/* register as interested in a password */
SSM_PARENT_CONN(conn)->m_waiting++;
/* Get passwd table lock. */
SSM_LockPasswdTable(conn);
/* Look for entry for moduleID/slotID. */
rv = SSM_HashFind(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
SSM_UnlockPasswdTable(conn);
if (rv != PR_SUCCESS) {
first = PR_TRUE;
/* no entry found, we are the first to authenticate to this slot */
SSM_DEBUG("%ld: creating passwd table entry for %s \n",
conn, PK11_GetSlotName(slot));
SSM_LockPasswdTable(conn);
rv = SSM_HashInsert(SSM_PWD_TABLE(conn),tokenKey,(void *)SSM_NO_PASSWORD);
SSM_UnlockPasswdTable(conn);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: could not create entry in password table\n", conn);
goto loser;
}
rv = SSM_AskUserPassword(res, slot, retry, init);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: error sending password request event\n", conn);
goto loser;
}
} /* end of the we-are-first-to-request-this-passwd-clause */
/* If no password found, wait for it */
if (!passwd || passwd == (char *)SSM_NO_PASSWORD) {
rv = SSMControlConnection_WaitPassword(conn, tokenKey, &passwd);
if (rv != PR_SUCCESS)
goto loser;
}
if (((int) passwd) == SSM_CANCEL_PASSWORD) {
/* no password was provided or user hit "Cancel" */
SSM_LockPasswdTable(conn);
rv = SSM_HashRemove(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
SSM_UnlockPasswdTable(conn);
if (rv != SSM_SUCCESS)
SSM_DEBUG("SSM_GetAuthentication: user hit Cancel, can't remove password from connection table\n");
passwd = NULL;
goto done;
}
if (first) {
/* We were the first to request the password,
* so we need to enter it in to the token list.
*/
/* encrypt the password */
if (SSM_EncryptPasswd(slot, passwd, &info) != SSM_SUCCESS) {
SSM_DEBUG("%ld: could not encrypt password\n.", conn);
goto loser;
}
/* Place encrypted passwd in Cartman-wide tokenList */
PR_EnterMonitor(tokenLock);
/* Remove from tokenList if already on the list - must be stale */
rv = SSM_HashRemove(tokenList, tokenKey, (void **)&tmp);
if (rv == SSM_SUCCESS && tmp && tmp != (char *)SSM_NO_PASSWORD
&& tmp != (char *)SSM_CANCEL_PASSWORD) { /* free stale data */
PR_Free(tmp);
tmp = NULL;
}
rv = SSM_HashInsert(tokenList, tokenKey, info);
PR_ExitMonitor(tokenLock);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: can't create encr passwd entry\n", conn, tokenKey);
goto loser;
}
/* Store encrypted password in control connection table */
infoLocal = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
if (!infoLocal)
goto loser;
infoLocal->slot = info->slot;
infoLocal->tokenID = info->tokenID;
infoLocal->encryptedLen = info->encryptedLen;
infoLocal->symKey = info->symKey;
infoLocal->encrypted = (char *) PORT_ZAlloc(info->encryptedLen);
if (!infoLocal->encrypted)
goto loser;
memcpy(infoLocal->encrypted, info->encrypted, info->encryptedLen);
PR_EnterMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
rv = SSM_HashRemove(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
(void **)&tmp);
if (rv == SSM_SUCCESS && tmp && tmp != (char *)SSM_NO_PASSWORD &&
tmp != (char *)SSM_CANCEL_PASSWORD ) {/* free stale data */
PR_Free(tmp);
tmp = NULL;
}
rv = SSM_HashInsert(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
infoLocal);
PR_ExitMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: cannot insert token %d entry in encrPasswdTable\n",
conn, tokenKey);
goto loser;
}
SSM_DEBUG("%ld: wait untill others are done with passwd, remove it\n",
conn);
/* while ((SSM_PARENT_CONN(conn))->m_waiting > 1)
* PR_Sleep(SSM_PASSWORD_WAIT_TIME);
*/
SSM_LockPasswdTable(conn);
rv = SSM_HashRemove(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: could not remove passwd.\n", conn);
goto loser;
}
SSM_UnlockPasswdTable(conn);
} /* end of if-first clause */
goto done;
loser:
/* cleanup */
PR_FREEIF(passwd);
passwd = NULL;
if (info) {
PR_FREEIF(info->encrypted);
PR_Free(info);
}
if (infoLocal) {
PR_FREEIF(infoLocal->encrypted);
PR_Free(infoLocal);
}
done:
/* We are done receiving passwd */
(SSM_PARENT_CONN(conn))->m_waiting--;
return passwd ? strdup (passwd) : NULL;
}
/*
* We get this callback if the slot is already logged-in.
* Need to check client-supplied password against the password stored in
* tokenList.
*/
PRBool SSM_VerifyPasswdCallback(PK11SlotInfo * slot, void * arg)
{
char * passwd = NULL;
PRInt32 tokenKey;
SSM_TokenInfo * info = NULL;
SSM_TokenInfo * tokenInfo = NULL;
SSMStatus rv;
PRBool result = PR_FALSE;
SSMResource * res = (SSMResource*)arg;
SSMConnection * conn = &(res->m_connection->super);
PRInt32 doTry = 0;
void * tmp = NULL;
if (!slot || !arg)
goto loser;
tokenKey = PK11_GetSlotID(slot) ^ PK11_GetModuleID(slot);
info = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
if (!info) {
SSM_DEBUG("Could not allocate memory in VerifyPasswdCallback.\n");
goto loser;
}
/* Get the password for this token.
* We might have to find it in the local encrypted password table or
* to request it from the client.
*/
rv = SSM_HashFind(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
(void **)&info);
if (rv != PR_SUCCESS || info == (void *)SSM_NO_PASSWORD) {
askpassword:
/* ask user for a password and store it in local passwd table */
rv = SSM_AskUserPassword(res, slot, doTry?PR_TRUE:PR_FALSE, PR_FALSE);
if (rv != PR_SUCCESS)
goto loser;
doTry++;
rv = SSMControlConnection_WaitPassword(conn, tokenKey, &passwd);
if (rv != PR_SUCCESS || !passwd)
goto loser;
rv = SSM_EncryptPasswd(slot, passwd, &info);
if (rv != SSM_SUCCESS)
goto loser;
} /* end of no password, ask user */
/* Now get the stored password for this token */
if (!tokenInfo) {
PR_EnterMonitor(tokenLock);
rv = SSM_HashFind(tokenList, tokenKey, (void **)&tokenInfo);
PR_ExitMonitor(tokenLock);
if (rv != PR_SUCCESS || !tokenInfo) {
SSM_DEBUG("Can't find token info in VerifyPasswd.\n");
goto loser;
}
}
/* Check password against tokenList entry */
if (memcmp(tokenInfo->encrypted, info->encrypted, tokenInfo->encryptedLen)
!= 0 || tokenInfo->encryptedLen != info->encryptedLen) {
/* Failed compare, bad password */
/* first clean up */
if (info) PR_Free(info);
info = NULL;
/* If not retry, ask client for password. */
if (doTry < 2 ) {
/* ask user again */
PR_Free(passwd);
passwd = NULL;
goto askpassword;
}
else
goto loser;
} /* end of password not verified */
SSM_DEBUG("Password verified OK.\n");
/* store password for local use */
PR_EnterMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
SSM_HashRemove(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
(void **)&tmp);
if (tmp && tmp != (char *)SSM_NO_PASSWORD ) {/* free stale data */
PR_Free(tmp);
tmp = NULL;
}
rv = SSM_HashInsert(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
info);
PR_ExitMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: cannot insert token %d entry in encrPasswdTable\n",
conn, tokenKey);
goto loser;
}
result = PR_TRUE;
goto done;
loser:
SSM_DEBUG("Password not verified. \n");
/* log out this slot?? */
if (info) {
if (info->encrypted)
PR_Free(info->encrypted);
PR_Free(info);
}
result = PR_FALSE;
done:
if (passwd)
PR_Free(passwd);
return result;
}
/* Encrypt password for storage */
#define SSM_PAD_BLOCK_SIZE(x, y) ((((x) + ((y)-1))/(y))*(y))
SSMStatus SSM_EncryptPasswd(PK11SlotInfo * slot, char * passwd,
SSM_TokenInfo ** tokenInfo)
{
int resultLen;
char *hashResult = NULL;
SSMStatus rv = SSM_SUCCESS;
SECStatus srv;
SSM_TokenInfo * info;
/* Hash the password. */
resultLen = HASH_ResultLen(HASH_AlgSHA1);
hashResult = (char *) PORT_ZAlloc(resultLen); /* because the original PORT_ZAlloc'd */
if (!hashResult)
goto loser;
srv = HASH_HashBuf(HASH_AlgSHA1, (unsigned char *) hashResult, (unsigned char *) passwd, strlen(passwd));
if (srv != SECSuccess)
goto loser;
/* fill in the tokenInfo structure */
info = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
if (!info) {
SSM_DEBUG("EncryptPwd: could not allocate memory to token list entry.\n");
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
goto loser;
}
info->encrypted = hashResult;
info->encryptedLen = resultLen;
info->slot = slot;
info->tokenID = SSM_GetTokenKey(slot);
*tokenInfo = info;
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
PR_FREEIF(hashResult);
done:
return rv;
}
SSMStatus SSM_NotEncryptPasswd(PK11SlotInfo * slot, char * passwd,
SSM_TokenInfo * info)
{
CK_MECHANISM_TYPE mechanism;
/* CK_SESSION_HANDLE session = CK_INVALID_SESSION; */
PRInt32 keyLength, blockSize, outlen;
PRUint32 encryptedLength;
PK11SymKey * symKey;
SECStatus rv;
char * encrypted = NULL;
PK11Context * context=NULL;
SECItem *params;
if (!slot || !passwd || !info) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto loser;
}
mechanism = CRMF_GetBestWrapPadMechanism(slot);
keyLength = PK11_GetBestKeyLength(slot, mechanism);
/* session = PK11_GetRWSession(slot);
if (session == CK_INVALID_SESSION)
goto loser;*/
blockSize = PK11_GetBlockSize(mechanism, NULL);
/*
* A password is encrypted when we first authenticate to token.
* In this case, generate a symmetric Key on the slot.
* If the key is already present, it means that the password for this
* slot has already been encrypted and stored, need to encrypt
* new password with the same key to compare against the stored
* password.
*/
/* If no symKey found, generate one */
if (!info->symKey) {
symKey = PK11_KeyGen(slot, mechanism, NULL, keyLength, NULL);
if (!symKey) {
SSM_DEBUG("Failed to generate symKey to encrypt passwd.\n");
goto loser;
}
} else
symKey = info->symKey;
encryptedLength = SSM_PAD_BLOCK_SIZE(strlen(passwd)+1, blockSize);
encrypted = (char *) PORT_ZAlloc(encryptedLength);
if (!encrypted) {
SSM_DEBUG("Could not allocate space for encrypted password. \n");
goto loser;
}
params = CRMF_GetIVFromMechanism(mechanism);
context=PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT,
symKey, params);
if (params != NULL) {
SECITEM_FreeItem(params, PR_TRUE);
}
if (!context) {
SSM_DEBUG("Can't create context to encrypt password: %d.\n",
PR_GetError());
goto loser;
}
rv = PK11_CipherOp(context, (unsigned char *) encrypted, &outlen,
(int) encryptedLength,
(unsigned char *) passwd, strlen(passwd));
if (rv != PR_SUCCESS) {
SSM_DEBUG("Error encrypting password: %d\n", PR_GetError());
goto loser;
}
rv = PK11_DigestFinal(context, (unsigned char *) &encrypted[outlen],
(unsigned int *) &outlen, (unsigned int) blockSize);
if (rv != PR_SUCCESS) {
SSM_DEBUG("Error encrypting password: %d\n", PR_GetError());
goto loser;
}
PK11_DestroyContext(context, PR_TRUE);
/*if (session != CK_INVALID_SESSION)
PK11_RestoreROSession(slot, session);*/
/* fill in the tokenInfo structure */
info->encrypted = encrypted;
info->encryptedLen = encryptedLength;
info->slot = slot;
return SSM_SUCCESS;
loser:
SSM_DEBUG("Failed to encrypt password.\n");
if (context != NULL)
PK11_DestroyContext(context, PR_TRUE);
/*if (session != CK_INVALID_SESSION)
PK11_RestoreROSession(slot, session);*/
if (encrypted && *encrypted)
PR_Free(encrypted);
return SSM_FAILURE;
}
/* Needs to be fixed using NLS lib and proper string storage. -jane */
char * SSM_GetPrompt(PK11SlotInfo *slot, PRBool retry, PRBool init)
{
char * prompt = NULL, * tmp = NULL, * key;
SSMTextGenContext * cx;
SSMStatus rv;
PR_ASSERT(init != PR_TRUE);
rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
if (rv != SSM_SUCCESS || !cx)
goto loser;
if (retry)
key = "retry_token_password";
else
key = "ask_token_password";
rv = SSM_GetAndExpandTextKeyedByString(cx, key, &tmp);
if (rv != SSM_SUCCESS || !tmp)
goto loser;
prompt = PR_smprintf(tmp, PK11_GetTokenName(slot));
loser:
PR_FREEIF(tmp);
return prompt;
}
/* Send a password request for the client */
SSMStatus SSM_AskUserPassword(SSMResource * res,
PK11SlotInfo * slot, PRInt32 retry, PRBool init)
{
SECItem message;
char * prompt = NULL;
PRInt32 tokenKey = SSM_GetTokenKey(slot);
SSMStatus rv = PR_FAILURE;
SSMConnection *conn = (SSMConnection *)res->m_connection;
PasswordRequest request;
prompt = SSM_GetPrompt(slot, retry, init);
retry++;
if (!prompt) {
SSM_DEBUG("%ld: error getting prompt for password request.\n", conn);
goto loser;
}
request.tokenKey = tokenKey;
request.prompt = prompt;
request.clientContext = res->m_clientContext;
if (CMT_EncodeMessage(PasswordRequestTemplate, (CMTItem*)&message, &request) != CMTSuccess) {
goto loser;
}
if (message.len == 0 || !message.data) {
SSM_DEBUG("%ld: could not create password request message.\n", conn);
goto loser;
}
message.type = (SECItemType) (SSM_EVENT_MESSAGE | SSM_AUTH_EVENT);
rv = SSM_SendQMessage(SSM_OUT_QUEUE(conn), SSM_PRIORITY_UI, message.type,
message.len, (char *)message.data, PR_TRUE);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: Can't enqueue password request. \n", conn);
goto loser;
}
loser:
if (prompt)
PR_Free(prompt);
if (message.data)
PR_Free(message.data);
return rv;
}
SSMStatus SSMControlConnection_WaitPassword(SSMConnection * conn,
PRInt32 key, char ** str)
{
char * passwd;
PRIntervalTime before;
SSMStatus rv = PR_FAILURE;
*str = NULL;
/* Wait no longer than our time-out period. */
before = PR_IntervalNow();
SSM_LockPasswdTable(conn);
wait:
SSM_DEBUG("%ld : waiting on password table for the password\n", conn);
SSM_WaitPasswdTable(conn);
/* Returned from wait.
* Look for password.
*/
rv = SSM_HashFind(SSM_PWD_TABLE(conn), key, (void **)&passwd);
if (rv!=PR_SUCCESS || !passwd || passwd ==(char *)SSM_NO_PASSWORD) {
/* password not found, check for timeout */
if (PR_IntervalNow() - before > SSM_PASSWORD_WAIT_TIME) {
SSM_DEBUG("%ld:Timed out waiting for password.Bailing out.\n",
conn);
SSM_UnlockPasswdTable(conn);
return PR_FAILURE;
}
else
goto wait; /* continue waiting */
} /* end of no password found */
SSM_UnlockPasswdTable(conn);
*str = passwd;
return rv;
}
extern PK11SlotListElement *
PK11_GetNextSafe(PK11SlotList * list, PK11SlotListElement * element,PRBool start);
PK11SlotListElement *
ssm_GetSlotWithPwd(PK11SlotList * slotlist, PK11SlotListElement * current,
PRBool start)
{
PK11SlotListElement * next = NULL;
PR_ASSERT(slotlist);
if (!current || start)
next = PK11_GetFirstSafe(slotlist);
else
next = PK11_GetNextSafe(slotlist, current, PR_FALSE);
while (next && PK11_NeedUserInit(next->slot) && !PK11_NeedLogin(next->slot))
next = PK11_GetNextSafe(slotlist, next, PR_FALSE);
return next;
}
PRIntn
ssm_NumSlotsWithPassword(PK11SlotList * slotList)
{
PRIntn numslots = 0;
PK11SlotListElement * element = PK11_GetFirstSafe(slotList);
while (element) {
if (PK11_NeedLogin(element->slot) || !PK11_NeedUserInit(element->slot))
numslots++;
element = PK11_GetNextSafe(slotList, element,PR_FALSE);
}
return numslots;
}
SSMStatus SSM_ReSetPasswordKeywordHandler(SSMTextGenContext * cx)
{
char * slotname = NULL;
PK11SlotInfo * slot;
char * tmp = NULL;
SSMStatus rv;
SSMResource * target = cx->m_request->target;
PK11SlotList * slotList = NULL;
PK11SlotListElement * el = NULL;
PR_ASSERT(cx != NULL);
PR_ASSERT(cx->m_request != NULL);
PR_ASSERT(&cx->m_result != NULL);
rv = SSM_HTTPParamValue(cx->m_request, "action", &slotname);
if (!slotname || strcmp(slotname, "")== 0)
slot = PK11_GetInternalKeySlot();
else if (strcmp(slotname, "all") == 0) {
/* ask user */
slotList = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_TRUE, PR_TRUE, target);
if (!slotList || !slotList->head)
goto loser;
if (ssm_NumSlotsWithPassword(slotList)>1) {
char * mech = PR_smprintf("mech=%d&unused1=unused1&unused2=unused2",CKM_INVALID_MECHANISM);
SSM_LockUIEvent(target);
rv = SSMControlConnection_SendUIEvent(cx->m_request->ctrlconn,
"get", "select_token",
target,mech,&target->m_clientContext);
SSM_WaitUIEvent(target, PR_INTERVAL_NO_TIMEOUT);
slot = (PK11SlotInfo *) target->m_uiData;
if (!slot)
goto cancel;
} else {
/* only one interesting slot in the list */
el = ssm_GetSlotWithPwd(slotList, NULL, PR_TRUE);
slot = el->slot;
}
}
else
slot = PK11_FindSlotByName(slotname);
if (!slot) {
SSM_DEBUG("ReSetPasswordKeywordHandler: bad slotname %s\n", slotname);
goto loser;
}
slotname = PK11_GetTokenName(slot);
if (PK11_NeedPWInitForSlot(slot))
rv = SSM_GetAndExpandTextKeyedByString(cx, "set_new_password", &tmp);
else
rv = SSM_GetAndExpandTextKeyedByString(cx, "reset_password", &tmp);
if (rv != SSM_SUCCESS)
goto loser;
PR_FREEIF(cx->m_result);
cx->m_result = PR_smprintf(tmp, slotname);
return rv;
loser:
if (cx->m_result)
PR_Free(cx->m_result);
cx->m_result = NULL;
return PR_FAILURE;
cancel:
SSM_HTTPCloseWindow(cx->m_request);
goto loser;
}
PRBool
ssm_VerifyPwdLength(char * password)
{
if (!password)
return (!SSM_MIN_PWD_LEN);
if (strlen(password) < SSM_MIN_PWD_LEN)
return PR_FALSE;
if (strlen(password) > SSM_MAX_PWD_LEN)
return PR_FALSE;
return PR_TRUE;
}
SSMStatus SSM_PasswordPrefKeywordHandler(SSMTextGenContext * cx)
{
char * fmt = NULL, * checked = NULL;
char * markchecked[] = { "", "", ""};
SSMStatus rv;
PRIntn askpw, timeout;
PR_ASSERT(cx != NULL);
PR_ASSERT(cx->m_request != NULL);
PR_ASSERT(cx->m_result != NULL);
/* need to get the table and fill it with current preferences */
rv = SSM_GetAndExpandTextKeyedByString(cx, "password_lifetime", &fmt);
if (rv != SSM_SUCCESS || !fmt)
goto done;
rv = SSM_GetAndExpandTextKeyedByString(cx, "text_checked", &checked);
if (rv != SSM_SUCCESS || !checked)
goto done;
rv = PREF_GetIntPref(cx->m_request->ctrlconn->m_prefs,
"security.ask_for_password", &askpw);
if (rv != SSM_SUCCESS)
goto done;
rv = PREF_GetIntPref(cx->m_request->ctrlconn->m_prefs,
"security.password_lifetime", &timeout);
if (rv != SSM_SUCCESS)
goto done;
markchecked[askpw] = checked;
PR_FREEIF(cx->m_result);
cx->m_result = PR_smprintf(fmt, markchecked[0], markchecked[1],
markchecked[2], timeout);
done:
return rv;
}
SSMStatus SSM_SetDBPasswordHandler(HTTPRequest * req)
{
SSMStatus rv = SSM_FAILURE;
char * oldpassword, * newpassword, *repeatpassword, * action;
PK11SlotInfo * slot;
char * responseKey = NULL;
char * result = NULL;
char * slotname = NULL, * askpwdoption, * pwdlifetime;
PRIntn askpw, timeout;
rv = SSM_HTTPParamValue(req, "baseRef", &action);
if (rv != SSM_SUCCESS || strcmp(action, "windowclose_doclose_js")!= 0)
SSM_DEBUG("SetDBPasswordHandler: bad action %s\n", action);
rv = SSM_HTTPParamValue(req, "slot", &slotname);
if (rv != SSM_SUCCESS || !slotname ||
!(slot = PK11_FindSlotByName(slotname)))
goto loser;
/* process password preferences */
rv = SSM_HTTPParamValue(req, "passwordlife", &askpwdoption);
if (rv != SSM_SUCCESS || !askpwdoption)
goto loser;
rv = SSM_HTTPParamValue(req, "passwordwillexpire", &pwdlifetime);
if (rv != SSM_SUCCESS || !pwdlifetime)
goto loser;
if (strcmp(askpwdoption, "firsttime") == 0)
askpw = 0;
else if (strcmp(askpwdoption, "everytime") == 0)
askpw = 1;
else if (strcmp(askpwdoption, "expiretime")==0) {
askpw = 2;
}
else {
SSM_DEBUG("SetDBPasswordHandler: bad password lifetime parameter %s\n",
askpwdoption);
goto loser;
}
timeout = atoi(pwdlifetime);
if (askpw == 2 && !timeout)
goto loser;
PK11_SetSlotPWValues(slot, askpw, timeout);
rv = SSMControlConnection_SaveIntPref(req->ctrlconn,
"security.ask_for_password", askpw);
if (rv != PR_SUCCESS)
goto loser;
rv = SSMControlConnection_SaveIntPref(req->ctrlconn,
"security.password_lifetime", timeout);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPParamValue(req, "newpassword", &newpassword);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPParamValue(req, "repeatpassword", &repeatpassword);
if (rv != SSM_SUCCESS)
goto loser;
if (!PK11_NeedPWInitForSlot(slot)) {
/* oldpassword doesn't make sense for password initialization dialog */
rv = SSM_HTTPParamValue(req, "oldpassword", &oldpassword);
if (rv != SSM_SUCCESS) {
goto loser;
}
/* we do this check to find the case where the user changed only password
* settings, not the password itself
*/
if ((oldpassword[0] == '\0') && (newpassword[0] == '\0') &&
(repeatpassword[0] == '\0')) {
rv = SSM_HTTPDefaultCommandHandler(req);
goto done;
}
}
if (!ssm_VerifyPwdLength(newpassword))
goto loser;
if (strcmp(newpassword, repeatpassword) != 0)
goto loser;
if (!PK11_NeedPWInitForSlot(slot)) { /* there is some password on the DB */
if (!oldpassword)
goto loser;
if (PK11_CheckUserPassword(slot, oldpassword) !=
SECSuccess)
goto loser;
if (PK11_ChangePW(slot, oldpassword, newpassword) !=
SECSuccess)
goto loser;
}
else
{
if (PK11_NeedUserInit(slot)) {
if (PK11_InitPin(slot, NULL, newpassword) != SECSuccess)
goto loser;
}
else {
if (PK11_ChangePW(slot, NULL, newpassword) != SECSuccess)
goto loser;
}
}
result = PR_smprintf("result=password_success");
loser:
if (!result)
result = PR_smprintf("result=password_failure");
rv = SSM_HTTPCloseAndSleep(req);
if (rv != SSM_SUCCESS)
SSM_DEBUG("SetDBPasswordHandler: failure in DefaultCommandHandler\n");
/* post status if password dialog was invoked from the SecurityAdvisor */
if (SSM_IsA(req->target, SSM_RESTYPE_SECADVISOR_CONTEXT))
SSMControlConnection_SendUIEvent(req->ctrlconn, "get",
"show_followup", NULL,
result,
&((SSMResource *)req->ctrlconn)->m_clientContext);
PR_FREEIF(responseKey);
done:
if (req->target && req->target->m_UILock)
SSM_NotifyUIEvent(req->target);
return rv;
}
SSMStatus SSM_ShowFollowupKeywordHandler(SSMTextGenContext * cx)
{
char * resultvalue;
SSMStatus rv;
PR_ASSERT(cx != NULL);
PR_ASSERT(cx->m_request != NULL);
PR_ASSERT(cx->m_result != NULL);
rv = SSM_HTTPParamValue(cx->m_request, "result", &resultvalue);
if (rv != SSM_SUCCESS || !resultvalue)
goto loser;
if (!strcmp(resultvalue, "password_success"))
rv = SSM_GetAndExpandTextKeyedByString(cx, "set_password_success",
&cx->m_result);
else if (!strcmp(resultvalue,"password_failure"))
rv = SSM_GetAndExpandTextKeyedByString(cx, "set_password_failure",
&cx->m_result);
else if (!strcmp(resultvalue, "no_ldap_setup"))
rv = SSM_GetAndExpandTextKeyedByString(cx, "no_ldap_server_set",
&cx->m_result);
loser:
return rv;
}
SSMStatus SSM_SetUserPassword(PK11SlotInfo * slot, SSMResource * ct)
{
SSMStatus rv;
char * params = PR_smprintf("slot=%s&mechanism=%d",
PK11_GetTokenName(slot),
CKM_INVALID_MECHANISM);
SSM_LockUIEvent(ct);
rv = SSMControlConnection_SendUIEvent(ct->m_connection,
"get", "set_password",
ct, params,
&ct->m_clientContext);
if (rv != SSM_SUCCESS)
goto loser;
SSM_WaitUIEvent(ct, PR_INTERVAL_NO_TIMEOUT);
return rv;
loser:
SSM_UnlockUIEvent(ct);
return rv;
}
SSMStatus SSM_ProcessPasswordWindow(HTTPRequest * req)
{
SSMStatus rv = SSM_FAILURE;
SSMResource * target = NULL;
if (!req || !req->ctrlconn)
goto loser;
/*
* The window contents aren't going to change, so just send back
* a NO_CONTENT error which causes leave its content as is.
*/
rv = SSM_HTTPReportError(req, HTTP_NO_CONTENT);
target = (req->target ? req->target : (SSMResource *) req->ctrlconn);
/* send UI event to bring up the dialog */
SSM_LockUIEvent(&req->ctrlconn->super.super);
rv = SSMControlConnection_SendUIEvent(req->ctrlconn, "get",
"set_password", target,
"slot=all&mech=1",
&target->m_clientContext);
if (rv != SSM_SUCCESS) {
SSM_UnlockUIEvent(&req->ctrlconn->super.super);
goto loser;
}
SSM_WaitUIEvent(&req->ctrlconn->super.super, PR_INTERVAL_NO_TIMEOUT);
loser:
return rv;
}

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

@ -0,0 +1,961 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 "pkcs11ui.h"
#include "pkcs11.h"
#include "pk11func.h"
#include "plstr.h"
#include "secmod.h"
#include "secmodti.h"
#include "minihttp.h"
#include "textgen.h"
/* Utility */
PK11SlotInfo *
SSMPKCS11_FindSlotByID(SECMODModuleID modID,
CK_SLOT_ID slotID)
{
SECMODModule *mod = NULL;
PRIntn i;
mod = SECMOD_FindModuleByID(modID);
if (mod)
{
for(i=0;i<mod->slotCount;i++)
{
if (mod->slots[i]->slotID == slotID)
return mod->slots[i];
}
}
return NULL;
}
/*
---------------------------------------------------------
PKCS11 module processing (list, add, delete)
---------------------------------------------------------
*/
SSMStatus
ssmpkcs11_convert_module(SSMTextGenContext *cx,
PRInt32 modIndex,
SECMODModule *mod,
char *fmt)
{
char *dllName = NULL;
char *tempStr = NULL;
char *lib_ch = NULL;
CK_INFO modInfo;
SSMStatus rv = SSM_FAILURE;
SECStatus srv;
/* 65? Why 65??? It's what's was used in the original UI. */
char buf[65];
char buf2[65];
srv = PK11_GetModInfo(mod, &modInfo);
if (srv != SECSuccess)
goto loser;
/* we provide the space in (buf), so we don't deallocate lib_ch */
lib_ch = PK11_MakeString(NULL,buf2,(char *)modInfo.libraryDescription,
sizeof(modInfo.libraryDescription));
if (mod->dllName)
{
char *cursor, *newString;
int numSlashes = 0, newLen, i, j, oldLen;
dllName = mod->dllName;
/*
* Now we need to escape the '\' characters so the string shows
* up correctly in the UI.
*/
/* First count them to see if we even need to re-allocate*/
cursor = dllName;
while ((cursor = PL_strchr(cursor, '\\')) != NULL) {
numSlashes++;
cursor++;
}
if (numSlashes > 0) {
oldLen = PL_strlen(dllName);
newLen = oldLen + numSlashes + 1;
newString = SSM_NEW_ARRAY(char, newLen);
/*
* If we can't allocate a new buffer, then let's just display
* the original string. That's better than not displaying
* anything.
*/
if (newString != NULL) {
for (i=0, j=0; i<oldLen+1; i++,j++){
newString[j] = dllName[i];
if (newString[j] == '\\'){
newString[j+1] = '\\';
j++;
}
}
dllName = newString;
}
}
}
else
{
rv = SSM_GetAndExpandText(cx, "text_pk11_no_dll", &dllName);
if (rv != SSM_SUCCESS)
goto loser;
}
PR_snprintf(buf, sizeof(buf), "%d.%d",
modInfo.libraryVersion.major, modInfo.libraryVersion.minor);
tempStr = PR_smprintf(fmt, modIndex, (long)mod->moduleID, lib_ch,
mod->commonName, dllName, buf);
if (tempStr == NULL) {
rv = SSM_FAILURE;
goto loser;
}
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
loser:
if (dllName && dllName != mod->dllName)
PR_Free(dllName);
PR_FREEIF (tempStr);
return rv;
}
/*
PKCS11 module list keyword handler.
Syntax: {_pk11modules <wrapper_key>}
*/
SSMStatus
SSM_PKCS11ModulesKeywordHandler(SSMTextGenContext *cx)
{
SSMStatus rv = SSM_SUCCESS;
char *wrapperKey = NULL;
char *wrapperStr = NULL;
SECMODModuleList *modList = SECMOD_GetDefaultModuleList();
SECMODModuleList *modWalk = NULL;
SECMODListLock *modLock = SECMOD_GetDefaultModuleListLock();
PRBool gotLock = PR_FALSE; /* indicates whether we should release at end */
PRInt32 i=0;
/* 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 = PR_INVALID_ARGUMENT_ERROR;
goto real_loser; /* really bail here */
}
if (SSM_Count(cx->m_params) != 1)
{
SSM_HTTPReportSpecificError(cx->m_request, "_certList: "
"Incorrect number of parameters "
"(%d supplied, 1 needed).\n",
SSM_Count(cx->m_params));
goto user_loser;
}
/* Convert parameters to something we can use in finding certs. */
wrapperKey = (char *) SSM_At(cx->m_params, 0);
PR_ASSERT(wrapperKey);
/* Get the wrapper text. */
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapperStr);
if (rv != SSM_SUCCESS)
goto real_loser; /* error string set by the called function */
/* Iterate over the PKCS11 modules. Put relevant info from each
into its own copy of the wrapper text. */
SECMOD_GetReadLock(modLock);
gotLock = PR_TRUE;
modWalk = modList;
while (modWalk)
{
rv = ssmpkcs11_convert_module(cx, i++, modWalk->module, wrapperStr);
modWalk = modWalk->next;
}
goto done;
user_loser:
/* If we reach this point, something in the input is wrong, but we
can still send something back to the client to indicate that a
problem has occurred. */
/* If we can't do what we're about to do, really bail. */
if (!cx->m_request || !cx->m_request->errormsg)
goto real_loser;
/* Clear the string we were accumulating. */
SSMTextGen_UTF8StringClear(&cx->m_result);
/* Use the result string given to us to explain what happened. */
SSM_ConcatenateUTF8String(&cx->m_result, cx->m_request->errormsg);
/* Clear the result string, since we're sending this inline */
SSMTextGen_UTF8StringClear(&cx->m_request->errormsg);
goto done;
real_loser:
/* If we reach this point, then we are so screwed that we cannot
send anything vaguely normal back to the client. Bail. */
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
PR_FREEIF(wrapperStr);
if (modLock && gotLock)
SECMOD_ReleaseReadLock(modLock);
return rv;
}
/*
---------------------------------------------------------
PKCS11 slot code
---------------------------------------------------------
*/
enum
{
SSM_PK11STR_SLOT_LOGGED_IN = (long) 0,
SSM_PK11STR_SLOT_NOT_LOGGED_IN,
SSM_PK11STR_SLOT_NO_LOGIN_REQUIRED,
SSM_PK11STR_SLOT_NOT_PRESENT,
SSM_PK11STR_SLOT_UNINITIALIZED,
SSM_PK11STR_SLOT_DISABLED,
SSM_PK11STR_SLOT_READY,
SSM_PK11STR_SLOT_STRING_COUNT
};
static char *slotStringKeys[] =
{
"text_pk11_slot_logged_in",
"text_pk11_slot_not_logged_in",
"text_pk11_slot_no_login_required",
"text_pk11_slot_not_present",
"text_pk11_slot_uninitialized",
"text_pk11_slot_disabled",
"text_pk11_slot_ready"
};
static char **slotStrings = NULL;
void
ssmpkcs11_initialize_slot_labels(SSMTextGenContext *cx)
{
SSMStatus rv = SSM_SUCCESS;
PRIntn i;
slotStrings = (char **) PR_Calloc(SSM_PK11STR_SLOT_STRING_COUNT + 1,
sizeof(char**));
PR_ASSERT(slotStrings);
for(i=0;i<SSM_PK11STR_SLOT_STRING_COUNT;i++)
{
rv = SSM_FindUTF8StringInBundles(cx, slotStringKeys[i],
&slotStrings[i]);
PR_ASSERT(rv == SSM_SUCCESS);
}
}
SSMStatus
ssmpkcs11_convert_slot(SSMTextGenContext *cx,
PRInt32 slotIndex,
PK11SlotInfo *slot,
char *fmt,
PRBool accumulate) /* accumulate in cx->m_result? */
{
char *name = NULL;
char *statusStr = NULL;
char *serial = NULL;
char *version = NULL;
char *tempStr = NULL;
long status, slotID = 0, moduleID = 0;
CK_TOKEN_INFO tokenInfo;
SSMStatus rv = SSM_FAILURE;
SECStatus srv = SECSuccess;
/* 65? Why 65??? It's what's was used in the original UI. */
char buf[65];
char empty[1] = { '\0' } ;
if (!slotStrings)
ssmpkcs11_initialize_slot_labels(cx);
/* If we have a NULL slot, return blank information. */
if (!slot)
{
name = empty;
statusStr = empty;
serial = empty;
version = empty;
slotID = 0;
goto show_stuff;
}
/* Get the slot name. Either the default name or the name of the token
in the slot will be used. */
if (PK11_IsPresent(slot))
name = PK11_GetTokenName(slot);
else
name = PK11_GetSlotName(slot);
/* Report the status of the slot. */
if (PK11_IsDisabled(slot))
status = SSM_PK11STR_SLOT_DISABLED;
else if (!PK11_IsPresent(slot))
status = SSM_PK11STR_SLOT_NOT_PRESENT;
else if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot))
status = SSM_PK11STR_SLOT_UNINITIALIZED;
else if (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))
status = SSM_PK11STR_SLOT_NOT_LOGGED_IN;
else if (PK11_NeedLogin(slot))
status = SSM_PK11STR_SLOT_LOGGED_IN;
else
status = SSM_PK11STR_SLOT_READY;
statusStr = slotStrings[status];
/* Get the serial number and version. */
/* This is how the old UI determines if there's a token in, so... */
if (PK11_IsPresent(slot))
srv = PK11_GetTokenInfo(slot, &tokenInfo);
if (PK11_IsPresent(slot) && (srv == SECSuccess))
{
/* Get serial number and version from the token info. */
serial = PK11_MakeString(NULL, NULL, (char*)tokenInfo.serialNumber,
sizeof(tokenInfo.serialNumber));
PR_snprintf(buf, sizeof(buf), "%d.%d",
tokenInfo.firmwareVersion.major,
tokenInfo.firmwareVersion.minor);
version = buf;
}
else
{
/* Get serial number and version from the slot info. */
CK_SLOT_INFO slotInfo;
srv = PK11_GetSlotInfo(slot, &slotInfo);
if (srv != SECSuccess)
goto loser;
serial = empty;
PR_snprintf(buf, sizeof(buf), "%d.%d",
slotInfo.firmwareVersion.major,
slotInfo.firmwareVersion.minor);
version = buf;
}
slotID = (long) (slot->slotID);
moduleID = (long) (slot->module->moduleID);
show_stuff:
tempStr = PR_smprintf(fmt, slotIndex, slotID, moduleID, name,
statusStr, serial, version);
if (accumulate)
{
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
}
else
rv = SSM_HTTPSendUTF8String(cx->m_request, tempStr);
loser:
/* The data that isn't freed is either because it's a member of the
* data in a structure of the PK11 libraries or its a static local
* variable.
*/
if (serial && serial != empty)
PR_Free(serial);
PR_FREEIF(tempStr);
return rv;
}
/*
PKCS11 slot list keyword handler.
Syntax: {_pk11slots <moduleID>,<wrapper_key>}
*/
SSMStatus
SSM_PKCS11SlotsKeywordHandler(SSMTextGenContext *cx)
{
SSMStatus rv = SSM_SUCCESS;
SECMODModule *module = NULL;
char *wrapperKey = NULL;
char *moduleIDStr = NULL;
long moduleID;
char *wrapperStr = NULL;
PRInt32 i=0;
/* 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 = PR_INVALID_ARGUMENT_ERROR;
goto real_loser; /* really bail here */
}
if (SSM_Count(cx->m_params) != 2)
{
SSM_HTTPReportSpecificError(cx->m_request, "_certList: "
"Incorrect number of parameters "
"(%d supplied, 2 needed).\n",
SSM_Count(cx->m_params));
goto user_loser;
}
/* Convert parameters to something we can use in finding certs. */
moduleIDStr = (char *) SSM_At(cx->m_params, 0);
PR_ASSERT(moduleIDStr);
wrapperKey = (char *) SSM_At(cx->m_params, 1);
PR_ASSERT(wrapperKey);
/* Find the module we're looking for based on the module ID. */
module = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
if (!module)
goto user_loser;
/* Get the wrapper text. */
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapperStr);
if (rv != SSM_SUCCESS)
goto real_loser; /* error string set by the called function */
/* Iterate over the slots from this module. Put relevant info from each
into its own copy of the wrapper text. */
for(i=0;i<module->slotCount;i++)
{
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], wrapperStr,
PR_TRUE);
if (rv != SSM_SUCCESS)
goto user_loser;
}
goto done;
user_loser:
/* If we reach this point, something in the input is wrong, but we
can still send something back to the client to indicate that a
problem has occurred. */
/* If we can't do what we're about to do, really bail. */
if (!cx->m_request || !cx->m_request->errormsg)
goto real_loser;
/* Clear the string we were accumulating. */
SSMTextGen_UTF8StringClear(&cx->m_result);
/* Use the result string given to us to explain what happened. */
SSM_ConcatenateUTF8String(&cx->m_result, cx->m_request->errormsg);
/* Clear the result string, since we're sending this inline */
SSMTextGen_UTF8StringClear(&cx->m_request->errormsg);
goto done;
real_loser:
/* If we reach this point, then we are so screwed that we cannot
send anything vaguely normal back to the client. Bail. */
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
PR_FREEIF(wrapperStr);
if (module)
SECMOD_DestroyModule(module);
return rv;
}
SSMStatus
ssm_pkcs11_chuck_property(SSMTextGenContext *cx, char *propName)
{
char *text = NULL;
SSMStatus rv;
rv = SSM_GetAndExpandText(cx, propName, &text);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPSendUTF8String(cx->m_request, text);
loser:
PR_FREEIF(text);
SSMTextGen_UTF8StringClear(&cx->m_result);
return rv;
}
/* PKCS11ShowSlots?module=<moduleID> */
SSMStatus
SSM_ShowSlotsCommandHandler(HTTPRequest *req)
{
SSMTextGenContext *cx = NULL;
char *tmpl = NULL, *type = NULL;
char *nomod_ch = NULL;
char *modID_ch = NULL;
long moduleID;
SECMODModule *module = NULL;
PRIntn i;
SSMStatus rv;
/* If we have a "no_module" parameter, then there
is no module for which to load slots. */
rv = SSM_HTTPParamValue(req, "no_module", &nomod_ch);
if (rv == SSM_SUCCESS)
goto display_stuff;
rv = SSM_HTTPParamValue(req, "module", &modID_ch);
if (rv != SSM_SUCCESS)
goto display_stuff;
if (modID_ch)
{
/* Convert the module ID into a real module ID. */
PR_sscanf(modID_ch, "%ld", &moduleID);
/* Find the module we're looking for based on the module ID. */
module = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
if (!module)
goto loser;
}
display_stuff:
/* Make a new top-level text gen context to chuck text back. */
rv = SSMTextGen_NewTopLevelContext(req, &cx);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_type", &type);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPSendOKHeader(req, NULL, type);
if (rv != SSM_SUCCESS)
goto loser;
/* Chuck out part 1. */
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part1");
if (rv != SSM_SUCCESS)
goto loser;
/* Get the template for the JS slot list. */
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_js_template", &tmpl);
if (rv != SSM_SUCCESS)
goto loser;
/* Iterate over the slots from this module. Put relevant info from each
into its own copy of the wrapper text. */
if (module)
{
for(i=0;i<module->slotCount;i++)
{
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], tmpl,
PR_FALSE);
if (rv != SSM_SUCCESS)
goto loser;
}
}
PR_Free(tmpl);
tmpl = NULL;
/* Chuck out part 2. */
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part2");
if (rv != SSM_SUCCESS)
goto loser;
/* Get the template for the selectable slot list. */
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_select_template", &tmpl);
if (rv != SSM_SUCCESS)
goto loser;
/* Iterate over the slots from this module. Put relevant info from each
into its own copy of the wrapper text. */
if (module)
{
for(i=0;i<module->slotCount;i++)
{
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], tmpl,
PR_FALSE);
if (rv != SSM_SUCCESS)
goto loser;
}
}
/* Chuck out part 3. */
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part3");
req->sentResponse = PR_TRUE;
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
if (cx)
SSMTextGen_DestroyContext(cx);
PR_FREEIF(tmpl);
return rv;
}
SSMStatus
ssm_find_module_from_request(HTTPRequest *req, SECMODModule **mod)
{
char *modID_ch = NULL;
PRInt32 moduleID;
SSMStatus rv;
rv = SSM_HTTPParamValue(req, "module", &modID_ch);
if (rv != SSM_SUCCESS)
goto done;
if (modID_ch)
{
/* Convert the module ID into a real module ID. */
PR_sscanf(modID_ch, "%ld", &moduleID);
/* Find the module we're looking for based on the module ID. */
*mod = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
}
done:
if ((!*mod) && (rv == SSM_SUCCESS))
rv = SSM_FAILURE;
return rv;
}
PK11SlotInfo *
find_slot_by_ID(SECMODModule *mod, CK_SLOT_ID slotID)
{
int i;
PK11SlotInfo *slot;
for (i=0; i < mod->slotCount; i++) {
slot = mod->slots[i];
if (slot->slotID == (CK_SLOT_ID) slotID)
return PK11_ReferenceSlot(slot);
}
return NULL;
}
SSMStatus
ssm_find_slot_from_request(HTTPRequest *req, PK11SlotInfo **slot)
{
char *slotID_ch = NULL;
PRInt32 slotID;
SECMODModule *mod;
SSMStatus rv = SSM_SUCCESS;
rv = ssm_find_module_from_request(req, &mod);
if (rv != SSM_SUCCESS)
goto done;
rv = SSM_HTTPParamValue(req, "slot", &slotID_ch);
if (rv != SSM_SUCCESS)
goto done;
if (slotID_ch)
{
/* Convert the module ID into a real module ID. */
PR_sscanf(slotID_ch, "%ld", &slotID);
/* Find the module we're looking for based on the module ID. */
*slot = find_slot_by_ID(mod, (CK_SLOT_ID) slotID);
}
done:
if ((!*slot) && (rv == SSM_SUCCESS))
rv = SSM_FAILURE;
return rv;
}
SSMStatus
ssmpkcs11_show_slot_info(HTTPRequest *req, PK11SlotInfo *slot)
{
char *wrapperStr = NULL;
char *tmpl = NULL;
char *type = NULL;
SSMTextGenContext *cx;
SSMStatus rv;
/* Make a new top-level text gen context to chuck text back. */
rv = SSMTextGen_NewTopLevelContext(req, &cx);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_GetAndExpandText(cx, "adv_modules_slot_info_type", &type);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPSendOKHeader(req, NULL, type);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_GetAndExpandText(cx, "adv_modules_slot_info_content", &wrapperStr);
if (rv != SSM_SUCCESS)
goto loser; /* error string set by the called function */
rv = ssmpkcs11_convert_slot(cx, 0, slot, wrapperStr, PR_FALSE);
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
if (cx)
SSMTextGen_DestroyContext(cx);
PR_FREEIF(tmpl);
PR_FREEIF(type);
PR_FREEIF(wrapperStr);
return rv;
}
SSMStatus
SSM_ShowSlotCommandHandler(HTTPRequest *req)
{
SSMStatus rv;
PK11SlotInfo *slot;
/* Find the slot. */
rv = ssm_find_slot_from_request(req, &slot);
if (rv != SSM_SUCCESS)
goto loser;
/* Display the slot info. */
rv = ssmpkcs11_show_slot_info(req, slot);
req->sentResponse = PR_TRUE;
loser:
if (slot)
PK11_FreeSlot(slot);
return rv;
}
SSMStatus
SSM_LoginSlotCommandHandler(HTTPRequest *req)
{
SSMStatus rv;
PK11SlotInfo *slot;
/* Find the slot. */
rv = ssm_find_slot_from_request(req, &slot);
if (rv != SSM_SUCCESS)
goto loser;
/* Log into the slot. */
PK11_Authenticate(slot, PR_TRUE, req->ctrlconn);
/* Display the slot info. */
rv = ssmpkcs11_show_slot_info(req, slot);
req->sentResponse = PR_TRUE;
loser:
if (slot)
PK11_FreeSlot(slot);
return rv;
}
SSMStatus
SSM_LogoutSlotCommandHandler(HTTPRequest *req)
{
SSMStatus rv;
PK11SlotInfo *slot;
/* Find the slot. */
rv = ssm_find_slot_from_request(req, &slot);
if (rv != SSM_SUCCESS)
goto loser;
/* Log out of the slot. */
PK11_Logout(slot);
/* Display the slot info. */
rv = ssmpkcs11_show_slot_info(req, slot);
req->sentResponse = PR_TRUE;
loser:
if (slot)
PK11_FreeSlot(slot);
return rv;
}
SSMStatus
SSM_LogoutAllSlotsCommandHandler(HTTPRequest *req)
{
SSMStatus rv;
PK11SlotInfo *slot;
/* Find the slot. */
rv = ssm_find_slot_from_request(req, &slot);
/* Not relevant if we find the slot here,
just remember to display (or not) whatever slot we have */
if (rv != SSM_SUCCESS)
slot = NULL;
/* Log out of all slots. */
PK11_LogoutAll();
/* Display the slot info (if any). */
rv = ssmpkcs11_show_slot_info(req, slot);
req->sentResponse = PR_TRUE;
if (slot)
PK11_FreeSlot(slot);
return rv;
}
/*
---------------------------------------------------------
FIPS mode code
---------------------------------------------------------
*/
/*
FIPS mode keyword handler.
Syntax: {_fipsmode <true_text>,<false_text>}
where <true_text> is displayed if FIPS mode is on, <false_text> otherwise.
*/
SSMStatus
SSM_PKCS11FIPSModeKeywordHandler(SSMTextGenContext *cx)
{
SSMStatus rv = SSM_SUCCESS;
char *param = NULL;
char *tempStr = NULL;
PR_ASSERT(cx);
PR_ASSERT(cx->m_params);
PR_ASSERT(cx->m_result);
if (!cx || !cx->m_params || !cx->m_result)
{
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
/* Figure out if we're in FIPS mode. */
if (PK11_IsFIPS())
param = (char *) SSM_At(cx->m_params, 0);
else
param = (char *) SSM_At(cx->m_params, 1);
/* Display the appropriate string. */
rv = SSMTextGen_SubstituteString(cx, param, &tempStr);
if (rv != SSM_SUCCESS)
goto loser; /* error string set by the called function */
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
if (rv == SSM_SUCCESS)
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
PR_FREEIF(tempStr);
return rv;
}
void
SSM_TrimTrailingWhitespace(char *str)
{
char *end = &(str[strlen(str)]);
char *start = str;
do
{
end--;
}
while ((end >= start) &&
((*end == ' ') || (*end == '\0')));
*(++end) = '\0';
}
/*
Command handler to set FIPS mode.
Syntax: setFIPSMode?fips={on|off}&baseRef=<baseRef>&target=<ctrlconn>
*/
SSMStatus
SSM_SetFIPSModeCommandHandler(HTTPRequest *req)
{
char *fips_ch = NULL, *baseRef_ch = NULL;
SECStatus srv = SECSuccess;
PRBool oldFIPS, newFIPS;
SSMStatus rv = SSM_SUCCESS;
rv = SSM_HTTPParamValue(req, "fips", &fips_ch);
if (rv != SSM_SUCCESS)
goto loser;
newFIPS = !PL_strncmp(fips_ch, "on", 2);
oldFIPS = PK11_IsFIPS();
if (newFIPS != oldFIPS)
{
/*
Turning FIPS mode on/off requires the exact same operation:
deleting the built-in PKCS11 module.
### mwelch We need these calls to differentiate between
secmod dbs!
*/
SECMODModule *internal;
CK_INFO modInfo;
internal = SECMOD_GetInternalModule();
if (!internal)
goto loser;
srv = PK11_GetModInfo(internal, &modInfo);
if (srv != SECSuccess)
goto loser;
SSM_TrimTrailingWhitespace((char*) modInfo.libraryDescription);
/* Delete the {FIPS,non-FIPS} internal module, so that
it will be replaced by the {non-FIPS,FIPS} counterpart. */
srv = SECMOD_DeleteInternalModule(internal->commonName);
if (srv != SECSuccess)
goto loser;
}
/* if there's a baseRef, send it back. otherwise, no content. */
rv = SSM_HTTPParamValue(req, "baseRef", &baseRef_ch);
if (rv == SSM_SUCCESS)
{
/* send what was requested */
rv = SSM_HTTPCloseAndSleep(req);
}
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
SSM_HTTPReportSpecificError(req, "SetFIPSModeCommandHandler: Error %d "
"attempting to change FIPS mode.",
srv != SECSuccess ? srv : rv);
done:
return rv;
}

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

1234
security/psm/server/prefs.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

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

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

179
security/psm/server/serv.h Normal file
Просмотреть файл

@ -0,0 +1,179 @@
/*
* 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.
*/
#ifndef __SERV_H__
#define __SERV_H__
#include "prio.h"
#include "prtypes.h"
#include "prnetdb.h"
#include "prprf.h"
#include "prinit.h"
#include "prthread.h"
#include "prinrval.h"
#include "prmon.h"
#include "prmem.h"
#include "prerror.h"
#include <stdlib.h>
#include "seccomon.h"
#include "ssmdefs.h"
#include "servimpl.h"
#include "protocol.h"
#include "ssmerrs.h"
/* extern int errno; */
#undef ALLOW_STANDALONE
#ifdef ALLOW_STANDALONE
extern PRBool standalone;
#define SSM_ENV_STANDALONE "NSM_STANDALONE"
#endif
/* Environment variables we pay attention to */
#ifdef DEBUG
#define SSM_ENV_SUPPRESS_CONSOLE "NSM_SUPPRESS_CONSOLE"
#define SSM_ENV_LOG_FILE "NSM_LOG_FILE"
/* Password must be base64 encoded. */
#define SSM_ENV_STATIC_PASSWORD "NSM_PASSWORD"
#endif
#define MAX_CONNECTIONS 5
#define LINESIZE 512
#define DATA_CONN_MSG_SIZE sizeof(PRFileDesc *)
#define CARTMAN_WAIT_BEFORE_SLEEP (PR_TicksPerSecond() * 60)
#define CARTMAN_SPINTIME CARTMAN_WAIT_BEFORE_SLEEP
#define CARTMAN_KEEP_CONNECTION_ALIVE (CARTMAN_WAIT_BEFORE_SLEEP * 900)
/* Some macros to cut down typing when doing memory allocation.*/
#define SSM_NEW PR_NEW
#define SSM_ZNEW PR_NEWZAP
#define SSM_NEW_ARRAY(type,size) (type*)PR_Malloc((size)*sizeof(type))
#define SSM_ZNEW_ARRAY(type,size) (type*)PR_Calloc((size),sizeof(type))
/* Safe strcmp() which compares only based on the shorter
of the two lengths. DO NOT USE if you really want to determine
string equality -- this is used for sloppy parameter matches. */
#define MIN_STRCMP(x,y) strncmp((x), (y), MIN(strlen(x),strlen(y)))
/* forward declare this type to eliminate circular dependencies */
typedef struct SSMResource SSMResource;
typedef struct SSMControlConnection SSMControlConnection;
extern PRUint32 httpPort;
PRIntn mainLoop(PRIntn argc, char ** argv);
PRFileDesc * SSM_OpenControlPort(void);
PRFileDesc * SSM_OpenPort(void);
PRBool SSM_SocketPeerCheck(PRFileDesc *sock, PRBool isCtrl);
SSMPolicyType SSM_GetPolicy(void);
#define THREAD_NAME_LEN 128
SSMStatus SSM_AddLogSocket(PRFileDesc *sock);
void SSM_DebugP(char *fmt, ...);
#if defined(WIN32)
#define STRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
#elif defined(XP_UNIX)
#define STRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
#else
/* Should really figure out how this platform does this */
int SSM_strncasecmp(const char *s1, const char *s2, size_t count);
#define STRNCASECMP(s1,s2,n) SSM_strncasecmp((s1),(s2),(n))
#endif
#ifdef DEBUG
#define SSM_DEBUG SSM_DebugP
#else
#define SSM_DEBUG if(0) SSM_DebugP
#endif
void SSM_DumpBuffer(char *buf, PRIntn len);
SECItem * SSM_ConstructMessage(PRUintn size);
void SSM_FreeEvent(SECItem * event);
void SSM_FreeResponse(SSMResponse * response);
void SSM_FreeMessage(SECItem * msg);
int ssm_ReadThisMany(PRFileDesc * sockID, void * buffer, int thisMany);
int ssm_WriteThisMany(PRFileDesc * sockID, void * buffer, int thisMany);
/* Macros used in http and base64 processing */
#undef IS_EOL
#define IS_EOL(c) (((c) == 0x0A) || ((c) == 0x0D))
#undef IS_WHITESPACE
#define IS_WHITESPACE(c) (((c) == '\t') || ((c) == '\n') \
|| ((c) == '\r') || ((c) == ' '))
extern SSMPolicyType policyType;
SSMStatus SSM_CloseSocketWithLinger(PRFileDesc *sock);
SSMStatus SSM_RequestFilePathFromUser(SSMResource *res,
const char *promptKey,
const char *fileRegEx,
PRBool getExistingFile);
char* SSM_GetCharFromKey(const char *key, const char *locale);
void SSM_HandleFilePathReply(SSMControlConnection *ctrl,
SECItem *msg);
void SSM_HandleUserPromptReply(SSMControlConnection *ctrl,
SECItem *msg);
char * SSM_ConvertStringToHTMLString(char * string);
SSMStatus SSM_CopyCMTItem(CMTItem *dest, CMTItem *source);
#ifdef XP_UNIX
void SSM_ReleaseLockFile();
#endif /*XP_UNIX*/
/* Function used on Mac to register threads for later destruction at app quit time. */
#ifdef XP_MAC
PRThread * SSM_CreateAndRegisterThread(PRThreadType type,
void (*start)(void *arg),
void *arg,
PRThreadPriority priority,
PRThreadScope scope,
PRThreadState state,
PRUint32 stackSize);
void SSM_KillAllThreads(void);
#else
#define SSM_CreateAndRegisterThread PR_CreateThread
#endif
#endif

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

@ -0,0 +1,83 @@
/*
* 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.
*/
#ifndef __SERVIMPL_H__
#define __SERVIMPL_H__
#include "ssmdefs.h"
#include "collectn.h"
#include "hashtbl.h"
/* Doc subdirectory */
#ifdef XP_UNIX
#define PSM_DOC_DIR "./doc/"
#else
#ifdef XP_MAC
#define PSM_DOC_DIR ":doc:"
#else
#define PSM_DOC_DIR ".\\doc\\"
#endif
#endif
/* Messages passed between data service threads */
typedef enum
{
SSM_DATA_BUFFER = (PRIntn) 0, /* "Here's data to write" */
SSM_DATA_PROVIDER_OPEN, /* "My end is open, about to queue data" */
SSM_DATA_PROVIDER_SHUTDOWN /* "My socket has closed" */
} SSMDataMessageType;
typedef struct _SSMResponse SSMResponse;
typedef struct _SSMResponseQueue SSMResponseQueue;
void SSM_InitNLS(char *dataDirectory);
SECItem * SSM_ConstructMessage(PRUintn size);
void SSM_FreeEvent(SECItem * event);
void SSM_FreeResponse(SSMResponse * response);
void SSM_FreeMessage(SECItem * msg);
int SSM_ReadThisMany(PRFileDesc * sockID, void * buffer, int thisMany);
int SSM_WriteThisMany(PRFileDesc * sockID, void * buffer, int thisMany);
SSMStatus SSM_SendQMessage(SSMCollection *c,
PRIntn priority,
PRIntn type, PRIntn length, char *data,
PRBool doBlock);
SSMStatus SSM_RecvQMessage(SSMCollection *c,
PRIntn priority,
PRIntn *type, PRIntn *length, char **data,
PRBool doBlock);
void ssm_DrainAndDestroyQueue(SSMCollection **coll);
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,584 @@
/*
* 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 "serv.h"
#include "minihttp.h"
#include "signtextres.h"
#include "protocolf.h"
#include "base64.h"
#include "secmime.h"
#include "newproto.h"
#include "messages.h"
#include "certres.h"
#define SSMRESOURCE(object) (&(object)->super)
SSMStatus
SSM_CreateSignTextRequest(SECItem *msg, SSMControlConnection *conn)
{
SSMStatus rv;
SSMSignTextResource *signTextRes = NULL;
int i;
SignTextRequest request;
/* Decode the sign text protocol message */
if (CMT_DecodeMessage(SignTextRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
goto loser;
}
/* Get the resource */
rv = SSMControlConnection_GetResource(conn, (SSMResourceID)request.resID,
(SSMResource**)&signTextRes);
if ((rv != PR_SUCCESS) || (signTextRes == NULL)) {
goto loser;
}
/* Get a reference to it */
SSM_GetResourceReference(SSMRESOURCE(signTextRes));
if (!SSM_IsAKindOf(SSMRESOURCE(signTextRes), SSM_RESTYPE_SIGNTEXT)) {
goto loser;
}
/* Set the request data */
signTextRes->m_stringToSign = PL_strdup(request.stringToSign);
signTextRes->m_hostName = PL_strdup(request.hostName);
if (PL_strcasecmp(request.caOption, "auto") == 0) {
signTextRes->m_autoFlag = PR_TRUE;
} else if (PL_strcasecmp(request.caOption, "ask") == 0) {
signTextRes->m_autoFlag = PR_FALSE;
} else {
goto loser;
}
signTextRes->m_numCAs = request.numCAs;
if (signTextRes->m_numCAs > 0) {
signTextRes->m_caNames = (char **) PR_CALLOC(sizeof(char*)*(signTextRes->m_numCAs));
if (!signTextRes->m_caNames) {
goto loser;
}
for (i=0;i<signTextRes->m_numCAs;i++) {
signTextRes->m_caNames[i] = PL_strdup(request.caNames[i]);
}
}
signTextRes->m_conn = conn;
signTextRes->m_action = SIGN_TEXT_WAITING;
signTextRes->m_thread = SSM_CreateAndRegisterThread(PR_USER_THREAD,
SSMSignTextResource_ServiceThread,
(void*)signTextRes,
PR_PRIORITY_NORMAL,
PR_LOCAL_THREAD,
PR_UNJOINABLE_THREAD, 0);
if (!signTextRes->m_thread) {
goto loser;
}
return PR_SUCCESS;
loser:
/* XXX Free request */
return PR_FAILURE;
}
SSMStatus
SSMSignTextResource_Create(void *arg, SSMControlConnection * conn, SSMResource **res)
{
SSMSignTextResource *signTextRes;
SSMStatus rv;
signTextRes = PR_NEWZAP(SSMSignTextResource);
if (!signTextRes) {
goto loser;
}
rv = SSMSignTextResource_Init(conn, signTextRes, SSM_RESTYPE_SIGNTEXT);
if (rv != PR_SUCCESS) {
goto loser;
}
*res = SSMRESOURCE(signTextRes);
return PR_SUCCESS;
loser:
if (signTextRes != NULL) {
SSM_FreeResource(SSMRESOURCE(signTextRes));
}
*res = NULL;
return PR_FAILURE;
}
SSMStatus
SSMSignTextResource_Init(SSMControlConnection *conn, SSMSignTextResource *in,
SSMResourceType type)
{
SSMStatus rv;
rv = SSMResource_Init(conn, SSMRESOURCE(in), type);
if (rv != PR_SUCCESS) {
goto loser;
}
/* Set all our data to zero */
in->m_stringToSign = NULL;
in->m_hostName = NULL;
in->m_autoFlag = PR_FALSE;
in->m_numCAs = 0;
in->m_caNames = NULL;
in->m_conn = conn;
in->m_thread = NULL;
in->m_certs = NULL;
in->m_action = SIGN_TEXT_INIT;
in->m_nickname = NULL;
in->m_resultString = NULL;
return PR_SUCCESS;
loser:
return PR_FAILURE;
}
SSMStatus SSMSignTextResource_Destroy(SSMResource *res, PRBool doFree)
{
SSMSignTextResource *signTextRes = (SSMSignTextResource*)res;
if (res == NULL) {
return PR_FAILURE;
}
PR_ASSERT(res->m_threadCount == 0);
/* Free our data */
/* Destroy the super class */
SSMResource_Destroy(res, PR_FALSE);
/* Free our memory */
if (doFree) {
PR_DELETE(signTextRes);
}
return PR_SUCCESS;
}
SSMStatus SSMSignTextResource_Shutdown(SSMResource *arg, SSMStatus status)
{
return PR_SUCCESS;
}
void
SSMSignTextResource_SendTaskCompletedEvent(SSMSignTextResource *res)
{
SECItem msg;
SSMStatus rv;
TaskCompletedEvent event;
/* Assemble the event. */
SSM_DEBUG("Sign Text Resource Task completed event: id %ld, status %d\n",
SSMRESOURCE(res)->m_id, SSMRESOURCE(res)->m_status);
event.resourceID = SSMRESOURCE(res)->m_id;
event.numTasks = 0;
event.result = SSMRESOURCE(res)->m_status;
if (CMT_EncodeMessage(TaskCompletedEventTemplate, (CMTItem*)&msg, &event) != CMTSuccess) {
return;
}
if (msg.data) {
/* Send the event to the control queue. */
rv = SSM_SendQMessage(SSMRESOURCE(res)->m_connection->m_controlOutQ,
SSM_PRIORITY_NORMAL,
SSM_EVENT_MESSAGE | SSM_TASK_COMPLETED_EVENT,
(int) msg.len, (char *) msg.data, PR_FALSE);
SSM_DEBUG("Sent message, rv = %d.\n", rv);
}
}
void
SSMSignTextResource_ServiceThread(void *arg)
{
SSMSignTextResource *signTextRes = (SSMSignTextResource*)arg;
SSMStatus rv;
unsigned char hashVal[SHA1_LENGTH];
SECItem digest, signedResult, *tmpItem;
SEC_PKCS7ContentInfo *ci = NULL;
CERTCertificate *cert = NULL;
CERTCertListNode *node;
int i,numCerts;
SSM_LockResource(SSMRESOURCE(signTextRes));
PR_ASSERT(signTextRes);
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(signTextRes), SSM_RESTYPE_SIGNTEXT));
memset(&signedResult, 0, sizeof(SECItem));
/* Get the certificates */
signTextRes->m_certs = CERT_MatchUserCert(signTextRes->m_conn->m_certdb,
certUsageEmailSigner,
signTextRes->m_numCAs,
signTextRes->m_caNames,
signTextRes->m_conn);
numCerts = SSM_CertListCount(signTextRes->m_certs);
if((signTextRes->m_certs == NULL) || (numCerts == 0)) {
signTextRes->m_resultString = strdup("error:noMatchingCert");
goto loser;
}
/* Send UI event to client */
if (signTextRes->m_autoFlag == PR_TRUE) {
rv = SSMControlConnection_SendUIEvent(signTextRes->m_conn, "get", "signtext_auto", SSMRESOURCE(signTextRes), NULL,
&SSMRESOURCE(signTextRes)->m_clientContext);
} else {
rv = SSMControlConnection_SendUIEvent(signTextRes->m_conn, "get", "signtext_ask", SSMRESOURCE(signTextRes), NULL,
&SSMRESOURCE(signTextRes)->m_clientContext);
}
if (rv != PR_SUCCESS) {
goto loser;
}
/* Here we wait for the user to confirm or deny the signing */
SSM_WaitResource(SSMRESOURCE(signTextRes), PR_INTERVAL_NO_TIMEOUT);
switch (SSMRESOURCE(signTextRes)->m_buttonType) {
case SSM_BUTTON_OK:
/* Get the signing cert */
node = (CERTCertListNode *)PR_LIST_HEAD(&signTextRes->m_certs->list);
if (signTextRes->m_nickname == NULL ) {
/* this is the "auto" case */
cert = node->cert;
} else {
/* this is the "ask" case */
for ( i = 0; i < numCerts; i++ ) {
if ( PL_strcasecmp(signTextRes->m_nickname, node->cert->nickname) == 0 ) {
cert = node->cert;
break;
}
node = (struct CERTCertListNodeStr *) node->links.next;
}
}
/* Hash the string to be signed */
rv = HASH_HashBuf(HASH_AlgSHA1, hashVal,
(unsigned char *) signTextRes->m_stringToSign,
strlen(signTextRes->m_stringToSign));
if (rv != SECSuccess) {
goto loser;
}
digest.len = SHA1_LENGTH;
digest.data = hashVal;
/* Sign the hash */
ci = SECMIME_CreateSigned(cert, cert, cert->dbhandle, SEC_OID_SHA1,
&digest, NULL, signTextRes->m_conn);
if (ci == NULL) {
goto loser;
}
/* Create the PKCS#7 object */
tmpItem = SEC_PKCS7EncodeItem(NULL, &signedResult, ci, NULL, NULL,
signTextRes->m_conn);
if (tmpItem != &signedResult) {
goto loser;
}
/* Convert the result to base 64 */
signTextRes->m_resultString = BTOA_DataToAscii(signedResult.data, signedResult.len);
if (signTextRes->m_resultString == NULL) {
goto loser;
}
break;
case SSM_BUTTON_CANCEL:
signTextRes->m_resultString= PL_strdup("error:userCancel");
break;
default:
break;
}
SSM_UnlockResource(SSMRESOURCE(signTextRes));
loser:
/* Free data */
if (signTextRes->m_stringToSign) {
PR_Free(signTextRes->m_stringToSign);
}
if (signTextRes->m_hostName) {
PR_Free(signTextRes->m_hostName);
}
if (signTextRes->m_certs) {
CERT_DestroyCertList(signTextRes->m_certs);
}
/* Send the task complete event here */
SSMSignTextResource_SendTaskCompletedEvent(signTextRes);
return;
}
SSMStatus
SSMSignTextResource_Print(SSMResource *res,
char *fmt,
PRIntn numParam,
char ** value,
char **resultStr)
{
char *hostName = NULL, *stringToSign = NULL;
SSMSignTextResource *signTextRes = (SSMSignTextResource*)res;
hostName = signTextRes->m_hostName;
stringToSign = signTextRes->m_stringToSign;
if (numParam)
SSMResource_Print(res, fmt, numParam, value, resultStr);
else if (signTextRes->m_autoFlag) {
CERTCertListNode *node;
CERTCertificate *cert;
/* Get the cert nickname */
node = (CERTCertListNode*)PR_LIST_HEAD(&signTextRes->m_certs->list);
cert = node->cert;
/* Get the nickname */
*resultStr = PR_smprintf(fmt, signTextRes->super.m_id, hostName,
stringToSign, cert->nickname);
} else {
*resultStr = PR_smprintf(fmt, signTextRes->super.m_id, hostName,
stringToSign);
}
return (*resultStr != NULL) ? PR_SUCCESS : PR_FAILURE;
}
SSMStatus
SSMSignTextResource_GetAttr(SSMResource *res, SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMSignTextResource *signTextRes = (SSMSignTextResource*)res;
if (!signTextRes || !signTextRes->m_resultString) {
goto loser;
}
switch (attrID) {
case SSM_FID_SIGNTEXT_RESULT:
if (!signTextRes->m_resultString) {
goto loser;
}
value->type = SSM_STRING_ATTRIBUTE;
value->u.string.len = PL_strlen(signTextRes->m_resultString);
value->u.string.data = (unsigned char *) PL_strdup(signTextRes->m_resultString);
break;
default:
goto loser;
}
return PR_SUCCESS;
loser:
return PR_FAILURE;
}
SSMStatus
SSMSignTextResource_FormSubmitHandler(SSMResource* res,
HTTPRequest* req)
{
SSMStatus rv;
char* tmpStr;
SSMSignTextResource *signTextRes = (SSMSignTextResource*)res;
SSM_LockResource(res);
rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
if (rv != SSM_SUCCESS ||
PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
goto loser;
}
/* Detect which button was pressed */
if (res->m_buttonType == SSM_BUTTON_OK) {
/* Get the certificate nickname */
SSM_HTTPParamValue(req, "chose", &signTextRes->m_nickname);
}
loser:
/* Close the window */
SSM_HTTPCloseAndSleep(req);
/* Unblock the sign text thread waiting on this */
SSM_NotifyResource(res);
SSM_UnlockResource(res);
return rv;
}
SSMStatus SSM_SignTextCertListKeywordHandler(SSMTextGenContext* cx)
{
SSMStatus rv = SSM_SUCCESS;
SSMResource* target = NULL;
SSMSignTextResource* res;
char* prefix = NULL;
char* wrapper = NULL;
char* suffix = NULL;
char* tmpStr = NULL;
char* fmt = NULL;
const PRIntn CERT_LIST_PREFIX = (PRIntn)0;
const PRIntn CERT_LIST_WRAPPER = (PRIntn)1;
const PRIntn CERT_LIST_SUFFIX = (PRIntn)2;
const PRIntn CERT_LIST_PARAM_COUNT = (PRIntn)3;
/*
* make sure cx, cx->m_request, cx->m_params, cx->m_result are not
* NULL
*/
PR_ASSERT(cx != NULL && cx->m_request != NULL && cx->m_params != NULL &&
cx->m_result != NULL);
if (cx == NULL || cx->m_request == NULL || cx->m_params == NULL ||
cx->m_result == NULL) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto loser;
}
if (SSM_Count(cx->m_params) != CERT_LIST_PARAM_COUNT) {
SSM_HTTPReportSpecificError(cx->m_request, "_signtext_certList: ",
"Incorrect number of parameters "
" (%d supplied, %d needed).\n",
SSM_Count(cx->m_params),
CERT_LIST_PARAM_COUNT);
goto loser;
}
/* get the connection object */
target = SSMTextGen_GetTargetObject(cx);
PR_ASSERT(target != NULL);
res = (SSMSignTextResource*)target;
/* form the MessageFormat object */
/* find arguments (prefix, wrapper, and suffix) */
prefix = (char *) SSM_At(cx->m_params, CERT_LIST_PREFIX);
wrapper = (char *) SSM_At(cx->m_params, CERT_LIST_WRAPPER);
suffix = (char *) SSM_At(cx->m_params, CERT_LIST_SUFFIX);
PR_ASSERT(prefix != NULL && wrapper != NULL && suffix != NULL);
/* grab the prefix and expand it */
rv = SSM_GetAndExpandTextKeyedByString(cx, prefix, &tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
/* append the prefix */
rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
SSMTextGen_UTF8StringClear(&tmpStr);
SSM_DebugUTF8String("signtext cert list prefix", cx->m_result);
/* grab the wrapper */
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapper, &tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
SSM_DebugUTF8String("sign text cert list wrapper", fmt);
/* form the wrapped cert list UnicodeString */
rv = ssm_signtext_get_unicode_cert_list(res, tmpStr, &tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
/* append the wrapped cert list */
rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
SSMTextGen_UTF8StringClear(&tmpStr);
/* grab the suffix and expand it */
rv = SSM_GetAndExpandTextKeyedByString(cx, suffix, &tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
SSM_DebugUTF8String("client cert list suffix", tmpStr);
/* append the suffix */
rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
goto done;
loser:
if (rv == SSM_SUCCESS) {
rv = SSM_FAILURE;
}
done:
PR_FREEIF(fmt);
PR_FREEIF(tmpStr);
return rv;
}
/*
* Function: SSMStatus ssm_client_auth_get_unicode_cert_list()
* Purpose: forms the cert list UnicodeString
*
* Arguments and return values:
* - conn: SSL connection object
* - fmt: cert wrapper UnicodeString format
* - result: resulting UnicodeString
*
* Note: if we include the expired certs, we need to append to the end as
* well
*/
SSMStatus ssm_signtext_get_unicode_cert_list(SSMSignTextResource* res,
char* fmt,
char** result)
{
SSMStatus rv = SSM_SUCCESS;
char * tmpStr = NULL;
char * finalStr = NULL;
int i;
CERTCertListNode *head = NULL;
int numCerts;
PR_ASSERT(res != NULL && fmt != NULL && result != NULL);
/* in case we fail */
*result = NULL;
/* concatenate the string using the nicknames */
head = (CERTCertListNode *)PR_LIST_HEAD(&res->m_certs->list);
numCerts = SSM_CertListCount(res->m_certs);
for (i = 0; i < numCerts; i++) {
tmpStr = PR_smprintf(fmt, i, head->cert->nickname);
rv = SSM_ConcatenateUTF8String(&finalStr, tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
PR_Free(tmpStr);
tmpStr = NULL;
head = (CERTCertListNode *)head->links.next;
}
SSM_DebugUTF8String("client auth: final cert list", finalStr);
*result = finalStr;
return SSM_SUCCESS;
loser:
SSM_DEBUG("client auth: wrapping cert list failed.\n");
if (rv == SSM_SUCCESS) {
rv = SSM_FAILURE;
}
PR_FREEIF(finalStr);
PR_FREEIF(tmpStr);
return rv;
}

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

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

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,202 @@
/*
* 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.
*/
#ifndef __SSM_SSLDLGS_H__
#define __SSM_SSLDLGS_H__
#include "textgen.h"
#include "minihttp.h"
#include "sslconn.h"
#include "certt.h"
/*
* Function: SSMStatus SSM_ServerCertKeywordHandler()
* Purpose: keyword handler for "_server_cert_info"
* performs substitution for cert info data
* syntax: {_server_cert_info cert_format,wrapper}
* cert_format: either simple_cert_format (0) or
* pretty_cert_format (1)
* Arguments and return values:
* - cx: SSMTextGenContext to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
*/
SSMStatus SSM_ServerCertKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_FormatCert()
* Purpose: creates a UnicodeString that is used in expanding the keyword
* "_server_cert_info" from the given cert
* this function provides info on hostname, issuer name, and validity
* period. Any UI dialog that uses a subset of this info can use
* this function.
* Arguments and return values
* - cert: server cert to be manipulated
* - fmt: message format (shouldn't be NULL)
* - result: resulting expanded string (shouldn't be NULL)
*
* Note: note that this is very similar to a _Print method. In fact,
* this could be turned into SSMResourceCert_Print() method w/o too many
* changes.
*/
SSMStatus SSM_FormatCert(CERTCertificate* cert, char* fmt,
char** result);
/*
* Function: SSMStatus SSM_HTTPBadClientAuthButtonHandler()
* Purpose: command handler for "BCAButton" (button handling
* for bad client auth dialogs)
* Arguments and return values:
* - req: request object to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: we use this command handler instead of the default handler
* to block the SSL threads while this dialog is up.
*/
SSMStatus SSM_HTTPBadClientAuthButtonHandler(HTTPRequest* req);
/*
* Function: SSMStatus SSM_SSLMakeBadClientAuthDialog()
* Purpose: make "no cert" dialog by sending the "no cert" UI event
* Arguments and return values:
* - conn: SSL connection object
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: URL: ".../get?baseRef=bad_client_auth&target=(conn ID)"
* blocks until the dialog is complete
*/
SSMStatus SSM_SSLMakeBadClientAuthDialog(SSMSSLDataConnection* conn);
/*
* Function: SSMStatus SSM_SSLMakeClientAuthDialog()
* Purpose: generates the client auth cert selection dialog and receives
* a chosen cert nickname from the user
* Arguments and return values:
* - conn: SSL connection object to be manipulated; m_UIInfo.chosenNickname
* will be populated as a result of the dialog
* - returns: SSM_SUCCESS if successful; otherwise error code
*
* Note: (design issue) how do we handle "cancel" event? Do we display the
* "no cert" dialog and exit, or we just exit? Probably we just exit.
*/
SSMStatus SSM_SSLMakeClientAuthDialog(SSMSSLDataConnection* conn);
/*
* Function: SSMStatus SSM_ClientAuthCertListKeywordHandler()
* Purpose: formats the client cert list according to the given format
* for the cert selection dialog
* syntax: {_client_auth_certList prefix,wrapper,suffix}
* where wrapper is for the individual cert
* Arguments and return values:
* - cx: text context to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note:
*/
SSMStatus SSM_ClientAuthCertListKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_HTTPClientAuthButtonHandler()
* Purpose: handles the user input for buttons in cert selection dialog
* URL: "CAButton?baseRef=windowclose_doclose_js&target={0}&chosen=0&do_ok={text_ok}" or "CAButton?...&target={0}&do_cancel={text_cancel}", etc.
*/
SSMStatus SSM_HTTPClientAuthButtonHandler(HTTPRequest* req);
SECStatus SSM_SSLMakeCertExpiredDialog(CERTCertificate* cert,
SSMSSLDataConnection* conn);
SECStatus SSM_SSLMakeCertBadDomainDialog(CERTCertificate* cert,
SSMSSLDataConnection* conn);
SSMStatus SSM_ClientAuthCertSelectionButtonHandler(HTTPRequest* req);
SSMStatus SSM_ServerAuthFailureButtonHandler(HTTPRequest* req);
SSMStatus SSM_ServerAuthUnknownIssuerButtonHandler(HTTPRequest* req);
SSMStatus SSM_CurrentTimeKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_ServerAuthDomainKeywordHandler()
* Purpose: formats the domain name mismatch warning string for server auth
* syntax: {_server_cert_domain_info bad_domain_wrapper}
* Arguments and return values
* - cx: text context to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: I wrote a separate keyword handler although there is a generic
* server cert info keyword handler; this is the only place where
* one needs the URL hostname and it turns out to be simpler and more
* efficient to write a separate handler for this purpose
*/
SSMStatus SSM_ServerAuthDomainNameKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_VerifyServerCertKeywordHandler()
* Purpose: handles the nickname substitution for keyword
* "_verify_server_cert"
* Arguments and return values:
* - cx: text context to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: since this only comes from the server auth failure dialog, we know
* beforehand that the cert is bad (thus no need really to verify the
* cert). This might change if we want to print out the nature of the
* error. Also, if we want to consolidate this view cert window
* handling (it's not clear how we can do that because we have different
* certs and different targets for different cases), this function
* may have to be modified.
*/
SSMStatus SSM_VerifyServerCertKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_PrettyFormatCert()
* Purpose: formats the cert info for "View Security Certificate" dialogs
* this function provides info on issuer name, serial number,
* validity period, finger print, and comment. Any dialog that
* needs a subset of the parameters can use this function to format
* the cert
* Arguments and return values:
* - cert: cert to be presented
* - fmt: MessageFormat object
* - result: UnicodeString to be returned as a result of the operation
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: this provides no information on whether the cert is valid or not
* lot of the code is borrowed from CERT_HTMLInfo() from NSS
* we also access lots of internal cert fields but can't help it...
*/
SSMStatus SSM_PrettyFormatCert(CERTCertificate* cert, char* fmt,
char** result);
SECStatus SSM_SSLMakeUnknownIssuerDialog(CERTCertificate* cert,
SSMSSLDataConnection* conn);
SSMStatus SSM_HTTPUnknownIssuerStep1ButtonHandler(HTTPRequest* req);
#endif /* __SSM_SSLDLGS_H__ */

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

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

@ -0,0 +1,503 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 "sslconn.h"
#include "ctrlconn.h"
#include "serv.h"
#include "servimpl.h"
/* Shorthand macros for inherited classes */
#define SSMRESOURCE(ss) (&(ss)->super)
/* implemented in resource.c: this should belong to resource.h! */
SSMStatus SSM_UnpickleResource(SSMResource** res, SSMResourceType type,
SSMControlConnection* connection,
PRIntn len, void* value);
SSMStatus
SSMSSLSocketStatus_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMSSLSocketStatus *ss;
*res = NULL; /* in case we fail */
ss = (SSMSSLSocketStatus *) PR_CALLOC(sizeof(SSMSSLSocketStatus));
if (!ss) goto loser;
rv = SSMSSLSocketStatus_Init(ss, connection,
(PRFileDesc *) arg,
SSM_RESTYPE_SSL_SOCKET_STATUS);
if (rv != PR_SUCCESS) goto loser;
SSMSSLSocketStatus_Invariant(ss);
*res = &ss->super;
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (ss)
{
SSMRESOURCE(ss)->m_refCount = 1; /* force destroy */
SSM_FreeResource(SSMRESOURCE(ss));
}
return rv;
}
SSMStatus
SSMSSLSocketStatus_Init(SSMSSLSocketStatus *ss,
SSMControlConnection * connection,
PRFileDesc *fd, SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
int keySize, secretKeySize, level;
SSMResource *certObj;
SSMResourceID certRID;
CERTCertificate *cert;
/* Initialize superclass */
SSMResource_Init(connection, SSMRESOURCE(ss), type);
/* Get the peer cert and import it into an NSM object */
cert = SSL_PeerCertificate(fd);
if (!cert) goto loser;
rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, cert,
SSMRESOURCE(ss)->m_connection, &certRID,
&certObj);
if (rv != PR_SUCCESS) goto loser;
ss->m_cert = (SSMResourceCert*)certObj;
/* Get the other socket status information */
rv = SSL_SecurityStatus(fd, &level, &ss->m_cipherName,
&keySize,
&secretKeySize,
NULL, NULL);
if (rv != PR_SUCCESS) goto loser;
ss->m_keySize = keySize;
ss->m_secretKeySize = secretKeySize;
ss->m_level = level;
/* Sanity check before returning */
SSMSSLSocketStatus_Invariant(ss);
goto done;
loser:
/* member destruct, if any are allocated, will happen in the
_Destroy method */
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMSSLSocketStatus_Destroy(SSMResource *res, PRBool doFree)
{
SSMSSLSocketStatus *ss = (SSMSSLSocketStatus *) res;
SSMSSLSocketStatus_Invariant(ss);
/* Destroy our members. */
if (ss->m_cert)
{
SSM_FreeResource(&ss->m_cert->super);
ss->m_cert = NULL;
}
if (ss->m_cipherName)
{
PORT_Free(ss->m_cipherName);
ss->m_cipherName = NULL;
}
/* Destroy superclass. */
SSMResource_Destroy(res, PR_FALSE);
/* Free if asked. */
if (doFree)
PR_Free(res);
return PR_SUCCESS;
}
void
SSMSSLSocketStatus_Invariant(SSMSSLSocketStatus *ss)
{
/* Superclass invariant */
SSMResource_Invariant(SSMRESOURCE(ss));
/* Class check */
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(ss), SSM_RESTYPE_SSL_SOCKET_STATUS));
/* Member check */
#if 0
/* Make sure we used a cert to initialize ourselves */
if (ss->m_cert)
PR_ASSERT(ss->m_cert != NULL);
#endif
}
SSMStatus
SSMSSLSocketStatus_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMResource_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 4) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_SSS_KEYSIZE;
(*ids)[*count++] = SSM_FID_SSS_SECRET_KEYSIZE;
(*ids)[*count++] = SSM_FID_SSS_CERT_ID;
(*ids)[*count++] = SSM_FID_SSS_CIPHER_NAME;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMSSLSocketStatus_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMStatus rv = PR_SUCCESS;
SSMSSLSocketStatus *ss = (SSMSSLSocketStatus *) res;
char *tmpstr = NULL;
SSM_DEBUG("socket status get attr is called.\n");
SSMSSLSocketStatus_Invariant(ss);
/* see what it is */
switch(attrID)
{
case SSM_FID_SSS_KEYSIZE:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = ss->m_keySize;
break;
case SSM_FID_SSS_SECRET_KEYSIZE:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = ss->m_secretKeySize;
break;
case SSM_FID_SSS_CERT_ID:
value->type = SSM_RID_ATTRIBUTE;
value->u.numeric = ss->m_cert->super.m_id;
break;
case SSM_FID_SSS_SECURITY_LEVEL:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = ss->m_level;
break;
case SSM_FID_SSS_CIPHER_NAME:
value->type = SSM_STRING_ATTRIBUTE;
value->u.string.len = PL_strlen(ss->m_cipherName);
value->u.string.data = (unsigned char *) PL_strdup(ss->m_cipherName);
break;
case SSM_FID_SSS_HTML_STATUS:
value->type = SSM_STRING_ATTRIBUTE;
rv = (*res->m_html_func)(res, NULL, (void**)&tmpstr);
value->u.string.len = PL_strlen(tmpstr);
value->u.string.data = (unsigned char *) PL_strdup(tmpstr);
break;
default:
rv = SSMResource_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS)
goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
if (tmpstr != NULL)
PR_Free(tmpstr);
return rv;
}
SSMStatus SSMSSLSocketStatus_Pickle(SSMResource *res, PRIntn * len,
void **value)
{
int blobSize, certSize;
SSMStatus rv;
SSMSSLSocketStatus * resource = (SSMSSLSocketStatus *)res;
void * certBlob, *curptr, *tmpStr = NULL;
if (!res || !value) {
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
/* in case we fail */
*value = NULL;
if (len) *len = 0;
#if 0
/* first, pickle cert */
rv = SSMControlConnection_GetResource(res->m_connection,
resource->m_certID,
(SSMResource **)&certObj);
if (rv != PR_SUCCESS) goto loser;
#endif
rv = SSM_PickleResource(&resource->m_cert->super, &certSize, &certBlob);
if (rv != PR_SUCCESS)
goto loser;
/* allocate memory for the pickled blob */
blobSize = certSize + sizeof(PRUint32)*5 +
SSMSTRING_PADDED_LENGTH(strlen(resource->m_cipherName));
curptr = PORT_ZAlloc(blobSize);
if (!curptr) {
rv = PR_OUT_OF_MEMORY_ERROR;
goto loser;
}
*value = curptr;
*(PRUint32 *)curptr = resource->m_keySize;
curptr = (PRUint32 *)curptr + 1;
*(PRUint32 *)curptr = resource->m_secretKeySize;
curptr = (PRUint32 *)curptr + 1;
*(PRInt32*)curptr = resource->m_level;
curptr = (PRInt32 *)curptr + 1;
*(PRInt32*)curptr = resource->m_error;
curptr = (PRInt32 *)curptr + 1;
rv = SSM_StringToSSMString((SSMString **)&tmpStr, 0, resource->m_cipherName);
if (rv != PR_SUCCESS)
goto loser;
memcpy(curptr, tmpStr, SSM_SIZEOF_STRING(*(SSMString *)tmpStr));
curptr = (char *)curptr + SSM_SIZEOF_STRING(*(SSMString *)tmpStr);
PR_Free(tmpStr);
tmpStr = NULL;
/* copy cert into the blob */
memcpy(curptr, certBlob, certSize);
if (len) *len = blobSize;
return rv;
loser:
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
if (value && *value)
PR_Free(*value);
if (len)
*len = 0;
if (tmpStr)
PR_Free(tmpStr);
return rv;
}
SSMStatus SSMSSLSocketStatus_Unpickle(SSMResource ** res,
SSMControlConnection * connection,
PRInt32 len,
void *value)
{
SSMStatus rv = PR_SUCCESS;
SSMSSLSocketStatus *ss;
void * curptr = NULL;
PRUint32 strLength = 0, certLength = 0;
SSMResource * certResource = NULL;
if (!res || !value) {
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
*res = NULL; /* in case we fail */
ss = (SSMSSLSocketStatus *) PR_CALLOC(sizeof(SSMSSLSocketStatus));
if (!ss) goto loser;
ss->m_cipherName = NULL;
ss->m_cert = NULL;
/* Initialize superclass */
SSMResource_Init(connection, SSMRESOURCE(ss),
SSM_RESTYPE_SSL_SOCKET_STATUS);
/* Unpickle socket status data */
curptr = value;
ss->m_keySize = *(PRUint32 *)curptr;
curptr =(PRUint32 *)curptr + 1;
ss->m_secretKeySize = *(PRUint32 *)curptr;
curptr =(PRUint32 *)curptr + 1;
ss->m_level = *(PRInt32 *)curptr;
curptr = (PRInt32 *)curptr + 1;
ss->m_error = *(PRInt32 *)curptr;
curptr = (PRInt32 *)curptr + 1;
/* Fix this */
rv = SSM_SSMStringToString(&ss->m_cipherName, (int *) &strLength,
(SSMString *)curptr);
if (rv != PR_SUCCESS || ss->m_cipherName == NULL || strLength == 0)
goto loser;
curptr = (char *)curptr + SSMSTRING_PADDED_LENGTH(strLength) +
sizeof(PRUint32);
/* Unpickle cert */
certLength = len - ((unsigned long)curptr - (unsigned long)value);
rv = SSM_UnpickleResource(&certResource, SSM_RESTYPE_CERTIFICATE,
connection, certLength, curptr);
if (rv != PR_SUCCESS || !certResource)
goto loser;
#if 0
ss->m_certID = certResource->m_id;
#endif
ss->m_cert = (SSMResourceCert*)certResource;
/* Sanity check before returning */
SSMSSLSocketStatus_Invariant(ss);
*res = SSMRESOURCE(ss);
goto done;
loser:
if (ss) {
if (ss->m_cipherName)
PR_Free(ss->m_cipherName);
if (ss->m_cert) {
SSM_FreeResource(&ss->m_cert->super);
#if 0
(*(certResource->m_destroy_func))(certResource, PR_TRUE);
#endif
}
PR_Free(certResource);
}
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
return rv;
}
SSMStatus SSMSSLSocketStatus_HTML(SSMResource *res, PRIntn *len, void ** value)
{
SSMStatus rv = PR_SUCCESS;
SSMSSLSocketStatus * resource = (SSMSSLSocketStatus *)res;
char * line = NULL;
if (!res || !value) {
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
if (len) *len = 0;
*value = NULL;
switch (resource->m_level) {
case SSL_SECURITY_STATUS_ON_HIGH:
#ifdef FORTEZZA
case SSL_SECURITY_STATUS_FORTEZZA:
#endif
line = PR_smprintf("%s", SECURITY_HIGH_MESSAGE);
break;
case SSL_SECURITY_STATUS_ON_LOW:
line = PR_smprintf("%s", SECURITY_LOW_MESSAGE);
break;
default:
*value = PR_smprintf("%s", SECURITY_NO_MESSAGE);
goto done;
}
if (resource->m_keySize != resource->m_secretKeySize) {
*value = PR_smprintf("%s (%s, %d bit with %d secret).", line,
resource->m_cipherName,
resource->m_keySize,
resource->m_secretKeySize);
} else {
*value = PR_smprintf("%s (%s, %d bit).", line,
resource->m_cipherName,
resource->m_keySize);
}
goto done;
loser:
if (value && *value)
PR_Free(*value);
*value = NULL;
if (len && *len)
*len = 0;
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
if (value && *value && len)
*len = strlen((char *)*value)+1;
if (line)
PR_Free(line);
return rv;
}
SSMStatus SSMSSLSocketStatus_UpdateSecurityStatus(SSMSSLSocketStatus* ss,
PRFileDesc* socket)
{
SSMStatus rv = PR_SUCCESS;
int keySize, secretKeySize, level;
/* ss should not be NULL when this function is called */
PR_ASSERT(ss != NULL);
/* Get the security status information */
if (ss->m_cipherName != NULL) {
PR_Free(ss->m_cipherName);
ss->m_cipherName = NULL;
}
rv = SSL_SecurityStatus(socket, &level, &ss->m_cipherName, &keySize,
&secretKeySize, NULL, NULL);
if (rv != PR_SUCCESS) {
goto loser;
}
ss->m_keySize = keySize;
ss->m_secretKeySize = secretKeySize;
ss->m_level = level;
/* Sanity check before returning */
SSMSSLSocketStatus_Invariant(ss);
goto done;
loser:
if (rv == PR_SUCCESS) {
rv = PR_FAILURE;
}
if (ss->m_cipherName != NULL) {
PR_Free(ss->m_cipherName);
ss->m_cipherName = NULL;
}
done:
return rv;
}

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

@ -0,0 +1,134 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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.
*/
#ifndef __SSM_SSLSKST_H__
#define __SSM_SSLSKST_H__
#include <stdio.h>
#include <string.h>
#include "prerror.h"
#include "pk11func.h"
#include "secitem.h"
#include "ssl.h"
#include "prnetdb.h"
#include "certt.h"
#include "nss.h"
#include "nspr.h"
#include "secrng.h"
#include "secder.h"
#include "key.h"
#include "sslproto.h"
#include "ctrlconn.h"
#include "dataconn.h"
#include "certres.h"
/* Initialization parameters for an SSMSSLSocketStatus. */
/*
SSL Socket Status object. This encapsulates the information about an SSL
connection.
*/
typedef struct SSMSSLSocketStatus
{
SSMResource super;
PRUint32 m_keySize;
PRUint32 m_secretKeySize;
PRInt32 m_level;
char *m_cipherName;
PRInt32 m_error;
SSMResourceCert *m_cert; /* placeholder - will we want to get an
SSMCertificate object ref later? */
} SSMSSLSocketStatus;
SSMStatus SSMSSLSocketStatus_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMSSLSocketStatus_Init(SSMSSLSocketStatus *ss,
SSMControlConnection * connection,
PRFileDesc *fd, SSMResourceType type);
SSMStatus SSMSSLSocketStatus_Destroy(SSMResource *res, PRBool doFree);
void SSMSSLSocketStatus_Invariant(SSMSSLSocketStatus *ss);
SSMStatus SSMSSLSocketStatus_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMSSLSocketStatus_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMSSLSocketStatus_Pickle(SSMResource *res, PRIntn * len,
void **value);
SSMStatus SSMSSLSocketStatus_Unpickle(SSMResource **res,
SSMControlConnection * conn, PRIntn len,
void *value);
SSMStatus SSMSSLSocketStatus_HTML(SSMResource *res, PRIntn *len, void ** value);
/*
* Function: SSMStatus SSMSSLSocketStatus_UpdateSecurityStatus()
* Purpose: updates the security status
* Arguments and return values:
* - ss: socket status (it should not be NULL when called)
* - socket: SSL socket
* - returns: PR_SUCCESS if the update is successful; PR_FAILURE otherwise
*
* Note: if the update fails, one can keep doing other work but (obviously)
* should not attempt to use any of the security-related values
*/
SSMStatus SSMSSLSocketStatus_UpdateSecurityStatus(SSMSSLSocketStatus* ss,
PRFileDesc* socket);
/*
* The following string are used to present security status in HTML format.
*/
#ifdef XP_UNIX
#define SECURITY_LOW_MESSAGE "This is a secure document that uses a medium-grade encryption key suited\nfor U.S. export"
#define SECURITY_HIGH_MESSAGE "This is a secure document that uses a high-grade encryption key for U.S.\ndomestic use only"
#define SECURITY_NO_MESSAGE "This is an insecure document that is not encrypted and offers no security\nprotection."
#else
#define SECURITY_LOW_MESSAGE "This is a secure document that uses a medium-grade encryption key suited for U.S. export"
#define SECURITY_HIGH_MESSAGE "This is a secure document that uses a high-grade encryption key for U.S. domestic use only"
#define SECURITY_NO_MESSAGE "This is an insecure document that is not encrypted and offers no security protection."
#endif
#endif

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,144 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 file for libnls related utilities. Separated because there
are a lot of headers for libnls, and only those objects which override
the default Print function (see resource.h) should be including
these files.
mwelch - 1999 January
*/
#ifndef __textgen_h__
#define __textgen_h__
#include "nlsutil.h"
#include "minihttp.h"
#include "resource.h"
#include "ctrlconn.h"
/* Indices for the resource bundles.
Keep in sync with (resBundleNames) below. */
typedef enum
{
SSM_RESBNDL_TEXT = (PRInt32) 0,
SSM_RESBNDL_UI,
SSM_RESBNDL_BIN,
SSM_RESBNDL_DOC,
SSM_RESBNDL_COUNT
} SSMResourceBundleIndex;
extern char *resBundleNames[];
/* Text generator state, used by keyword handlers */
typedef struct SSMTextGenContext
{
struct SSMTextGenContext *m_caller; /* who called us, if at all */
HTTPRequest * m_request; /* the HTTP request being processed */
char* m_keyword; /* the keywd by which we are called */
SSMCollection * m_params; /* params to this keyword */
char* m_result; /* where we store the result */
} SSMTextGenContext;
/* Create/destroy a textgen context. */
SSMStatus SSMTextGen_NewContext(SSMTextGenContext *caller, /* can be NULL */
HTTPRequest *req,
char *keyword,
char **params,
SSMTextGenContext **result);
/* Create a top-level textgen context. */
SSMStatus SSMTextGen_NewTopLevelContext(HTTPRequest *req,
SSMTextGenContext **result);
void SSMTextGen_DestroyContext(SSMTextGenContext *victim);
/* Helper routines used with a TextGenContext */
SSMResource *SSMTextGen_GetTargetObject(SSMTextGenContext *cx);
SSMResource *SSMTextGen_GetControlConnection(SSMTextGenContext *cx);
/*
Top level routine called by non-NLS-using parts of Cartman.
Retrieves a string, expands it, then formats it according to the
_Print method of the target object.
*/
SSMStatus SSM_GetUTF8Text(SSMTextGenContext *cx, /* can be NULL */
const char *key,
char **resultText);
/* Get a numeric parameter from the properties file. */
SSMStatus SSM_GetNumber(SSMTextGenContext *cx, char *key, PRInt32 *param);
/* Just gets and expands a string. Can pass NULL for (res). */
SSMStatus SSM_GetAndExpandText(SSMTextGenContext *cx,
const char *key, char **result);
SSMStatus SSM_GetAndExpandTextKeyedByString(SSMTextGenContext *cx,
const char *key,
char **result);
/* Keyword processing function. */
typedef SSMStatus (*KeywordHandlerFunc)(SSMTextGenContext *cx);
SSMStatus SSM_HelloKeywordHandler(SSMTextGenContext *cx);
/* Register a keyword callback. */
SSMStatus SSM_RegisterKeywordHandler(char *keyword,
KeywordHandlerFunc func);
/* Perform NLS-specific initialization. (dataDirectory) contains the path
of the directory containing the "conv" folder with conversion libraries
for the current locale. */
void SSM_InitNLS(char *dataDirectory);
/* Given a key and a context, cycle through resource bundles until
we find a match for the desired key. */
SSMStatus
SSM_FindUTF8StringInBundles(SSMTextGenContext *cx,
const char *key,
char **utf8result);
SSMStatus SSMTextGen_SubstituteString(SSMTextGenContext *cx,
char *str,
char **result);
SSMStatus
SSM_WarnPKCS12Incompatibility(SSMTextGenContext *cx);
SSMStatus
SSM_PassVariable(SSMTextGenContext *cx);
#endif

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