[Vm-dev] [commit][2708] update to most recent available sources
commits at squeakvm.org
commits at squeakvm.org
Fri Mar 22 14:12:03 UTC 2013
Revision: 2708
Author: piumarta
Date: 2013-03-22 07:11:57 -0700 (Fri, 22 Mar 2013)
Log Message:
-----------
update to most recent available sources
Modified Paths:
--------------
trunk/platforms/win32/plugins/SqueakSSL/sqWin32SSL.c
Modified: trunk/platforms/win32/plugins/SqueakSSL/sqWin32SSL.c
===================================================================
--- trunk/platforms/win32/plugins/SqueakSSL/sqWin32SSL.c 2013-03-22 12:38:54 UTC (rev 2707)
+++ trunk/platforms/win32/plugins/SqueakSSL/sqWin32SSL.c 2013-03-22 14:11:57 UTC (rev 2708)
@@ -115,11 +115,15 @@
}
/* Set up the local certificate for SSL */
+#define MAX_NAME_SIZE 4096
static sqInt sqSetupCert(sqSSL *ssl, char *certName, int server) {
SCHANNEL_CRED sc_cred = { 0 };
SECURITY_STATUS ret;
HCERTSTORE hStore;
PCCERT_CONTEXT pContext = NULL;
+ DWORD dwPropSize;
+ WCHAR wFriendlyName[MAX_NAME_SIZE];
+ char bFriendlyName[MAX_NAME_SIZE];
if(certName) {
hStore = CertOpenSystemStore(0, "MY");
@@ -127,12 +131,32 @@
if(ssl->loglevel) printf("sqSetupCert: CertOpenSystemStore failed\n");
return 0;
}
- pContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- 0, CERT_FIND_SUBJECT_STR_A, certName, NULL);
+ pContext = NULL;
- /* XXXX: Fail? Or just not provide the cert? For now, fail. */
+ /* Enumerate the certificate store to find the cert with the given friendly name */
+ while(pContext = CertEnumCertificatesInStore(hStore, pContext)) {
+ if(ssl->loglevel) printf("Checking certificate: ");
+ dwPropSize = MAX_NAME_SIZE * sizeof(WCHAR);
+ if(!CertGetCertificateContextProperty(pContext, CERT_FRIENDLY_NAME_PROP_ID, wFriendlyName, &dwPropSize)) {
+ if(ssl->loglevel) printf("<no friendly name>");
+ continue;
+ }
+ if(!WideCharToMultiByte(CP_UTF8, 0, wFriendlyName, -1, bFriendlyName, MAX_NAME_SIZE, NULL, NULL)) {
+ if(ssl->loglevel) printf("<utf-8 conversion failure>");
+ continue;
+ }
+ if(ssl->loglevel) printf("%s\n", bFriendlyName);
+ if(strcmp(certName, bFriendlyName) == 0) break;
+ }
+
+ if(pContext == 0) {
+ /* For compatibility with older versions of SqueakSSL, attempt to match against subject string */
+ pContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0, CERT_FIND_SUBJECT_STR_A, certName, NULL);
+ }
+
if(!pContext) {
- if(ssl->loglevel) printf("sqSetupCert: CertFindCertitficateInStore failed\n");
+ if(ssl->loglevel) printf("sqSetupCert: No suitable certificate found\n");
CertCloseStore(hStore, 0);
return 0;
}
@@ -471,6 +495,9 @@
int count;
/* Handle various failure conditions */
switch(ret) {
+ case SEC_E_INCOMPLETE_MESSAGE:
+ /* not enough data for the handshake to complete */
+ return SQSSL_NEED_MORE_DATA;
case SEC_I_CONTINUE_NEEDED:
/* Send contents back to peer and come back with more data */
count = sqCopyDescToken(ssl, ssl->sbdOut, dstBuf, dstLen);
@@ -500,7 +527,15 @@
/* TODO: Look at retFlags */
ssl->state = SQSSL_CONNECTED;
- sqCopyExtraData(ssl, ssl->sbdOut);
+ /* If there is SECBUFFER_EXTRA in the input we need to retain it */
+ if(ssl->inbuf[1].BufferType == SECBUFFER_EXTRA) {
+ int extra = ssl->inbuf[1].cbBuffer;
+ if(ssl->loglevel) printf("sqConnectSSL: Retaining %d token bytes\n", extra);
+ memmove(ssl->dataBuf, ssl->dataBuf + (ssl->dataLen - extra), extra);
+ ssl->dataLen = extra;
+ } else {
+ sqCopyExtraData(ssl, ssl->sbdOut);
+ }
ret = QueryContextAttributes(&ssl->sslCtxt, SECPKG_ATTR_STREAM_SIZES, &ssl->sslSizes);
if(ssl->loglevel) printf("sqConnectSSL: Maximum message size is %d bytes\n", ssl->sslSizes.cbMaximumMessage);
@@ -576,6 +611,9 @@
if(ret != SEC_E_OK) {
/* Handle various failure conditions */
switch(ret) {
+ case SEC_E_INCOMPLETE_MESSAGE:
+ /* not enough data for the handshake to complete */
+ return SQSSL_NEED_MORE_DATA;
case SEC_I_CONTINUE_NEEDED:
/* Send contents back to peer and come back with more data */
return sqCopyDescToken(ssl, ssl->sbdOut, dstBuf, dstLen);
@@ -677,6 +715,11 @@
if(ssl == NULL || ssl->state != SQSSL_CONNECTED) return SQSSL_INVALID_STATE;
+ /* Workaround for a strange Windows issue: Directly after an SSL handshake
+ has completed, calling DecryptMessage() with empty input can fail with
+ SEC_E_INVALID_TOKEN for no apparent reason. */
+ if(!ssl->dataLen && !srcLen) return 0;
+
if(ssl->dataLen + srcLen > ssl->dataMax) {
/* resize the read buffer */
ssl->dataMax += (srcLen < 4096) ? (4096) : (srcLen+1024);
@@ -708,6 +751,12 @@
ssl->sbdIn.cBuffers = 4;
ret = DecryptMessage(&ssl->sslCtxt, &ssl->sbdIn, 0, 0);
+ if(ret == SEC_I_CONTEXT_EXPIRED) {
+ /* The remote has shut down the ssl session */
+ ssl->dataLen = 0;
+ return 0;
+ }
+
/* Copy the result into destination buffer */
total = 0;
for(i=0;i<4;i++) {
@@ -757,6 +806,48 @@
return NULL;
}
+/* sqAddPfxCertToStore: Adds a PFX certificate to MY certificate store.
+ Arguments:
+ pfxData - the contents of the PFX certificate file
+ pfxLen - the length of the PFX certificate file
+ passData - the utf8 encoded password for the file
+ passLen - the size of the password
+ Returns: 1 on success, 0 on failure
+*/
+static sqInt sqAddPfxCertToStore(char *pfxData, sqInt pfxLen, char *passData, sqInt passLen) {
+ PCCERT_CONTEXT pContext;
+ HCERTSTORE pfxStore, myStore;
+ CRYPT_DATA_BLOB blob;
+ WCHAR widePass[4096];
+
+ /* Verify that this is a PFX file */
+ blob.cbData = pfxLen;
+ blob.pbData = pfxData;
+ if(!PFXIsPFXBlob(&blob)) return 0; /* Not a PFX blob */
+
+ /* Verify that the password is all right */
+ widePass[0] = 0;
+ if(passLen > 0) {
+ DWORD wideLen = MultiByteToWideChar(CP_UTF8, 0, passData, passLen, widePass, 4095);
+ widePass[wideLen] = 0;
+ }
+ if(!PFXVerifyPassword(&blob, widePass, 0)) return 0; /* Invalid password */
+
+ /* Import the PFX blob into a temporary store */
+ pfxStore = PFXImportCertStore(&blob, widePass, 0);
+ if(!pfxStore) return 0;
+
+ /* And copy the certificates to MY store */
+ myStore = CertOpenSystemStore(0, "MY");
+ pContext = NULL;
+ while(pContext = CertEnumCertificatesInStore(pfxStore, pContext)) {
+ CertAddCertificateContextToStore(myStore, pContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
+ }
+ CertCloseStore(myStore, 0);
+ CertCloseStore(pfxStore, 0);
+ return 1;
+}
+
/* sqSetStringPropertySSL: Set a string property in SSL.
Arguments:
handle - the ssl handle
@@ -780,6 +871,9 @@
switch(propID) {
case SQSSL_PROP_CERTNAME: ssl->certName = property; break;
+ /* Platform specific: Adds a .PFX file to MY certificate store w/o password.
+ Useful for installing the default test certificate in SqueakSSL. */
+ case 10001: return sqAddPfxCertToStore(propName, propLen, NULL, 0);
default:
if(ssl->loglevel) printf("sqSetStringPropertySSL: Unknown property ID %d\n", propID);
return 0;
More information about the Vm-dev
mailing list