Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend macOS implementation of SqueakSSL plugin to support setting a certificate on the SSL session context #812

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extracted/plugins/SqueakSSL/include/common/SqueakSSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#define SQSSL_PROP_PEERNAME 0
#define SQSSL_PROP_CERTNAME 1
#define SQSSL_PROP_SERVERNAME 2
#define SQSSL_PROP_CERTPASS 3

/* sqCreateSSL: Creates a new SSL instance.
Arguments: None.
Expand Down
70 changes: 69 additions & 1 deletion extracted/plugins/SqueakSSL/src/osx/sqMacSSL.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef struct sqSSL {
char* certName;
char* peerName;
char* serverName;
char* certPass;

SSLContextRef ctx;
CFArrayRef certs;
Expand Down Expand Up @@ -206,6 +207,62 @@ OSStatus sqSetupSSL(sqSSL* ssl, int isServer)
}
}

if (ssl->certName) {
size_t size = 128 * 1024;
char *buffer = malloc(size);
FILE *stream;
stream = fopen(ssl->certName, "rb");
if (buffer == NULL || stream == NULL)
return SQSSL_GENERIC_ERROR;
size_t length = fread(buffer, sizeof(char), size, stream);
int error = !feof(stream) || ferror(stream);
fclose(stream);
if (error) {
free(buffer);
return SQSSL_GENERIC_ERROR;
}
CFDataRef data = CFDataCreate(kCFAllocatorDefault, (UInt8 *)buffer, length);
free(buffer);
if (data == NULL)
return SQSSL_GENERIC_ERROR;

CFMutableDictionaryRef options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (options == NULL)
return SQSSL_GENERIC_ERROR;
if (ssl->certPass != NULL) {
const CFStringRef password = CFStringCreateWithCString(kCFAllocatorDefault, ssl->certPass, kCFStringEncodingASCII);
if (password == NULL) {
CFRelease(options);
return SQSSL_GENERIC_ERROR;
}
CFDictionarySetValue(options, kSecImportExportPassphrase, password);
CFRelease(password);
}

CFArrayRef items;
status = SecPKCS12Import(data, options, &items);
CFRelease(data);
CFRelease(options);
if (status != noErr) {
logStatus(status, "SecPKCS12Import failed");
return status;
}
if (!(CFArrayGetCount(items) >= 1))
return SQSSL_GENERIC_ERROR;
CFDictionaryRef item = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity);
if (identity == NULL)
return SQSSL_GENERIC_ERROR;
CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **)&identity, 1, &kCFTypeArrayCallBacks);

SSLSetCertificate(ssl->ctx, certs);
CFRelease(certs);
if (status != noErr) {
logStatus(status, "SSLSetCertificate failed");
return status;
}
}

return status;
}

Expand Down Expand Up @@ -479,6 +536,10 @@ sqInt sqDestroySSL(sqInt handle)
free(ssl->serverName);
ssl->serverName = NULL;
}
if (ssl->certPass) {
free(ssl->certPass);
ssl->certName = NULL;
}

free(ssl);
handleBuf[handle] = NULL;
Expand Down Expand Up @@ -626,7 +687,7 @@ sqInt sqAcceptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char* dstBuf,
}
/* We are connected. Verify the cert. */
ssl->state = SQSSL_CONNECTED;
return SQSSL_OK;
return ssl->outLen;
}

/* sqEncryptSSL: Encrypt data for SSL transmission.
Expand Down Expand Up @@ -729,6 +790,7 @@ char* sqGetStringPropertySSL(sqInt handle, int propID)
case SQSSL_PROP_PEERNAME: return ssl->peerName ? ssl->peerName : emptyString;
case SQSSL_PROP_CERTNAME: return ssl->certName;
case SQSSL_PROP_SERVERNAME: return ssl->serverName;
case SQSSL_PROP_CERTPASS: return ssl->certPass;
default:
logTrace("sqGetStringPropertySSL: Unknown property ID %d\n", propID);
return NULL;
Expand Down Expand Up @@ -774,6 +836,12 @@ sqInt sqSetStringPropertySSL(sqInt handle, int propID, char* propName,
}
ssl->serverName = property;
break;
case SQSSL_PROP_CERTPASS:
if (ssl->certPass) {
free(ssl->certPass);
}
ssl->certPass = property;
break;
default:
if (property) {
free(property);
Expand Down