https-proxy-protocol.cpp [plain text]
#include "https-proxy-protocol.h"
#include "netparameters.h"
namespace Security {
namespace Network {
ConnectHTTPProtocol::ConnectHTTPProtocol(Manager &mgr, const HostTarget &proxy)
: SecureHTTPProtocol(mgr), host(proxy.defaultPort(defaultHttpPort))
{
}
ConnectHTTPProtocol::ConnectHTTPTransfer *ConnectHTTPProtocol::makeTransfer(const Target &target,
Operation operation)
{
return new ConnectHTTPTransfer(*this, target, operation, defaultHttpsPort);
}
ConnectHTTPProtocol::ConnectHTTPConnection::ConnectHTTPConnection(Protocol &proto,
const HostTarget &hostTarget)
: SecureHTTPConnection(proto, hostTarget)
{
connectState = connectConnecting;
deferStartSSL = true; }
ConnectHTTPProtocol::ConnectHTTPConnection::~ConnectHTTPConnection()
{
}
void ConnectHTTPProtocol::ConnectHTTPConnection::connectRequest()
{
switch (connectState) {
case connectConnecting:
return; case connectStartup:
{
const HostTarget &host = target().host;
flushOutput(false); printfe("CONNECT %s:%d HTTP/1.1",
host.host().name().c_str(), target().host.port());
hostHeader();
authorizationHeader("Proxy-Authorization", hostTarget,
kNetworkGenericProxyUsername, kNetworkGenericProxyPassword);
printfe(""); flushOutput(); mode(lineInput);
connectState = connectPrimaryResponse;
}
break;
case connectReady: sslRequest();
break;
default:
assert(false); }
}
void ConnectHTTPProtocol::ConnectHTTPConnection::transit(Event event,
char *input, size_t inputLength)
{
if (event == endOfInput && connectState != connectReady)
UnixError::throwMe(ECONNRESET);
switch (connectState) {
case connectConnecting:
SecureHTTPConnection::transit(event, input, inputLength);
if (SecureHTTPConnection::sslState == sslStartup) { connectState = connectStartup;
connectRequest();
}
return;
case connectPrimaryResponse:
{
int major, minor, code;
if (sscanf(input, "HTTP/%d.%d %u", &major, &minor, &code) != 3) {
fail(input); }
if (major != 1 || minor < 0 || minor > 1)
fail(input);
switch (code) {
case 200: connectState = connectReadHeaders;
break;
default: transfer().httpResponse() = input; fail(input);
}
}
break;
case connectReadHeaders:
{
if (inputLength) {
headers().add(input);
} else {
connectState = connectReady;
try {
startSSL();
} catch (const CssmCommonError &err) {
setError("SSL failed", err.osStatus());
throw;
} catch (...) {
setError("SSL failed");
throw;
}
}
}
break;
case connectReady:
return SecureHTTPConnection::transit(event, input, inputLength);
default:
assert(false); }
}
ConnectHTTPProtocol::ConnectHTTPTransfer::ConnectHTTPTransfer(Protocol &proto,
const Target &tgt, Operation operation, IPPort defPort)
: SecureHTTPTransfer(proto, tgt, operation, defPort)
{
}
void ConnectHTTPProtocol::ConnectHTTPTransfer::start()
{
ConnectHTTPConnection *connection =
protocol.manager.findConnection<ConnectHTTPConnection>(target);
if (connection == NULL)
connection = new ConnectHTTPConnection(protocol, target);
connection->dock(this);
connection->connectRequest();
}
bool ConnectHTTPProtocol::ConnectHTTPTransfer::useProxyHeaders() const
{
return false;
}
bool ConnectHTTPProtocol::isProxy() const
{ return true; }
const HostTarget &ConnectHTTPProtocol::proxyHost() const
{ return host; }
} }