#ifndef _sys_windows_SslAsynchIO #define _sys_windows_SslAsynchIO /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include "qpid/sys/AsynchIO.h" #include "qpid/sys/IntegerTypes.h" #include "qpid/sys/Poller.h" #include "qpid/CommonImportExport.h" #include #include #include // security.h needs to see this to distinguish from kernel use. #define SECURITY_WIN32 #include #include #undef SECURITY_WIN32 namespace qpid { namespace sys { namespace windows { class Socket; class Poller; /* * SSL/Schannel shim between the frame-handling and AsynchIO layers. * SslAsynchIO creates a regular AsynchIO object to handle I/O and this class * gets involved for SSL negotiations and encrypt/decrypt. The details of * how this all works are invisible to the layers on either side. The only * change from normal AsynchIO usage is that there's an extra callback * from SslAsynchIO to indicate that the initial session negotiation is * complete. * * The details of session negotiation are different for client and server * SSL roles. These differences are handled by deriving separate client * and server role classes. */ class SslAsynchIO : public qpid::sys::AsynchIO { public: typedef boost::function1 NegotiateDoneCallback; SslAsynchIO(const qpid::sys::Socket& s, CredHandle hCred, ReadCallback rCb, EofCallback eofCb, DisconnectCallback disCb, ClosedCallback cCb = 0, BuffersEmptyCallback eCb = 0, IdleCallback iCb = 0, NegotiateDoneCallback nCb = 0); ~SslAsynchIO(); virtual void queueForDeletion(); virtual void start(qpid::sys::Poller::shared_ptr poller); virtual void queueReadBuffer(BufferBase* buff); virtual void unread(BufferBase* buff); virtual void queueWrite(BufferBase* buff); virtual void notifyPendingWrite(); virtual void queueWriteClose(); virtual bool writeQueueEmpty(); virtual void startReading(); virtual void stopReading(); virtual void requestCallback(RequestCallback); virtual BufferBase* getQueuedBuffer(); QPID_COMMON_EXTERN unsigned int getSslKeySize(); protected: CredHandle credHandle; // AsynchIO layer below that's actually doing the I/O qpid::sys::AsynchIO *aio; // Track what the state of the SSL session is. Have to know when it's // time to notify the upper layer that the session is up, and also to // know when it's not legit to pass data through to either side. enum { Negotiating, Running, Redo, ShuttingDown } state; bool sessionUp; CtxtHandle ctxtHandle; TimeStamp credExpiry; // Client- and server-side SSL subclasses implement these to do the // proper negotiation steps. negotiateStep() is called with a buffer // just received from the peer. virtual void startNegotiate() = 0; virtual void negotiateStep(BufferBase *buff) = 0; // The negotiating steps call one of these when it's finalized: void negotiationDone(); void negotiationFailed(SECURITY_STATUS status); private: // These are callbacks from AsynchIO to here. void sslDataIn(qpid::sys::AsynchIO& a, BufferBase *buff); void idle(qpid::sys::AsynchIO&); // These callbacks are to the layer above. ReadCallback readCallback; IdleCallback idleCallback; NegotiateDoneCallback negotiateDoneCallback; volatile unsigned int callbacksInProgress; // >0 if w/in callbacks volatile bool queuedDelete; // Address of peer, in case it's needed for logging. std::string peerAddress; // Partial buffer of decrypted plaintext given back by the layer above. AsynchIO::BufferBase *leftoverPlaintext; SecPkgContext_StreamSizes schSizes; }; /* * SSL/Schannel client-side shim between the frame-handling and AsynchIO * layers. */ class ClientSslAsynchIO : public SslAsynchIO { public: // Args same as for SslIoShim, with the addition of brokerHost which is // the expected SSL name of the server. QPID_COMMON_EXTERN ClientSslAsynchIO(const std::string& brokerHost, const qpid::sys::Socket& s, CredHandle hCred, ReadCallback rCb, EofCallback eofCb, DisconnectCallback disCb, ClosedCallback cCb = 0, BuffersEmptyCallback eCb = 0, IdleCallback iCb = 0, NegotiateDoneCallback nCb = 0); private: std::string serverHost; // Client- and server-side SSL subclasses implement these to do the // proper negotiation steps. negotiateStep() is called with a buffer // just received from the peer. void startNegotiate(); void negotiateStep(BufferBase *buff); }; /* * SSL/Schannel server-side shim between the frame-handling and AsynchIO * layers. */ class ServerSslAsynchIO : public SslAsynchIO { public: QPID_COMMON_EXTERN ServerSslAsynchIO(bool clientMustAuthenticate, const qpid::sys::Socket& s, CredHandle hCred, ReadCallback rCb, EofCallback eofCb, DisconnectCallback disCb, ClosedCallback cCb = 0, BuffersEmptyCallback eCb = 0, IdleCallback iCb = 0, NegotiateDoneCallback nCb = 0); private: bool clientAuth; // Client- and server-side SSL subclasses implement these to do the // proper negotiation steps. negotiateStep() is called with a buffer // just received from the peer. void startNegotiate(); void negotiateStep(BufferBase *buff); }; }}} // namespace qpid::sys::windows #endif // _sys_windows_SslAsynchIO