https-protocol.cpp [plain text]
#include "https-protocol.h"
#include "netparameters.h"
namespace Security {
namespace Network {
SecureHTTPProtocol::SecureHTTPProtocol(Manager &mgr) : HTTPProtocol(mgr, "https")
{
}
const char *SecureHTTPProtocol::name() const
{
return "http/ssl";
}
SecureHTTPProtocol::SecureHTTPTransfer *SecureHTTPProtocol::makeTransfer(const Target &target,
Operation operation)
{
return new SecureHTTPTransfer(*this, target, operation, defaultHttpsPort);
}
SecureHTTPProtocol::SecureHTTPConnection::SecureHTTPConnection(Protocol &proto,
const HostTarget &hostTarget)
: HTTPConnection(proto, hostTarget),
SecureTransport<Socket>(static_cast<TCPClientSocket &>(*this)), deferStartSSL(false), sslActive(false)
{
deferSendRequest = true; sslState = sslConnecting;
}
SecureHTTPProtocol::SecureHTTPConnection::~SecureHTTPConnection()
{
}
void SecureHTTPProtocol::SecureHTTPConnection::sslRequest()
{
switch (sslState) {
case sslConnecting: break;
case sslConnected: transfer().startRequest();
break;
default:
assert(false); }
}
void SecureHTTPProtocol::SecureHTTPConnection::startSSL()
{
assert(sslState == sslStartup);
sslActive = true;
mode(rawInput);
allowsExpiredCerts(getv<bool>(kNetworkHttpAcceptExpiredCerts, false));
allowsUnknownRoots(getv<bool>(kNetworkHttpAcceptUnknownRoots, false));
peerId(peerAddress());
SSL::open();
assert(SSL::state() == kSSLHandshake); sslState = sslHandshaking;
}
bool SecureHTTPProtocol::SecureHTTPConnection::validate()
{
return HTTPConnection::validate() && SSL::state() == kSSLConnected;
}
void SecureHTTPProtocol::SecureHTTPConnection::transit(Event event,
char *input, size_t inputLength)
{
try {
switch (sslState) {
case sslConnecting:
HTTPConnection::transit(event, input, inputLength);
if (HTTPConnection::state == idle) { sslState = sslStartup;
if (!deferStartSSL)
startSSL();
}
return;
case sslHandshaking:
assert(event == inputAvailable);
SecureTransport<Socket>::open(); switch (SSL::state()) {
case kSSLHandshake: return;
case kSSLConnected: sslState = sslConnected;
transfer().startRequest();
return;
default:
assert(false); }
case sslConnected:
return HTTPConnection::transit(event, input, inputLength);
default:
assert(false); }
} catch (const CssmCommonError &err) {
setError("SSL failed", err.osStatus());
throw;
} catch (...) {
setError("SSL failed");
throw;
}
}
size_t SecureHTTPProtocol::SecureHTTPConnection::read(void *data, size_t length)
{
return sslActive ? SSL::read(data, length) : Socket::read(data, length);
}
size_t SecureHTTPProtocol::SecureHTTPConnection::write(const void *data, size_t length)
{
return sslActive ? SSL::write(data, length) : Socket::write(data, length);
}
bool SecureHTTPProtocol::SecureHTTPConnection::atEnd() const
{
return sslActive ? SSL::atEnd() : Socket::atEnd();
}
SecureHTTPProtocol::SecureHTTPTransfer::SecureHTTPTransfer(Protocol &proto,
const Target &tgt, Operation operation, IPPort defPort)
: HTTPTransfer(proto, tgt, operation, defPort)
{
}
void SecureHTTPProtocol::SecureHTTPTransfer::start()
{
SecureHTTPConnection *connection =
protocol.manager.findConnection<SecureHTTPConnection>(target);
if (connection == NULL)
connection = new SecureHTTPConnection(protocol, target);
connection->dock(this);
connection->sslRequest();
}
} }