Revision: 3417 Author: eliot Date: 2015-07-29 18:55:26 -0700 (Wed, 29 Jul 2015) Log Message: ----------- Integrate Marcel Taeumel & Tobias Pape's v2 SSL plugin changes.
Modified Paths: -------------- branches/Cog/platforms/Mac OS/plugins/SqueakSSL/sqMacSSL.c branches/Cog/platforms/unix/plugins/SqueakSSL/sqUnixOpenSSL.c
Added Paths: ----------- branches/Cog/platforms/Mac OS/plugins/SqueakSSL/Info.plist branches/Cog/platforms/unix/plugins/SqueakSSL/config.cmake
Property Changed: ---------------- branches/Cog/platforms/Cross/vm/sqSCCSVersion.h
Property changes on: branches/Cog/platforms/Cross/vm/sqSCCSVersion.h ___________________________________________________________________ Modified: checkindate - Mon Jul 20 23:17:35 PDT 2015 + Wed Jul 29 18:55:18 PDT 2015
Added: branches/Cog/platforms/Mac OS/plugins/SqueakSSL/Info.plist =================================================================== --- branches/Cog/platforms/Mac OS/plugins/SqueakSSL/Info.plist (rev 0) +++ branches/Cog/platforms/Mac OS/plugins/SqueakSSL/Info.plist 2015-07-30 01:55:26 UTC (rev 3417) @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>SqueakSSL</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>org.squeak.SqueakSSL</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleSignature</key> + <string>FAST</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CSResourcesFileMapped</key> + <true/> +</dict> +</plist>
Modified: branches/Cog/platforms/Mac OS/plugins/SqueakSSL/sqMacSSL.c =================================================================== --- branches/Cog/platforms/Mac OS/plugins/SqueakSSL/sqMacSSL.c 2015-07-30 01:51:21 UTC (rev 3416) +++ branches/Cog/platforms/Mac OS/plugins/SqueakSSL/sqMacSSL.c 2015-07-30 01:55:26 UTC (rev 3417) @@ -1,479 +1,683 @@ -/* sqMacSSL.c: SqueakSSL implementation based on Mac OSX Security Services */ +/**************************************************************************** + * PROJECT: SqueakSSL implementation for Mac OS X + * FILE: sqMac2SSL.c + * CONTENT: SSL platform functions + * + * AUTHORS: Andreas Raab (ar) + * + * Tobias Pape (topa) + * Hasso Plattner Institute, Postdam, Germany + *****************************************************************************/ #include "sq.h" #include "SqueakSSL.h" +#include <string.h> +#include <stdarg.h>
-#include <Security/Security.h> -#include <Security/SecCertificate.h> +#import <Security/Security.h>
typedef struct sqSSL { - int state; - int certFlags; - int loglevel; + int state; + int certFlags; + int loglevel;
- char *certName; - char *peerName; + char* certName; + char* peerName; + char* serverName;
- - SSLContextRef ctx; - CFArrayRef certs; + SSLContextRef ctx; + CFArrayRef certs;
- /* internal data buffer */ - char *dataBuf; - int dataLen; - int dataMax; - - /* external data buffer */ - char *outBuf; - int outLen; - int outMax; + /* internal data buffer */ + char* dataBuf; + int dataLen; + int dataMax; + + /* external data buffer */ + char* outBuf; + int outLen; + int outMax; } sqSSL;
-static sqSSL **handleBuf = NULL; +/********************************************************************/ +#pragma mark Global State +/********************************************************************/ + +static sqSSL** handleBuf = NULL; static sqInt handleMax = 0;
+// Max lengh of a Certificate common name or DNS Host name +#define CN_MAX 255
+ /********************************************************************/ +#pragma mark Forward Declarations /********************************************************************/ + +static int printf_status(OSStatus status, const char* restrict format, ...); +static OSStatus sqExtractPeerName(sqSSL* ssl); +static sqSSL* sqSSLFromHandle(sqInt handle); +OSStatus sqSetupSSL(sqSSL* ssl, int isServer); + +OSStatus SqueakSSLRead(SSLConnectionRef connection, void* data, + size_t* dataLength); + +OSStatus SqueakSSLWrite(SSLConnectionRef connection, const void* data, + size_t* dataLength); + + /********************************************************************/ +#pragma mark - +#pragma mark Internal Helper +/********************************************************************/
-/* SqueakSSLRead: Custom read function for Secure Transport */ -OSStatus SqueakSSLRead(SSLConnectionRef connection, void *data, - size_t *dataLength) { - sqSSL *ssl = (sqSSL*) connection; - size_t sz = *dataLength; +static int printf_status(OSStatus status, const char* restrict format, ...) +{ + int ret = 0; + va_list args; + va_start(args, format); + CFErrorRef _e = CFErrorCreate(NULL, kCFErrorDomainOSStatus, status, NULL); + CFStringRef _sdesc = CFErrorCopyDescription(_e); + CFStringRef _sreas = CFErrorCopyFailureReason(_e); + CFStringRef _sreco = CFErrorCopyRecoverySuggestion(_e); + ret += vprintf(format, args); + ret += printf("Status (%d): %s (%s): %s\n", + (int)status, + CFStringGetCStringPtr(_sdesc, kCFStringEncodingUTF8), + CFStringGetCStringPtr(_sreas, kCFStringEncodingUTF8), + CFStringGetCStringPtr(_sreco, kCFStringEncodingUTF8)); + CFRelease(_sreco); + CFRelease(_sreas); + CFRelease(_sdesc); + CFRelease(_e); + va_end(args); + return ret; +}
- if(ssl->loglevel) - printf("SqueakSSLRead: Requesting %d bytes, having %d bytes\n", - (int)sz, ssl->dataLen); - if(ssl->dataLen < sz) sz = ssl->dataLen; - memcpy(data, ssl->dataBuf, sz); - /* Did we have enough data? */ - if(sz == *dataLength) { - /* Adjust read buffer */ - memmove(ssl->dataBuf, ssl->dataBuf+sz, ssl->dataLen - sz); - ssl->dataLen -= sz; - *dataLength = sz; - return noErr; - } - ssl->dataLen = 0; - *dataLength = sz; - return errSSLWouldBlock; +/* By convention, the sqSSL object is named ssl and has its logLevel >= 0 */ +#define logprintf if (ssl->loglevel) printf +#define logprintf_status if (ssl->loglevel) printf_status + +/* sqSSLFromHandle: Maps a handle to an SSL */ +static sqSSL* sqSSLFromHandle(sqInt handle) +{ + return handle < handleMax ? handleBuf[handle] : NULL; }
-/* SqueakSSLRead: Custom write function for Secure Transport */ -OSStatus SqueakSSLWrite(SSLConnectionRef connection, const void *data, - size_t *dataLength) { - sqSSL *ssl = (sqSSL*) connection; - size_t sz = ssl->outMax - ssl->outLen; - - if(ssl->loglevel) - printf("SqueakSSLWrite: Writing %d bytes, having %d free\n", - (int)*dataLength, (int)sz); - if(sz == 0) { - *dataLength = 0; - return errSSLWouldBlock; - } - if(*dataLength < sz) sz = *dataLength; - memcpy(ssl->outBuf + ssl->outLen, data, sz); - ssl->outLen += sz; - *dataLength = sz; - return noErr; +/* sqSetupSSL: Common SSL setup task */ +OSStatus sqSetupSSL(sqSSL* ssl, int isServer) +{ + OSStatus status = noErr; + + logprintf("sqSetupSSL: Setting up new context\n"); + /* Create the new context */ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + ssl->ctx = SSLCreateContext(NULL, + isServer ? kSSLServerSide : kSSLClientSide, + kSSLStreamType); +#else + status = SSLNewContext(isServer, &ssl->ctx); + if (status != noErr) { + logprintf_status(status, "SSLNewContext failed"); + return status; + } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + + /* Set the connection ref */ + status = SSLSetConnection(ssl->ctx, ssl); + if (status != noErr) { + logprintf_status(status, "SSLSetConnection failed"); + return status; + } + + /* Set up the read/write functions */ + status = SSLSetIOFuncs(ssl->ctx, SqueakSSLRead, SqueakSSLWrite); + if (status != noErr) { + logprintf_status(status, "SSLSetIOFuncs failed"); + return status; + } + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + /* At least TLS 1 */ + status = SSLSetProtocolVersionMin(ssl->ctx, kTLSProtocol1); +#else + /* Prefer TLS 1 */ + status = SSLSetProtocolVersionEnabled(ssl->ctx, kTLSProtocol1, true); +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + if (status != noErr) { + logprintf_status(status, "SSLSetProtocolVersion{Min,Enabled} failed"); + return status; + } + + + /* Disable cert verification since we do that ourselves */ + status = SSLSetEnableCertVerify(ssl->ctx, false); + if (status != noErr) { + logprintf_status(status, "SSLSetEnableCertVerify failed"); + return status; + } + + if (ssl->serverName) { + /* Try for SNI */ +#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= 1070) + status = SSLSetPeerDomainName(ssl->ctx, ssl->serverName, + strlen(ssl->serverName)); +#else + status = SSLSetPeerDomainName(ssl->ctx, ssl->serverName, + strnlen(ssl->serverName, CN_MAX - 1)); +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if (status != noErr) { + logprintf_status(status, "SSLSetPeerDomainName failed"); + return status; + } + } + + return status; }
+/* sqExtractPeerName: Extract a copy of the first common name from the + certificate obtained in a handshake + */ +static OSStatus sqExtractPeerName(sqSSL* ssl) +{ + OSStatus status = noErr; + if (CFArrayGetCount(ssl->certs) <= 0) { + // No cert -> no peer name available + return status; + } + + char peerName[CN_MAX + 1]; + CFStringRef cfName = NULL; + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(ssl->certs, 0); + status = SecCertificateCopyCommonName(cert, &cfName); + if (status == noErr) { + CFStringGetCString(cfName, peerName, sizeof(peerName), kCFStringEncodingUTF8); +#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= 1070) + ssl->peerName = strdup(peerName); +#else + ssl->peerName = strndup(peerName, CN_MAX); +#endif + CFRelease(cfName); + } + return status; +} + + +#pragma mark - +#pragma mark Callbacks + /********************************************************************/ /********************************************************************/ /********************************************************************/
-/* sslFromHandle: Maps a handle to an SSL */ -static sqSSL *sslFromHandle(sqInt handle) { - return handle < handleMax ? handleBuf[handle] : NULL; -} +/* SqueakSSLRead: Custom read function for Secure Transport */ +OSStatus SqueakSSLRead(SSLConnectionRef connection, void* data, + size_t* dataLength) +{ + sqSSL* ssl = (sqSSL*)connection; + size_t sz = *dataLength;
-/* sqSetupSSL: Common SSL setup task */ + logprintf("SqueakSSLRead: Requesting %d bytes, having %d bytes\n", + (int)sz, ssl->dataLen);
-int sqSetupSSL(sqSSL *ssl, int isServer) { - OSStatus status; + if (ssl->dataLen < sz) { + sz = ssl->dataLen; + } + memcpy(data, ssl->dataBuf, sz);
- if(ssl->loglevel) printf("sqSetupSSL: Setting up new context\n"); - /* Create the new context */ - status = SSLNewContext(isServer, &ssl->ctx); - if(status) { - if(ssl->loglevel) printf("SSLNewContext failed: code = %d\n", (int)status); - return 0; - } - /* Set the connection ref */ - status = SSLSetConnection(ssl->ctx, ssl); - if(status) { - if(ssl->loglevel) printf("SSLSetConnection failed: code = %d\n", (int)status); - return 0; - } - - /* Set up the read/write functions */ - status = SSLSetIOFuncs(ssl->ctx,SqueakSSLRead, SqueakSSLWrite); - if(status) { - if(ssl->loglevel) printf("SSLSetIOFuncs failed: code = %d\n", (int)status); - return 0; - } + /* Did we have enough data? */ + if (sz == *dataLength) { + /* Adjust read buffer */ + memmove(ssl->dataBuf, ssl->dataBuf+sz, ssl->dataLen - sz); + ssl->dataLen -= sz; + *dataLength = sz; + return noErr; + }
- /* Enable desired protocols */ - status = SSLSetProtocolVersionEnabled(ssl->ctx, kSSLProtocol2, false); - if(status) { - if(ssl->loglevel) printf("SSLSetProtocolVersionEnabled failed: code = %d\n", (int)status); - return 0; - } + ssl->dataLen = 0; + *dataLength = sz; + return errSSLWouldBlock; +}
- status = SSLSetProtocolVersionEnabled(ssl->ctx, kSSLProtocol3, true); - if(status) { - if(ssl->loglevel) printf("SSLSetProtocolVersionEnabled failed: code = %d\n", (int)status); - return 0; - } +/* SqueakSSLRead: Custom write function for Secure Transport */ +OSStatus SqueakSSLWrite(SSLConnectionRef connection, const void* data, + size_t* dataLength) +{ + sqSSL* ssl = (sqSSL*)connection; + size_t sz = ssl->outMax - ssl->outLen;
- status = SSLSetProtocolVersionEnabled(ssl->ctx, kTLSProtocol1, true); - if(status) { - if(ssl->loglevel) printf("SSLSetProtocolVersionEnabled failed: code = %d\n", (int)status); - return 0; - } - /* Disable cert verification since we do that ourselves */ - status = SSLSetEnableCertVerify(ssl->ctx, false); - if(status) { - if(ssl->loglevel) printf("SSLSetEnableCertVerify failed: code = %d\n", (int)status); - return 0; - } + logprintf("SqueakSSLWrite: Writing %d bytes, having %d free\n", + (int)*dataLength, (int)sz); + if (sz == 0) { + *dataLength = 0; + return errSSLWouldBlock; + }
- return 1; + if (*dataLength < sz) { + sz = *dataLength; + } + memcpy(ssl->outBuf + ssl->outLen, data, sz); + ssl->outLen += sz; + *dataLength = sz; + return noErr; }
/********************************************************************/ +#pragma mark - +#pragma mark Plugin Interface /********************************************************************/ -/********************************************************************/
/* sqCreateSSL: Creates a new SSL instance. - Arguments: None. - Returns: SSL handle. + Arguments: None. + Returns: SSL handle. */ -sqInt sqCreateSSL(void) { - sqInt handle = 0; - sqSSL *ssl = NULL; +sqInt sqCreateSSL(void) +{ + sqInt handle = 0; + sqSSL* ssl = NULL;
- ssl = calloc(1, sizeof(sqSSL)); - ssl->loglevel = 0; + ssl = calloc(1, sizeof(sqSSL)); + ssl->loglevel = 0;
- /* Find a free handle */ - for(handle = 1; handle < handleMax; handle++) - if(handleBuf[handle] == NULL) break; + /* Find a free handle */ + for (handle = 1; handle < handleMax; handle++) { + if (handleBuf[handle] == NULL) { + break; + } + }
- if(handle >= handleMax) { - int i, delta = 100; - /* Resize the handle buffer */ - handleBuf = realloc(handleBuf, (handleMax+delta)*sizeof(void*)); - for(i = handleMax; i < handleMax+delta; i++) - handleBuf[i] = NULL; - handleMax += delta; - } - handleBuf[handle] = ssl; - return handle; + if (handle >= handleMax) { + int delta = 100; + /* Resize the handle buffer */ + handleBuf = (sqSSL**)realloc(handleBuf, + (handleMax + delta) * sizeof(sqSSL*)); + for (int i = handleMax; i < handleMax + delta; i++) { + handleBuf[i] = NULL; + } + handleMax += delta; + } + handleBuf[handle] = ssl; + return handle; }
/* sqDestroySSL: Destroys an SSL instance. - Arguments: - handle - the SSL handle - Returns: Non-zero if successful. + Arguments: + handle - the SSL handle + Returns: Non-zero if successful. */ -sqInt sqDestroySSL(sqInt handle) { - sqSSL *ssl = sslFromHandle(handle); - if(ssl == NULL) return 0; +sqInt sqDestroySSL(sqInt handle) +{ + sqSSL* ssl = sqSSLFromHandle(handle); + if (ssl == NULL) { + return 0; + }
- if(ssl->certName) free(ssl->certName); - if(ssl->peerName) free(ssl->peerName); + if (ssl->ctx) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + CFRelease(ssl->ctx); +#else + SSLDisposeContext(ssl->ctx); +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + }
- free(ssl); - handleBuf[handle] = NULL; - return 1; + if (ssl->certName) { + free(ssl->certName); + } + if (ssl->peerName) { + free(ssl->peerName); + } + if (ssl->serverName) { + free(ssl->serverName); + } + + free(ssl); + handleBuf[handle] = NULL; + return 1; }
/* sqConnectSSL: Start/continue an SSL client handshake. - Arguments: - handle - the SSL handle - srcBuf - the input token sent by the remote peer - srcLen - the size of the input token - dstBuf - the output buffer for a new token - dstLen - the size of the output buffer - Returns: The size of the output token or an error code. + Arguments: + handle - the SSL handle + srcBuf - the input token sent by the remote peer + srcLen - the size of the input token + dstBuf - the output buffer for a new token + dstLen - the size of the output buffer + Returns: The size of the output token or an error code. */ -sqInt sqConnectSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen) { - OSStatus status; - sqSSL *ssl = sslFromHandle(handle); +sqInt sqConnectSSL(sqInt handle, char* srcBuf, sqInt srcLen, char* dstBuf, + sqInt dstLen) +{ + OSStatus status; + sqSSL* ssl = sqSSLFromHandle(handle);
- if(ssl->loglevel) printf("sqConnectSSL: %x\n", (int)ssl); + logprintf("sqConnectSSL: %x\n", (int)ssl);
- /* Verify state of session */ - if(ssl == NULL || (ssl->state != SQSSL_UNUSED && ssl->state != SQSSL_CONNECTING)) { - return SQSSL_INVALID_STATE; - } + /* Verify state of session */ + if (ssl == NULL + || (ssl->state != SQSSL_UNUSED && ssl->state != SQSSL_CONNECTING)) { + return SQSSL_INVALID_STATE; + }
- /* Set up the output buffer */ - ssl->outBuf = dstBuf; - ssl->outLen = 0; - ssl->outMax = dstLen; + /* Set up the output buffer */ + ssl->outBuf = dstBuf; + ssl->outLen = 0; + ssl->outMax = dstLen;
- if(ssl->dataLen + srcLen > ssl->dataMax) { - /* 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->loglevel) printf("sqConnectSSL: input token %d bytes\n", srcLen); - memcpy(ssl->dataBuf + ssl->dataLen, srcBuf, srcLen); - ssl->dataLen += srcLen; + if (ssl->dataLen + srcLen > ssl->dataMax) { + /* 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; + } + } + logprintf("sqConnectSSL: input token %d bytes\n", srcLen); + memcpy(ssl->dataBuf + ssl->dataLen, srcBuf, srcLen); + ssl->dataLen += srcLen;
- /* Establish initial connection */ - if(ssl->state == SQSSL_UNUSED) { - ssl->state = SQSSL_CONNECTING; - if(ssl->loglevel) printf("sqConnectSSL: Setting up SSL\n"); - if(!sqSetupSSL(ssl, 0)) return SQSSL_GENERIC_ERROR; - } + /* Establish initial connection */ + if (ssl->state == SQSSL_UNUSED) { + ssl->state = SQSSL_CONNECTING; + logprintf("sqConnectSSL: Setting up SSL\n"); + status = sqSetupSSL(ssl, 0); + if (status != noErr) { + return SQSSL_GENERIC_ERROR; + } + }
- status = SSLHandshake(ssl->ctx); - if(status == errSSLWouldBlock) { - /* Return token to caller */ - if(ssl->loglevel) printf("sqConnectSSL: Produced %d token bytes\n", ssl->outLen); - return ssl->outLen ? ssl->outLen : SQSSL_NEED_MORE_DATA; - } - if(status != noErr) { - if(ssl->loglevel) printf("sqConnectSSL: SSLHandshake returned %d\n", (int)status); - return SQSSL_GENERIC_ERROR; - } - /* We are connected. Verify the cert. */ - ssl->state = SQSSL_CONNECTED; - ssl->certFlags = -1; + status = SSLHandshake(ssl->ctx); + if (status == errSSLWouldBlock) { + /* Return token to caller */ + logprintf("sqConnectSSL: Produced %d token bytes\n", ssl->outLen); + return ssl->outLen ? ssl->outLen : SQSSL_NEED_MORE_DATA; + } + if (status != noErr) { + logprintf_status(status, "sqConnectSSL: SSLHandshake"); + return SQSSL_GENERIC_ERROR; + } + /* We are connected. Verify the cert. */ + ssl->state = SQSSL_CONNECTED; + ssl->certFlags = -1;
- /* Extract the peer name from the cert */ - status = SSLCopyPeerCertificates(ssl->ctx, &ssl->certs); - if(status == noErr) { - if(CFArrayGetCount(ssl->certs) > 0) { - char peerName[256]; - CFStringRef cfName; - SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(ssl->certs, 0); - status = SecCertificateCopyCommonName(cert, &cfName); - if(status == noErr) { - CFStringGetCString(cfName, peerName, sizeof(peerName), kCFStringEncodingUTF8); - ssl->peerName = strdup(peerName); - CFRelease(cfName); - } - } - } - return 0; + /* Extract the peer name from the cert */ + status = SSLCopyPeerCertificates(ssl->ctx, &ssl->certs); + if (status == noErr) { + sqExtractPeerName(ssl); + } + return SQSSL_OK; }
/* sqAcceptSSL: Start/continue an SSL server handshake. - Arguments: - handle - the SSL handle - srcBuf - the input token sent by the remote peer - srcLen - the size of the input token - dstBuf - the output buffer for a new token - dstLen - the size of the output buffer - Returns: The size of the output token or an error code. + Arguments: + handle - the SSL handle + srcBuf - the input token sent by the remote peer + srcLen - the size of the input token + dstBuf - the output buffer for a new token + dstLen - the size of the output buffer + Returns: The size of the output token or an error code. */ -sqInt sqAcceptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen) { - OSStatus status; - sqSSL *ssl = sslFromHandle(handle); +sqInt sqAcceptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char* dstBuf, + sqInt dstLen) +{ + OSStatus status = noErr; + sqSSL* ssl = sqSSLFromHandle(handle);
- /* Verify state of session */ - if(ssl == NULL || (ssl->state != SQSSL_UNUSED && ssl->state != SQSSL_ACCEPTING)) { - return SQSSL_INVALID_STATE; - } + /* Verify state of session */ + if (ssl == NULL + || (ssl->state != SQSSL_UNUSED && ssl->state != SQSSL_ACCEPTING)) { + return SQSSL_INVALID_STATE; + }
- /* Set up the output buffer */ - ssl->outBuf = dstBuf; - ssl->outLen = 0; - ssl->outMax = dstLen; - - if(ssl->dataLen + srcLen > ssl->dataMax) { - /* 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->loglevel) printf("sqConnectSSL: input token %d bytes\n", srcLen); - memcpy(ssl->dataBuf + ssl->dataLen, srcBuf, srcLen); - ssl->dataLen += srcLen; - - /* Establish initial connection */ - if(ssl->state == SQSSL_UNUSED) { - ssl->state = SQSSL_ACCEPTING; - if(ssl->loglevel) printf("sqAcceptSSL: Setting up SSL\n"); - if(!sqSetupSSL(ssl, 1)) return SQSSL_GENERIC_ERROR; - if(ssl->loglevel) printf("sqAcceptSSL: setting accept state\n"); - } + /* Set up the output buffer */ + ssl->outBuf = dstBuf; + ssl->outLen = 0; + ssl->outMax = dstLen;
- status = SSLHandshake(ssl->ctx); - if(status == errSSLWouldBlock) { - /* Return token to caller */ - return ssl->outLen ? ssl->outLen : SQSSL_NEED_MORE_DATA; - } - if(status != noErr) { - if(ssl->loglevel) printf("sqConnectSSL: SSLHandshake returned %d\n", (int)status); - return SQSSL_GENERIC_ERROR; - } - /* We are connected. Verify the cert. */ - ssl->state = SQSSL_CONNECTED; - return 0; + if (ssl->dataLen + srcLen > ssl->dataMax) { + /* 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; + } + } + logprintf("sqConnectSSL: input token %d bytes\n", srcLen); + memcpy(ssl->dataBuf + ssl->dataLen, srcBuf, srcLen); + ssl->dataLen += srcLen; + + /* Establish initial connection */ + if (ssl->state == SQSSL_UNUSED) { + ssl->state = SQSSL_ACCEPTING; + logprintf("sqAcceptSSL: Setting up SSL\n"); + status = sqSetupSSL(ssl, 1); + if (status != noErr) { + return SQSSL_GENERIC_ERROR; + } + logprintf("sqAcceptSSL: setting accept state\n"); + } + + status = SSLHandshake(ssl->ctx); + if (status == errSSLWouldBlock) { + /* Return token to caller */ + return ssl->outLen ? ssl->outLen : SQSSL_NEED_MORE_DATA; + } + if (status != noErr) { + logprintf("sqConnectSSL: SSLHandshake returned %d\n", (int)status); + return SQSSL_GENERIC_ERROR; + } + /* We are connected. Verify the cert. */ + ssl->state = SQSSL_CONNECTED; + return SQSSL_OK; }
/* sqEncryptSSL: Encrypt data for SSL transmission. - Arguments: - handle - the SSL handle - srcBuf - the unencrypted input data - srcLen - the size of the input data - dstBuf - the output buffer for the encrypted contents - dstLen - the size of the output buffer - Returns: The size of the output generated or an error code. + Arguments: + handle - the SSL handle + srcBuf - the unencrypted input data + srcLen - the size of the input data + dstBuf - the output buffer for the encrypted contents + dstLen - the size of the output buffer + Returns: The size of the output generated or an error code. */ -sqInt sqEncryptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen) { - size_t nbytes; - OSStatus status; - sqSSL *ssl = sslFromHandle(handle); +sqInt sqEncryptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char* dstBuf, + sqInt dstLen) +{ + size_t nbytes = 0; + OSStatus status = noErr; + sqSSL* ssl = sqSSLFromHandle(handle);
- if(ssl == NULL || ssl->state != SQSSL_CONNECTED) return SQSSL_INVALID_STATE; + if (ssl == NULL || ssl->state != SQSSL_CONNECTED) { + return SQSSL_INVALID_STATE; + }
- /* Set up the output buffer */ - ssl->outBuf = dstBuf; - ssl->outLen = 0; - ssl->outMax = dstLen; - - if(ssl->loglevel) printf("sqEncryptSSL: Encrypting %d bytes\n", srcLen); + /* Set up the output buffer */ + ssl->outBuf = dstBuf; + ssl->outLen = 0; + ssl->outMax = dstLen;
- status = SSLWrite(ssl->ctx, srcBuf, srcLen, &nbytes); - if(nbytes != srcLen) return SQSSL_GENERIC_ERROR; - if(status == errSSLWouldBlock || status == noErr) return ssl->outLen; - if(ssl->loglevel) printf("sqDecryptSSL: SSLWrite returned %d\n", (int)status); - return SQSSL_GENERIC_ERROR; + logprintf("sqEncryptSSL: Encrypting %d bytes\n", srcLen); + + status = SSLWrite(ssl->ctx, srcBuf, srcLen, &nbytes); + if (nbytes != srcLen) { + return SQSSL_GENERIC_ERROR; + } + if (status == errSSLWouldBlock || status == noErr + || status == errSSLClosedGraceful) { + return ssl->outLen; + } + logprintf_status(status, "sqDecryptSSL: SSLWrite"); + return SQSSL_GENERIC_ERROR; }
/* sqDecryptSSL: Decrypt data for SSL transmission. - Arguments: - handle - the SSL handle - srcBuf - the encrypted input data - srcLen - the size of the input data - dstBuf - the output buffer for the decrypted contents - dstLen - the size of the output buffer - Returns: The size of the output generated or an error code. + Arguments: + handle - the SSL handle + srcBuf - the encrypted input data + srcLen - the size of the input data + dstBuf - the output buffer for the decrypted contents + dstLen - the size of the output buffer + Returns: The size of the output generated or an error code. */ -sqInt sqDecryptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen) { - size_t nbytes = 0; - OSStatus status; - sqSSL *ssl = sslFromHandle(handle); +sqInt sqDecryptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char* dstBuf, + sqInt dstLen) +{ + size_t nbytes = 0; + OSStatus status = noErr; + sqSSL* ssl = sqSSLFromHandle(handle);
- if(ssl == NULL || ssl->state != SQSSL_CONNECTED) return SQSSL_INVALID_STATE; + if (ssl == NULL || ssl->state != SQSSL_CONNECTED) { + return SQSSL_INVALID_STATE; + }
- if(ssl->dataLen + srcLen > ssl->dataMax) { - /* resize the read 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->loglevel) printf("sqDecryptSSL: Input data %d bytes\n", srcLen); - memcpy(ssl->dataBuf + ssl->dataLen, srcBuf, srcLen); - ssl->dataLen += srcLen; - - if(ssl->loglevel) printf("sqDecryptSSL: Decrypting %d bytes\n", ssl->dataLen); + if (ssl->dataLen + srcLen > ssl->dataMax) { + /* resize the read buffer */ + ssl->dataMax += (srcLen < 4096) ? (4096) : (srcLen + 1024); + ssl->dataBuf = realloc(ssl->dataBuf, ssl->dataMax); + if (!ssl->dataBuf) { + return SQSSL_OUT_OF_MEMORY; + } + } + logprintf("sqDecryptSSL: Input data %d bytes\n", srcLen); + memcpy(ssl->dataBuf + ssl->dataLen, srcBuf, srcLen); + ssl->dataLen += srcLen;
- status = SSLRead(ssl->ctx, dstBuf, dstLen, &nbytes); - if(status == errSSLWouldBlock || status == noErr) return nbytes; - if(ssl->loglevel) printf("sqDecryptSSL: SSLRead returned %d\n", (int)status); - return SQSSL_GENERIC_ERROR; + logprintf("sqDecryptSSL: Decrypting %d bytes\n", ssl->dataLen); + + status = SSLRead(ssl->ctx, dstBuf, dstLen, &nbytes); + if (status == errSSLWouldBlock || status == noErr + || status == errSSLClosedGraceful) { + return nbytes; + } + logprintf_status(status, "sqDecryptSSL: SSLRead"); + return SQSSL_GENERIC_ERROR; }
/* sqGetStringPropertySSL: Retrieve a string property from SSL. - Arguments: - handle - the ssl handle - propID - the property id to retrieve - Returns: The string value of the property. + Arguments: + handle - the ssl handle + propID - the property id to retrieve + Returns: The string value of the property. */ -char* sqGetStringPropertySSL(sqInt handle, int propID) { - sqSSL *ssl = sslFromHandle(handle); +char* sqGetStringPropertySSL(sqInt handle, int propID) +{ + sqSSL* ssl = sqSSLFromHandle(handle);
- if(ssl == NULL) return NULL; - switch(propID) { - case SQSSL_PROP_PEERNAME: return ssl->peerName; - case SQSSL_PROP_CERTNAME: return ssl->certName; - default: - if(ssl->loglevel) printf("sqGetStringPropertySSL: Unknown property ID %d\n", propID); - return NULL; - } - return NULL; + if (ssl == NULL) { + return NULL; + } + + switch (propID) { + case SQSSL_PROP_PEERNAME: return ssl->peerName; + case SQSSL_PROP_CERTNAME: return ssl->certName; + case SQSSL_PROP_SERVERNAME: return ssl->serverName; + default: + logprintf("sqGetStringPropertySSL: Unknown property ID %d\n", propID); + return NULL; + } + return NULL; }
/* sqSetStringPropertySSL: Set a string property in SSL. - Arguments: - handle - the ssl handle - propID - the property id to retrieve - propName - the property string - propLen - the length of the property string - Returns: Non-zero if successful. + Arguments: + handle - the ssl handle + propID - the property id to retrieve + propName - the property string + propLen - the length of the property string + Returns: Non-zero if successful. */ -sqInt sqSetStringPropertySSL(sqInt handle, int propID, char *propName, sqInt propLen) { - sqSSL *ssl = sslFromHandle(handle); - char *property = NULL; +sqInt sqSetStringPropertySSL(sqInt handle, int propID, char* propName, + sqInt propLen) +{ + sqSSL* ssl = sqSSLFromHandle(handle); + char* property = NULL;
- if(ssl == NULL) return 0; + if (ssl == NULL) return 0;
- if(propLen) { - property = calloc(1, propLen+1); - memcpy(property, propName, propLen); - }; + if (propLen) { + property = malloc(propLen + 1); + memcpy(property, propName, propLen); + property[propLen] = '\0'; + }
- if(ssl->loglevel) printf("sqSetStringPropertySSL(%d): %s\n", propID, property); + logprintf("sqSetStringPropertySSL(%d): %s\n", + propID, property ? property : "(null)");
- switch(propID) { - case SQSSL_PROP_CERTNAME: ssl->certName = property; break; - default: - if(ssl->loglevel) printf("sqSetStringPropertySSL: Unknown property ID %d\n", propID); - return 0; - } - return 1; + switch(propID) { + 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; + default: + if (property) { + free(property); + } + logprintf("sqSetStringPropertySSL: Unknown property ID %d\n", propID); + return 0; + } + return 1; }
/* sqGetIntPropertySSL: Retrieve an integer property from SSL. - Arguments: - handle - the ssl handle - propID - the property id to retrieve - Returns: The integer value of the property. + Arguments: + handle - the ssl handle + propID - the property id to retrieve + Returns: The integer value of the property. */ -int sqGetIntPropertySSL(sqInt handle, int propID) { - sqSSL *ssl = sslFromHandle(handle); +int sqGetIntPropertySSL(sqInt handle, int propID) +{ + sqSSL* ssl = sqSSLFromHandle(handle);
- if(ssl == NULL) return 0; - 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_LOGLEVEL: return ssl->loglevel; - default: - if(ssl->loglevel) printf("sqGetIntPropertySSL: Unknown property ID %d\n", propID); - return 0; - } - return 0; + if (ssl == NULL) { + return 0; + } + + switch(propID) { + case SQSSL_PROP_SSLSTATE: return ssl->state; + case SQSSL_PROP_CERTSTATE: return ssl->certFlags; + case SQSSL_PROP_VERSION: return SQSSL_VERSION; + case SQSSL_PROP_LOGLEVEL: return ssl->loglevel; + default: + logprintf("sqGetIntPropertySSL: Unknown property ID %d\n", propID); + return 0; + } + return 0; }
/* sqSetIntPropertySSL: Set an integer property in SSL. - Arguments: - handle - the ssl handle - propID - the property id to retrieve - propValue - the property value - Returns: Non-zero if successful. + Arguments: + handle - the ssl handle + propID - the property id to retrieve + propValue - the property value + Returns: Non-zero if successful. */ -sqInt sqSetIntPropertySSL(sqInt handle, sqInt propID, sqInt propValue) { - sqSSL *ssl = sslFromHandle(handle); - if(ssl == NULL) return 0; +sqInt sqSetIntPropertySSL(sqInt handle, sqInt propID, sqInt propValue) +{ + sqSSL* ssl = sqSSLFromHandle(handle); + if (ssl == NULL) { + return 0; + }
- switch(propID) { - case SQSSL_PROP_LOGLEVEL: ssl->loglevel = propValue; break; - default: - if(ssl->loglevel) printf("sqSetIntPropertySSL: Unknown property ID %d\n", propID); - return 0; - } - return 1; + switch(propID) { + case SQSSL_PROP_SSLSTATE: // falltrough + case SQSSL_PROP_CERTSTATE: // falltrough + case SQSSL_PROP_VERSION: + logprintf("sqSetIntPropertySSL: property is readonly %d\n", propID); + break; + case SQSSL_PROP_LOGLEVEL: + ssl->loglevel = propValue; + break; + default: + logprintf("sqSetIntPropertySSL: Unknown property ID %d\n", propID); + return 0; + } + return 1; }
Added: branches/Cog/platforms/unix/plugins/SqueakSSL/config.cmake =================================================================== --- branches/Cog/platforms/unix/plugins/SqueakSSL/config.cmake (rev 0) +++ branches/Cog/platforms/unix/plugins/SqueakSSL/config.cmake 2015-07-30 01:55:26 UTC (rev 3417) @@ -0,0 +1 @@ +PLUGIN_REQUIRE_PACKAGE (OPENSSL openssl)
Modified: branches/Cog/platforms/unix/plugins/SqueakSSL/sqUnixOpenSSL.c =================================================================== --- branches/Cog/platforms/unix/plugins/SqueakSSL/sqUnixOpenSSL.c 2015-07-30 01:51:21 UTC (rev 3416) +++ branches/Cog/platforms/unix/plugins/SqueakSSL/sqUnixOpenSSL.c 2015-07-30 01:55:26 UTC (rev 3417) @@ -37,7 +37,7 @@ sqInt sqCopyBioSSL(sqSSL *ssl, BIO *bio, char *dstBuf, sqInt dstLen) { int nbytes = BIO_ctrl_pending(bio);
- if(ssl->loglevel) printf("sqCopyBioSSL: %d bytes pending; buffer size %d\n", + if(ssl->loglevel) printf("sqCopyBioSSL: %d bytes pending; buffer size %ld\n", nbytes, dstLen); if(nbytes > dstLen) return -1; return BIO_read(bio, dstBuf, dstLen); @@ -439,7 +439,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); @@ -462,7 +462,7 @@ switch(propID) { case SQSSL_PROP_LOGLEVEL: ssl->loglevel = propValue; break; default: - if(ssl->loglevel) printf("sqSetIntPropertySSL: Unknown property ID %d\n", propID); + if(ssl->loglevel) printf("sqSetIntPropertySSL: Unknown property ID %ld\n", propID); return 0; } return 1;
vm-dev@lists.squeakfoundation.org