[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