blob: edec081ced44fa5f85a9baca23b4c58255b4a85c [file] [log] [blame]
#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 <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <windows.h>
// security.h needs to see this to distinguish from kernel use.
#define SECURITY_WIN32
#include <security.h>
#include <Schnlsp.h>
#undef SECURITY_WIN32
namespace qpid {
namespace sys {
namespace windows {
/*
* 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<void, SECURITY_STATUS> 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