pharo-project / pharo-vm

This is the VM used by Pharo
http://pharo.org
Other
113 stars 68 forks source link

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

Closed Rinzwind closed 3 months ago

Rinzwind commented 4 months ago

This pull request extends the macOS implementation of the SqueakSSL plugin to support setting a certificate on the SSL session context. The certificate and private key can be given by setting the ‘CERTNAME’ property to the path of a PKCS#12 file (the Windows implementation expects the property to be set to the name of a certificate in a certificate store, while the Unix implementation expects the path to a PEM file). The function ‘SecPKCS12Import’ that is used to read the PKCS#12 file seems to require it to have a non-empty password, so a property ‘CERTPASS’ for giving the password is added. Commit 3d9d9004f7c305c2 also fixes a bug in ‘sqAcceptSSL’.

This can be used to set up a ZnSecureServer on macOS as follows (which assumes #certificatePassword: has been implemented similarly to the implementation of #certificate: and #certificateName: on ZdcPluginSSLSession):

"Generate a private key and certificate for a certificate authority:"
result1 := LibC resultOfCommand: 'cd /tmp && /usr/bin/openssl ' ,
    'req -x509 -newkey rsa -nodes -keyout ca-key -out ca-cert ' ,
    '-subj "/CN=ZnSecureServer Test CA Certificate" 2>&1'.

"Generate a private key and certificate for the server:"
result2 := LibC resultOfCommand: 'cd /tmp && /usr/bin/openssl ' ,
    'req -x509 -newkey rsa -nodes -keyout s-key -out s-cert1 ' ,
    '-subj "/CN=ZnSecureServer Test Server Certificate" ' ,
    '-addext subjectAltName=DNS:localhost 2>&1'.

"Generate a certificate for the server signed by the certificate authority:"
result3 := LibC resultOfCommand: 'cd /tmp && /usr/bin/openssl ' ,
    'x509 -in s-cert1 -out s-cert2 ' ,
    '-CAkey ca-key -CA ca-cert -CAserial ca-srl -CAcreateserial 2>&1'.

"Put the server private key and the certificate signed by the certificate authority in a PKCS#12 file:"
result4 := LibC resultOfCommand: 'cd /tmp && /usr/bin/openssl ' ,
    'pkcs12 -export -inkey s-key -in s-cert2 ' ,
    '-out s-pkcs12 -password pass:password123 2>&1'.

"Add the certificate authority’s certificate as trusted to the ‘login’ keychain (needs confirmation):"
result5 := LibC resultOfCommand: 'cd /tmp && /usr/bin/security ' ,
    'add-trusted-cert -k ~/Library/Keychains/login.keychain-db ca-cert 2>&1'.

"Start a ZnSecureServer with the PKCS#12 file and password:"
(server := ZnSecureServer on: 1443)
    certificate: '/tmp/s-pkcs12';
    certificatePassword: 'password123';
    logToTranscript;
    start.

"Get ‘/’ from the server:"
response := ZnEasy get: 'https://localhost:1443'.

Browsing ‘https://localhost:1443’ works with Chrome and Firefox. With Safari, a ConnectionClosed is signaled while performing #accept on a ZdcSecureSocketStream, I haven’t tried to find the cause yet.

A point I’m not sure about is whether the ‘items’ array assigned by ‘SecPKCS12Import’ should be released or not, though I assumed not as the function doesn’t have ‘Create’ or ‘Copy’ in its name (see ‘The Create Rule’ in the ‘Memory Management Programming Guide for Core Foundation’).

There’s a corresponding issue that I had opened about this in the OpenSmalltalk VM repository: OpenSmalltalk VM issue #680.

Rinzwind commented 3 months ago

I converted this to a draft because of the question in the OpenSmalltalk VM issue on whether to use ‘CERTNAME’ to identity a certificate in a keychain rather than as the path to a file containing the certificate like it is implemented here.

As for the problem with Safari, I found that when using port forwarding through ‘socat’ as follows, browsing ‘https://localhost:2443’ does work:

$ socat TCP6-LISTEN:2443,fork TCP4:localhost:1443

If I change the command to use ‘TCP4-LISTEN’ as follows instead, then browsing ‘https://localhost:2443’ also causes the signaling of a ConnectionClosed while performing #accept on a ZdcSecureSocketStream:

$ socat TCP4-LISTEN:2443,fork TCP4:localhost:1443

I’m afraid I don’t understand why that is though.

Rinzwind commented 3 months ago

I closed this and opened a new pull request: pull request #816.