BHttpRequest: propagate SSL errors to listener
This way it's possible to handle them in applications.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include <Certificate.h>
|
||||
#include <HttpForm.h>
|
||||
#include <HttpHeaders.h>
|
||||
#include <HttpResult.h>
|
||||
@@ -74,6 +75,12 @@ private:
|
||||
void _SetResultStatusCode(int32 statusCode);
|
||||
BString& _ResultStatusText();
|
||||
|
||||
// SSL failure management
|
||||
friend class CheckedSecureSocket;
|
||||
bool _CertificateVerificationFailed(
|
||||
BCertificate& certificate,
|
||||
const char* message);
|
||||
|
||||
// Utility methods
|
||||
bool _IsDefaultPort();
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ enum {
|
||||
B_URL_PROTOCOL_DATA_RECEIVED,
|
||||
B_URL_PROTOCOL_DOWNLOAD_PROGRESS,
|
||||
B_URL_PROTOCOL_UPLOAD_PROGRESS,
|
||||
B_URL_PROTOCOL_REQUEST_COMPLETED
|
||||
B_URL_PROTOCOL_REQUEST_COMPLETED,
|
||||
B_URL_PROTOCOL_CERTIFICATE_VERIFICATION_FAILED
|
||||
};
|
||||
|
||||
|
||||
@@ -52,9 +53,13 @@ public:
|
||||
ssize_t bytesSent, ssize_t bytesTotal);
|
||||
virtual void RequestCompleted(BUrlRequest* caller,
|
||||
bool success);
|
||||
virtual bool CertificateVerificationFailed(
|
||||
BUrlRequest* caller,
|
||||
BCertificate& certificate,
|
||||
const char* message);
|
||||
|
||||
private:
|
||||
void _SendMessage(BMessage* message,
|
||||
void _SendMessage(BMessage* message,
|
||||
int8 notification, BUrlRequest* caller);
|
||||
|
||||
private:
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stddef.h>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
class BCertificate;
|
||||
class BUrlRequest;
|
||||
|
||||
|
||||
@@ -27,96 +29,109 @@ public:
|
||||
/**
|
||||
ConnectionOpened()
|
||||
Frequency: Once
|
||||
|
||||
Called when the socket is opened.
|
||||
|
||||
Called when the socket is opened.
|
||||
*/
|
||||
virtual void ConnectionOpened(BUrlRequest* caller);
|
||||
|
||||
|
||||
/**
|
||||
HostnameResolved(ip)
|
||||
Frequency: Once
|
||||
Parameters: ip String representing the IP address of the resource
|
||||
host.
|
||||
|
||||
Called when the final IP is discovered
|
||||
|
||||
Called when the final IP is discovered
|
||||
*/
|
||||
virtual void HostnameResolved(BUrlRequest* caller,
|
||||
const char* ip);
|
||||
|
||||
|
||||
/**
|
||||
ReponseStarted()
|
||||
Frequency: Once
|
||||
|
||||
Called when the request has been emitted and the server begins to
|
||||
|
||||
Called when the request has been emitted and the server begins to
|
||||
reply. Typically when the HTTP status code is received.
|
||||
*/
|
||||
virtual void ResponseStarted(BUrlRequest* caller);
|
||||
|
||||
|
||||
/**
|
||||
HeadersReceived()
|
||||
Frequency: Once
|
||||
|
||||
Called when all the server response metadata (such as headers) have
|
||||
|
||||
Called when all the server response metadata (such as headers) have
|
||||
been read and parsed.
|
||||
*/
|
||||
virtual void HeadersReceived(BUrlRequest* caller);
|
||||
|
||||
|
||||
/**
|
||||
DataReceived(data, position, size)
|
||||
Frequency: Zero or more
|
||||
Parameters: data Pointer to the data block in memory
|
||||
position Offset of the data in the stream
|
||||
size Size of the data block
|
||||
|
||||
Called each time a full block of data is received.
|
||||
size Size of the data block
|
||||
|
||||
Called each time a full block of data is received.
|
||||
*/
|
||||
virtual void DataReceived(BUrlRequest* caller,
|
||||
const char* data, off_t position,
|
||||
ssize_t size);
|
||||
|
||||
|
||||
/**
|
||||
DownloadProgress(bytesReceived, bytesTotal)
|
||||
Frequency: Once or more
|
||||
Parameters: bytesReceived Number of data bytes received
|
||||
bytesTotal Total number of data bytes expected
|
||||
|
||||
Called each time a data block is received.
|
||||
|
||||
Called each time a data block is received.
|
||||
*/
|
||||
virtual void DownloadProgress(BUrlRequest* caller,
|
||||
ssize_t bytesReceived, ssize_t bytesTotal);
|
||||
|
||||
|
||||
/**
|
||||
UploadProgress(bytesSent, bytesTotal)
|
||||
Frequency: Once or more
|
||||
Parameters: bytesSent Number of data bytes sent
|
||||
bytesTotal Total number of data bytes expected
|
||||
|
||||
Called each time a data block is emitted.
|
||||
|
||||
Called each time a data block is emitted.
|
||||
*/
|
||||
virtual void UploadProgress(BUrlRequest* caller,
|
||||
ssize_t bytesSent, ssize_t bytesTotal);
|
||||
|
||||
|
||||
/**
|
||||
RequestCompleted(success)
|
||||
Frequency: Once
|
||||
Parameters: success true if the resource have been successfully
|
||||
false if not
|
||||
|
||||
Called once the request is complete.
|
||||
|
||||
Called once the request is complete.
|
||||
*/
|
||||
virtual void RequestCompleted(BUrlRequest* caller,
|
||||
bool success);
|
||||
|
||||
|
||||
/**
|
||||
DebugMessage(type, text)
|
||||
Frequency: zero or more
|
||||
Parameters: type Type of the verbose message (see BUrlProtocolDebug)
|
||||
|
||||
Called each time a debug message is emitted
|
||||
|
||||
Called each time a debug message is emitted
|
||||
*/
|
||||
virtual void DebugMessage(BUrlRequest* caller,
|
||||
BUrlProtocolDebugMessage type,
|
||||
const char* text);
|
||||
|
||||
/**
|
||||
CertificateVerificationFailed(certificate, message)
|
||||
Frequency: Once
|
||||
Parameters: certificate SSL certificate which coulnd't be validated
|
||||
message error message describing the problem
|
||||
|
||||
Return true to proceed anyway, false to abort the connection
|
||||
*/
|
||||
virtual bool CertificateVerificationFailed(
|
||||
BUrlRequest* caller,
|
||||
BCertificate& certificate,
|
||||
const char* message);
|
||||
};
|
||||
|
||||
#endif // _B_URL_PROTOCOL_LISTENER_H_
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <new>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <Certificate.h>
|
||||
#include <Debug.h>
|
||||
#include <DynamicBuffer.h>
|
||||
#include <File.h>
|
||||
@@ -31,6 +32,35 @@
|
||||
static const int32 kHttpBufferSize = 4096;
|
||||
|
||||
|
||||
class CheckedSecureSocket: public BSecureSocket
|
||||
{
|
||||
public:
|
||||
CheckedSecureSocket(BHttpRequest* request);
|
||||
|
||||
bool CertificateVerificationFailed(BCertificate& certificate,
|
||||
const char* message);
|
||||
|
||||
private:
|
||||
BHttpRequest* fRequest;
|
||||
};
|
||||
|
||||
|
||||
CheckedSecureSocket::CheckedSecureSocket(BHttpRequest* request)
|
||||
:
|
||||
BSecureSocket(),
|
||||
fRequest(request)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CheckedSecureSocket::CertificateVerificationFailed(BCertificate& certificate,
|
||||
const char* message)
|
||||
{
|
||||
return fRequest->_CertificateVerificationFailed(certificate, message);
|
||||
}
|
||||
|
||||
|
||||
BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName,
|
||||
BUrlProtocolListener* listener, BUrlContext* context)
|
||||
:
|
||||
@@ -50,7 +80,7 @@ BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName,
|
||||
{
|
||||
_ResetOptions();
|
||||
if (fSSL)
|
||||
fSocket = new(std::nothrow) BSecureSocket();
|
||||
fSocket = new(std::nothrow) CheckedSecureSocket(this);
|
||||
else
|
||||
fSocket = new(std::nothrow) BSocket();
|
||||
}
|
||||
@@ -76,7 +106,7 @@ BHttpRequest::BHttpRequest(const BHttpRequest& other)
|
||||
_ResetOptions();
|
||||
// FIXME some options may be copied from other instead.
|
||||
if (fSSL)
|
||||
fSocket = new(std::nothrow) BSecureSocket();
|
||||
fSocket = new(std::nothrow) CheckedSecureSocket(this);
|
||||
else
|
||||
fSocket = new(std::nothrow) BSocket();
|
||||
}
|
||||
@@ -791,7 +821,7 @@ BHttpRequest::_SendHeaders()
|
||||
BString host = Url().Host();
|
||||
if (Url().HasPort() && !_IsDefaultPort())
|
||||
host << ':' << Url().Port();
|
||||
|
||||
|
||||
outputHeaders.AddHeader("Host", host);
|
||||
|
||||
outputHeaders.AddHeader("Accept", "*/*");
|
||||
@@ -887,7 +917,7 @@ BHttpRequest::_SendHeaders()
|
||||
break;
|
||||
cookieString << "; ";
|
||||
}
|
||||
|
||||
|
||||
outputHeaders.AddHeader("Cookie", cookieString);
|
||||
}
|
||||
}
|
||||
@@ -1022,7 +1052,21 @@ BHttpRequest::_ResultStatusText()
|
||||
}
|
||||
|
||||
|
||||
bool BHttpRequest::_IsDefaultPort()
|
||||
bool
|
||||
BHttpRequest::_CertificateVerificationFailed(BCertificate& certificate,
|
||||
const char* message)
|
||||
{
|
||||
if (fListener != NULL) {
|
||||
return fListener->CertificateVerificationFailed(this, certificate,
|
||||
message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BHttpRequest::_IsDefaultPort()
|
||||
{
|
||||
if (fSSL && Url().Port() == 443)
|
||||
return true;
|
||||
|
||||
@@ -142,6 +142,20 @@ BUrlProtocolAsynchronousListener::MessageReceived(BMessage* message)
|
||||
}
|
||||
break;
|
||||
|
||||
case B_URL_PROTOCOL_CERTIFICATE_VERIFICATION_FAILED:
|
||||
{
|
||||
const char* error = message->FindString("url:error");
|
||||
BCertificate* certificate;
|
||||
message->FindPointer("url:certificate", (void**)&certificate);
|
||||
bool result = CertificateVerificationFailed(caller,
|
||||
*certificate, error);
|
||||
|
||||
BMessage reply;
|
||||
reply.AddBool("url:continue", result);
|
||||
message->SendReply(&reply);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINT(("BUrlProtocolAsynchronousListener: Unknown notification %d\n",
|
||||
notification));
|
||||
|
||||
@@ -125,6 +125,25 @@ BUrlProtocolDispatchingListener::RequestCompleted(BUrlRequest* caller,
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUrlProtocolDispatchingListener::CertificateVerificationFailed(
|
||||
BUrlRequest* caller, BCertificate& certificate, const char* error)
|
||||
{
|
||||
BMessage message(B_URL_PROTOCOL_NOTIFICATION);
|
||||
message.AddString("url:error", error);
|
||||
message.AddPointer("url:certificate", &certificate);
|
||||
message.AddInt8(kUrlProtocolMessageType,
|
||||
B_URL_PROTOCOL_CERTIFICATE_VERIFICATION_FAILED);
|
||||
message.AddPointer(kUrlProtocolCaller, caller);
|
||||
|
||||
// Warning: synchronous reply
|
||||
BMessage reply;
|
||||
fMessenger.SendMessage(&message, &reply);
|
||||
|
||||
return reply.FindBool("url:continue");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUrlProtocolDispatchingListener::_SendMessage(BMessage* message,
|
||||
int8 notification, BUrlRequest* caller)
|
||||
|
||||
@@ -27,6 +27,14 @@ BUrlProtocolListener::HostnameResolved(BUrlRequest*, const char*)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUrlProtocolListener::CertificateVerificationFailed(BUrlRequest* caller,
|
||||
BCertificate& certificate, const char* message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUrlProtocolListener::ResponseStarted(BUrlRequest*)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user