Revision: 3416
Author: eliot
Date: 2015-07-29 18:51:21 -0700 (Wed, 29 Jul 2015)
Log Message:
-----------
Integrate Marcel Taeumel & Tobias Pape's v2 SSL plugin changes.
M SqueakSSL/sqWin32SSL.c
Modified Paths:
--------------
trunk/platforms/win32/plugins/SqueakSSL/sqWin32SSL.c
Modified: trunk/platforms/win32/plugins/SqueakSSL/sqWin32SSL.c
===================================================================
--- trunk/platforms/win32/plugins/SqueakSSL/sqWin32SSL.c 2015-07-30 01:46:49 UTC (rev 3415)
+++ trunk/platforms/win32/plugins/SqueakSSL/sqWin32SSL.c 2015-07-30 01:51:21 UTC (rev 3416)
@@ -1,4 +1,16 @@
-/* sqWin32SSL.c: SqueakSSL implementation for Windows */
+/****************************************************************************
+* PROJECT: SqueakSSL implementation for Windows
+* FILE: sqWin32SSL.c
+* CONTENT: SSL platform functions
+*
+* AUTHORS: Andreas Raab (ar)
+*
+* Marcel Taeumel (mt)
+* Hasso Plattner Institute, Postdam, Germany
+* Tobias Pape (topa)
+* Hasso Plattner Institute, Postdam, Germany
+*****************************************************************************/
+
#include <windows.h>
#include <errno.h>
#include <malloc.h>
@@ -18,6 +30,7 @@
char *certName;
char *peerName;
+ char *serverName;
CredHandle sslCred;
CtxtHandle sslCtxt;
@@ -126,7 +139,7 @@
char bFriendlyName[MAX_NAME_SIZE];
if(certName) {
- hStore = CertOpenSystemStore(0, "MY");
+ hStore = CertOpenSystemStore(0, L"MY");
if(!hStore) {
if(ssl->loglevel) printf("sqSetupCert: CertOpenSystemStore failed\n");
return 0;
@@ -199,7 +212,9 @@
PCERT_NAME_INFO certInfo = NULL;
PCERT_RDN_ATTR certAttr = NULL;
DWORD dwSize = 0;
- char tmpBuf[1024];
+ int cbPeerName = 0;
+ LPTSTR tmpBuf = NULL;
+ DWORD cchTmpBuf = 0;
if(ssl->peerName) {
free(ssl->peerName);
@@ -214,32 +229,21 @@
return 0;
}
- /* Figure out the size of the blob */
- if(!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_NAME,
- certHandle->pCertInfo->Subject.pbData,
- certHandle->pCertInfo->Subject.cbData,
- 0, NULL, &dwSize)) {
- if(ssl->loglevel) printf("sqExtractPeerName: CryptDecodeObject failed\n");
- return 0;
- }
-
- /* Get the contents */
- certInfo = alloca(dwSize);
- if(!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_NAME,
- certHandle->pCertInfo->Subject.pbData,
- certHandle->pCertInfo->Subject.cbData,
- 0, certInfo, &dwSize)) {
- if(ssl->loglevel) printf("sqExtractPeerName: CryptDecodeObject failed\n");
- return 0;
- }
+ /* Extract CN from certificate */
+ cchTmpBuf = CertGetNameString(certHandle, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0);
+ tmpBuf = (LPTSTR)alloca(cchTmpBuf * sizeof(TCHAR));
+ CertGetNameString(certHandle, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, tmpBuf, cchTmpBuf);
- /* Fetch the CN from the cert */
- certAttr = CertFindRDNAttr(szOID_COMMON_NAME, certInfo);
- if(certAttr == NULL) return 0;
-
- /* Translate from RDN to string */
- if(CertRDNValueToStr(CERT_RDN_PRINTABLE_STRING, &certAttr->Value, tmpBuf, sizeof(tmpBuf)) == 0) return 0;
+#ifdef _UNICODE
+ /* Convert wide to UTF8 */
+ cbPeerName = WideCharToMultiByte(CP_UTF8, 0, tmpBuf, -1, NULL, 0, NULL, NULL);
+ if (cbPeerName == 0) return 0;
+ ssl->peerName = calloc(1, cbPeerName);
+ WideCharToMultiByte(CP_UTF8, 0, tmpBuf, -1, ssl->peerName, cbPeerName, NULL, NULL);
+#else
ssl->peerName = _strdup(tmpBuf);
+#endif
+
if(ssl->loglevel) printf("sqExtractPeerName: Peer name is %s\n", ssl->peerName);
CertFreeCertificateContext(certHandle);
@@ -401,6 +405,7 @@
if(ssl->certName) free(ssl->certName);
if(ssl->peerName) free(ssl->peerName);
+ if(ssl->serverName) free(ssl->serverName);
if(ssl->dataBuf) free(ssl->dataBuf);
free(ssl);
@@ -423,6 +428,8 @@
SCHANNEL_CRED sc_cred = { 0 };
ULONG sslFlags, retFlags;
sqSSL *ssl = sslFromHandle(handle);
+ LPTSTR serverName = NULL;
+ int ccServerName = 0;
/* Verify state of session */
if(ssl == NULL || (ssl->state != SQSSL_UNUSED && ssl->state != SQSSL_CONNECTING)) {
@@ -433,9 +440,10 @@
/* resize the data buffer */
ssl->dataMax += (srcLen < 4096) ? (4096) : (srcLen+1024);
ssl->dataBuf = realloc(ssl->dataBuf, ssl->dataMax);
- if(!ssl->dataBuf) return SQSSL_OUT_OF_MEMORY;
+ if (!ssl->dataBuf) return SQSSL_OUT_OF_MEMORY;
}
- if(ssl->loglevel) printf("sqConnectSSL: input token %d bytes\n", srcLen);
+ if(ssl->loglevel)
+ printf("sqConnectSSL: input token %d bytes\n", srcLen);
memcpy(ssl->dataBuf + ssl->dataLen, srcBuf, srcLen);
ssl->dataLen += srcLen;
@@ -470,18 +478,32 @@
if(ssl->loglevel) printf("sqConnectSSL: Input to InitSecCtxt is %d bytes\n", ssl->dataLen);
+#ifdef _UNICODE
+ if(ssl->serverName) {
+ ccServerName = MultiByteToWideChar(CP_UTF8, 0, ssl->serverName, -1, NULL, 0);
+ if (ccServerName == 0) {
+ return SQSSL_GENERIC_ERROR;
+ }
+ serverName = (LPTSTR)alloca(ccServerName * sizeof(TCHAR));
+ if (MultiByteToWideChar(CP_UTF8, 0, ssl->serverName, -1, serverName, ccServerName) == 0) {
+ return SQSSL_GENERIC_ERROR;
+ }
+ }
+#else
+ if(ssl->serverName) serverName = ssl->serverName;
+#endif
+
if(ssl->state == SQSSL_UNUSED) {
ssl->state = SQSSL_CONNECTING;
- if(!sqSetupCert(ssl, ssl->certName, 0))
- /* FIXME. We need a different error code here. */
+ if (!sqSetupCert(ssl, ssl->certName, 0)) {
return SQSSL_GENERIC_ERROR;
-
- ret = InitializeSecurityContext(&ssl->sslCred, NULL, NULL,
+ }
+ ret = InitializeSecurityContext(&ssl->sslCred, NULL, serverName,
sslFlags, 0, 0, NULL, 0, &ssl->sslCtxt,
&ssl->sbdOut, &retFlags, NULL);
} else {
- ret = InitializeSecurityContext(&ssl->sslCred, &ssl->sslCtxt, NULL,
+ ret = InitializeSecurityContext(&ssl->sslCred, &ssl->sslCtxt, serverName,
sslFlags, 0, 0, &ssl->sbdIn, 0, NULL,
&ssl->sbdOut, &retFlags, NULL);
}
@@ -516,11 +538,11 @@
memmove(ssl->dataBuf, ssl->dataBuf + (ssl->dataLen - extra), extra);
ssl->dataLen = extra;
} else ssl->dataLen = 0;
-
+
/* Don't return zero (SQSSL_OK) when more data is needed */
return count ? count : SQSSL_NEED_MORE_DATA;
default:
- if(ssl->loglevel) printf("Unexpected return code %d\n", ret);
+ if(ssl->loglevel) printf("Unexpected return code %lu\n", (unsigned long)ret);
return SQSSL_GENERIC_ERROR;
}
}
@@ -799,6 +821,7 @@
switch(propID) {
case SQSSL_PROP_PEERNAME: return ssl->peerName;
case SQSSL_PROP_CERTNAME: return ssl->certName;
+ case SQSSL_PROP_SERVERNAME: return ssl->serverName;
default:
if(ssl->loglevel) printf("sqGetStringPropertySSL: Unknown property ID %d\n", propID);
return NULL;
@@ -838,7 +861,7 @@
if(!pfxStore) return 0;
/* And copy the certificates to MY store */
- myStore = CertOpenSystemStore(0, "MY");
+ myStore = CertOpenSystemStore(0, L"MY");
pContext = NULL;
while(pContext = CertEnumCertificatesInStore(pfxStore, pContext)) {
CertAddCertificateContextToStore(myStore, pContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
@@ -865,16 +888,27 @@
if(propLen) {
property = calloc(1, propLen+1);
memcpy(property, propName, propLen);
+ property[propLen] = '\0';
};
- if(ssl->loglevel) printf("sqSetStringPropertySSL(%d): %s\n", propID, property);
+ if(ssl->loglevel) printf("sqSetStringPropertySSL(%d): %s\n", propID, property ? property : "(null)");
switch(propID) {
- case SQSSL_PROP_CERTNAME: ssl->certName = property; break;
+ case SQSSL_PROP_CERTNAME:
+ if(ssl->certName) free(ssl->certName);
+ ssl->certName = property;
+ break;
+ case SQSSL_PROP_SERVERNAME:
+ if(ssl->serverName) free(ssl->serverName);
+ ssl->serverName = 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:
+ case 10001:
+ if(property) free(property);
+ return sqAddPfxCertToStore(propName, propLen, NULL, 0);
+ default:
+ if(property) free(property);
if(ssl->loglevel) printf("sqSetStringPropertySSL: Unknown property ID %d\n", propID);
return 0;
}
@@ -894,7 +928,7 @@
switch(propID) {
case SQSSL_PROP_SSLSTATE: return ssl->state;
case SQSSL_PROP_CERTSTATE: return ssl->certFlags;
- case SQSSL_PROP_VERSION: return 1;
+ case SQSSL_PROP_VERSION: return SQSSL_VERSION;
case SQSSL_PROP_LOGLEVEL: return ssl->loglevel;
default:
if(ssl->loglevel) printf("sqGetIntPropertySSL: Unknown property ID %d\n", propID);
@@ -911,6 +945,7 @@
Returns: Non-zero if successful.
*/
sqInt sqSetIntPropertySSL(sqInt handle, sqInt propID, sqInt propValue) {
+
sqSSL *ssl = sslFromHandle(handle);
if(ssl == NULL) return 0;
@@ -920,5 +955,5 @@
if(ssl->loglevel) printf("sqSetIntPropertySSL: Unknown property ID %d\n", propID);
return 0;
}
- return 0;
+ return 1;
}