Asynchronous SChannel Servers


I'm currently working on an SChannel version of the asynchronous SSL connector code that we use to provide SSL support in The Server Framework. This will eventually be an alternative to the existing OpenSSL support that we currently provide and should prove useful for people who want a tighter integration with Microsoft's Certificate Stores than our current OpenSSL support provides.

In many ways the SChannel version of the code is more complex to implement than the OpenSSL version as the OpenSSL SSL_CTX context object deals with data accumulation and record splitting internally; you just push bytes into it and it eventually pushes cleartext out at you. With SChannel you need to manage the accumulation and deal with the result of record splitting yourself. Each call to the SSPI functions will deal with one or more complete SSL records from the stream when you're negotiating but when you're decrypting you need to accumulate spare or incomplete messages and attempt decryption again when you get more data.

To be honest I think I prefer the SChannel way. If only because allows you to see the operation of the link a little more clearly and, possibly, because it forced me to understand what was going on in terms of data flow more than I needed to with the OpenSSL implementation.

Right now I have a simple echo server that works and that interoperates with the OpenSSL test client. It needs some refactoring and there are several things that it doesn't do correctly yet but it's a start and it's nice to see the data flowing.

When I built the original OpenSSL connector back in 2001 (see here for the CAsyncSocket version that I wrote up for Windows Developer Magazine) I was doing less TDD than I am now and so there are no tests, eek! The SChannel code, though based on the OpenSSL connector's basic design, is fully testable and has been developed in a TDD style. This was necessary as dealing with accumulation of data prior to decryption is potentially tricky to get right; most examples show simple synchronous systems where you can block on a read() call to wait for more data. Once I had the simple tests working in terms of complete and distinct messages it was easy to create tests that pushed a byte at a time into the connector to make sure that fragmentation issues aren't missed, and then to push in multiple messages at a time to ensure that they are split and handled correctly.

Due to my impending wedding and subsequent honeymoon this code wont be shipping until mid December, but if you're interested in beta testing it please get in touch.

Leave a comment