зеркало из https://github.com/mozilla/pjs.git
Initial checkin of the PSM server
This commit is contained in:
Родитель
f03ff8d62c
Коммит
89611b5b5b
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
Загрузка…
Ссылка в новой задаче