added session caching support to NetSSL

This commit is contained in:
Guenter Obiltschnig
2010-03-29 14:11:11 +00:00
parent 5c75d2aa32
commit 7e19faf1c7
35 changed files with 979 additions and 58 deletions

View File

@@ -1,7 +1,7 @@
//
// Event_WIN32.h
//
// $Id: //poco/1.3/Foundation/include/Poco/Event_WIN32.h#2 $
// $Id: //poco/1.3/Foundation/include/Poco/Event_WIN32.h#3 $
//
// Library: Foundation
// Package: Threading
@@ -51,7 +51,7 @@ namespace Poco {
class Foundation_API EventImpl
{
protected:
EventImpl(bool autoReset = false);
EventImpl(bool autoReset);
~EventImpl();
void setImpl();
void waitImpl();

View File

@@ -1,7 +1,7 @@
//
// FileStream_POSIX.cpp
//
// $Id: //poco/1.3/Foundation/src/FileStream_POSIX.cpp#2 $
// $Id: //poco/1.3/Foundation/src/FileStream_POSIX.cpp#3 $
//
// Library: Foundation
// Package: Streams
@@ -81,7 +81,7 @@ void FileStreamBuf::open(const std::string& path, std::ios::openmode mode)
else
flags |= O_WRONLY;
_fd = ::open(path.c_str(), flags, S_IRUSR | S_IWUSR | S_IRGRP);
_fd = ::open(path.c_str(), flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (_fd == -1)
File::handleLastError(_path);

View File

@@ -1,7 +1,7 @@
//
// File_UNIX.cpp
//
// $Id: //poco/1.3/Foundation/src/File_UNIX.cpp#15 $
// $Id: //poco/1.3/Foundation/src/File_UNIX.cpp#16 $
//
// Library: Foundation
// Package: Filesystem
@@ -406,7 +406,7 @@ bool FileImpl::createFileImpl()
{
poco_assert (!_path.empty());
int n = open(_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
int n = open(_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (n != -1)
{
close(n);
@@ -426,7 +426,7 @@ bool FileImpl::createDirectoryImpl()
if (existsImpl() && isDirectoryImpl())
return false;
if (mkdir(_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
if (mkdir(_path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) != 0)
handleLastErrorImpl(_path);
return true;
}

View File

@@ -1,7 +1,7 @@
//
// HTMLForm.cpp
//
// $Id: //poco/1.3/Net/src/HTMLForm.cpp#5 $
// $Id: //poco/1.3/Net/src/HTMLForm.cpp#6 $
//
// Library: Net
// Package: HTML
@@ -125,7 +125,7 @@ void HTMLForm::addPart(const std::string& name, PartSource* pSource)
void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler)
{
clear();
if (request.getMethod() == HTTPRequest::HTTP_POST)
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
{
std::string mediaType;
NameValueCollection params;
@@ -176,7 +176,7 @@ void HTMLForm::read(std::istream& istr, PartHandler& handler)
void HTMLForm::prepareSubmit(HTTPRequest& request)
{
if (request.getMethod() == HTTPRequest::HTTP_POST)
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
{
if (_encoding == ENCODING_URL)
{

View File

@@ -18,7 +18,7 @@ objects = AcceptCertificateHandler CertificateHandlerFactory \
PrivateKeyPassphraseHandler SecureServerSocket SecureServerSocketImpl \
SecureSocketImpl SecureStreamSocket SecureStreamSocketImpl \
SSLException SSLManager Utility VerificationErrorArgs \
X509Certificate
X509Certificate Session
target = PocoNetSSL
target_version = $(LIBVERSION)

View File

@@ -287,6 +287,9 @@
<File
RelativePath=".\include\Poco\Net\PrivateKeyPassphraseHandler.h">
</File>
<File
RelativePath=".\include\Poco\Net\Session.h">
</File>
<File
RelativePath=".\include\Poco\Net\SSLException.h">
</File>
@@ -339,6 +342,9 @@
<File
RelativePath=".\src\PrivateKeyPassphraseHandler.cpp">
</File>
<File
RelativePath=".\src\Session.cpp">
</File>
<File
RelativePath=".\src\SSLException.cpp">
</File>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="NetSSL_OpenSSL"
ProjectGUID="{5AECC55E-A469-11DA-8DA6-005056C00008}"
RootNamespace="OpenSSL"
@@ -407,6 +407,10 @@
RelativePath=".\include\Poco\Net\PrivateKeyPassphraseHandler.h"
>
</File>
<File
RelativePath=".\include\Poco\Net\Session.h"
>
</File>
<File
RelativePath=".\include\Poco\Net\SSLException.h"
>
@@ -475,6 +479,10 @@
RelativePath=".\src\PrivateKeyPassphraseHandler.cpp"
>
</File>
<File
RelativePath=".\src\Session.cpp"
>
</File>
<File
RelativePath=".\src\SSLException.cpp"
>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="NetSSL_OpenSSL"
ProjectGUID="{5AECC55E-A469-11DA-8DA6-005056C00008}"
RootNamespace="OpenSSL"
@@ -402,6 +402,10 @@
RelativePath=".\include\Poco\Net\PrivateKeyPassphraseHandler.h"
>
</File>
<File
RelativePath=".\include\Poco\Net\Session.h"
>
</File>
<File
RelativePath=".\include\Poco\Net\SSLException.h"
>
@@ -470,6 +474,10 @@
RelativePath=".\src\PrivateKeyPassphraseHandler.cpp"
>
</File>
<File
RelativePath=".\src\Session.cpp"
>
</File>
<File
RelativePath=".\src\SSLException.cpp"
>

View File

@@ -1,7 +1,7 @@
//
// Context.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/Context.h#8 $
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/Context.h#10 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
@@ -9,7 +9,7 @@
//
// Definition of the Context class.
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -44,6 +44,7 @@
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <openssl/ssl.h>
#include <cctype>
namespace Poco {
@@ -56,6 +57,9 @@ class NetSSL_API Context: public Poco::RefCountedObject
/// verification mode and the location of certificates
/// and private key files, as well as the list of
/// supported ciphers.
///
/// The Context class is also used to control
/// SSL session caching on the server and client side.
{
public:
typedef Poco::AutoPtr<Context> Ptr;
@@ -142,13 +146,64 @@ public:
/// Returns the verification mode.
void enableSessionCache(bool flag = true);
/// Enable or disable the SSL/TLS session cache for a server.
/// Enable or disable SSL/TLS session caching.
/// For session caching to work, it must be enabled
/// on the server, as well as on the client side.
///
/// The default is a disabled session cache.
/// The default is disabled session caching.
///
/// To enable session caching on the server side, use the
/// two-argument version of this method to specify
/// a session ID context.
void enableSessionCache(bool flag, const std::string& sessionIdContext);
/// Enables or disables SSL/TLS session caching on the server.
/// For session caching to work, it must be enabled
/// on the server, as well as on the client side.
///
/// SessionIdContext contains the application's unique
/// session ID context, which becomes part of each
/// session identifier generated by the server within this
/// context. SessionIdContext can be an arbitrary sequence
/// of bytes with a maximum length of SSL_MAX_SSL_SESSION_ID_LENGTH.
///
/// This method may only be called on SERVER_USE Context objects.
bool sessionCacheEnabled() const;
/// Returns true iff the session cache is enabled.
void setSessionCacheSize(std::size_t size);
/// Sets the maximum size of the server session cache, in number of
/// sessions. The default size (according to OpenSSL documentation)
/// is 1024*20, which may be too large for many applications,
/// especially on embedded platforms with limited memory.
///
/// Specifying a size of 0 will set an unlimited cache size.
///
/// This method may only be called on SERVER_USE Context objets.
std::size_t getSessionCacheSize() const;
/// Returns the current maximum size of the server session cache.
///
/// This method may only be called on SERVER_USE Context objets.
void setSessionTimeout(long seconds);
/// Sets the timeout (in seconds) of cached sessions on the server.
/// A cached session will be removed from the cache if it has
/// not been used for the given number of seconds.
///
/// This method may only be called on SERVER_USE Context objets.
long getSessionTimeout() const;
/// Returns the timeout (in seconds) of cached sessions on the server.
///
/// This method may only be called on SERVER_USE Context objets.
void flushSessionCache();
/// Flushes the SSL session cache on the server.
///
/// This method may only be called on SERVER_USE Context objets.
void enableExtendedCertificateVerification(bool flag = true);
/// Enable or disable the automatic post-connection
/// extended certificate verification.
@@ -159,6 +214,12 @@ public:
/// Returns true iff automatic extended certificate
/// verification is enabled.
void disableStatelessSessionResumption();
/// Newer versions of OpenSSL support RFC 4507 tickets for stateless
/// session resumption.
///
/// The feature can be disabled by calling this method.
private:
Usage _usage;
VerificationMode _mode;

View File

@@ -1,7 +1,7 @@
//
// HTTPSClientSession.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/HTTPSClientSession.h#7 $
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/HTTPSClientSession.h#8 $
//
// Library: NetSSL_OpenSSL
// Package: HTTPSClient
@@ -44,6 +44,7 @@
#include "Poco/Net/Utility.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/Session.h"
#include "Poco/Net/X509Certificate.h"
@@ -84,6 +85,11 @@ class NetSSL_API HTTPSClientSession: public HTTPClientSession
/// result in a SSL protocol violation, as the framework shuts down
/// the socket after sending the message body. No orderly SSL shutdown
/// will be performed in this case.
///
/// If session caching has been enabled for the Context object passed
/// to the HTTPSClientSession, the HTTPSClientSession class will
/// attempt to reuse a previously obtained Session object in
/// case of a reconnect.
{
public:
enum
@@ -106,10 +112,26 @@ public:
/// Creates an unconnected HTTPSClientSession, using the
/// give SSL context.
HTTPSClientSession(Context::Ptr pContext, Session::Ptr pSession);
/// Creates an unconnected HTTPSClientSession, using the
/// give SSL context.
///
/// The given Session is reused, if possible (client session
/// caching is enabled for the given Context, and the server
/// agrees to reuse the session).
HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext);
/// Creates a HTTPSClientSession using the given host and port,
/// using the given SSL context.
HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext, Session::Ptr pSession);
/// Creates a HTTPSClientSession using the given host and port,
/// using the given SSL context.
///
/// The given Session is reused, if possible (client session
/// caching is enabled for the given Context, and the server
/// agrees to reuse the session).
~HTTPSClientSession();
/// Destroys the HTTPSClientSession and closes
/// the underlying socket.
@@ -119,6 +141,15 @@ public:
///
/// The certificate is available after the first request has been sent.
Session::Ptr sslSession();
/// Returns the SSL Session object for the current
/// connection, if session caching has been enabled for
/// the HTTPSClientSession's Context. A null pointer is
/// returned otherwise.
///
/// The Session object can be obtained after the first request has
/// been sent.
protected:
void connect(const SocketAddress& address);
std::string proxyRequestPrefix() const;
@@ -129,6 +160,7 @@ private:
HTTPSClientSession& operator = (const HTTPSClientSession&);
Context::Ptr _pContext;
Session::Ptr _pSession;
};

View File

@@ -1,7 +1,7 @@
//
// SSLManager.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h#6 $
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h#8 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
@@ -9,7 +9,7 @@
//
// Definition of the SSLManager class.
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -90,14 +90,48 @@ class NetSSL_API SSLManager
/// </privateKeyPassphraseHandler>
/// <invalidCertificateHandler>
/// <name>ConsoleCertificateHandler</name>
/// <options>
/// </options>
/// </invalidCertificateHandler>
/// <cacheSessions>true|false</cacheSessions>
/// <cacheSessions>true|false</cacheSessions> <!-- server only -->
/// <sessionIdContext>someString</sessionIdContext> <!-- server only -->
/// <sessionCacheSize>0..n</sessionCacheSize> <!-- server only -->
/// <sessionTimeout>0..n</sessionTimeout> <!-- server only -->
/// <extendedVerification>true|false</extendedVerification>
/// </server|client>
/// </openSSL>
/// </AppConfig>
///
/// Following is a list of supported configuration properties. Property names must always
/// be prefixed with openSSL.server or openSSL.client. Some properties are only supported
/// for servers.
///
/// - privateKeyFile (string): The path to the file containing the private key for the certificate
/// in PEM format (or containing both the private key and the certificate).
/// - certificateFile (string): The Path to the file containing the server's or client's certificate
/// in PEM format. Can be omitted if the the file given in privateKeyFile contains the certificate as well.
/// - caConfig (string): The path to the file or directory containing the trusted root certificates.
/// - verificationMode (string): Specifies whether and how peer certificates are validated (see
/// the Context class for details). Valid values are none, relaxed, strict, once.
/// - verificationDepth (integer, 1-9): Sets the upper limit for verification chain sizes. Verification
/// will fail if a certificate chain larger than this is encountered.
/// - loadDefaultCAFile (boolean): Specifies wheter the builtin CA certificates from OpenSSL are used.
/// - cipherList (string): Specifies the supported ciphers in OpenSSL notation
/// (e.g. "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH").
/// - privateKeyPassphraseHandler.name (string): The name of the class (subclass of PrivateKeyPassphraseHandler)
/// used for obtaining the passphrase for accessing the private key.
/// - privateKeyPassphraseHandler.options.password (string): The password to be used by KeyFileHandler.
/// - invalidCertificateHandler.name: The name of the class (subclass of CertificateHandler)
/// used for confirming invalid certificates.
/// - cacheSessions (boolean): Enables or disables session caching (server only).
/// - sessionIdContext (string): contains the application's unique session ID context, which becomes
/// part of each session identifier generated by the server. Can be an arbitrary sequence
/// of bytes with a maximum length of SSL_MAX_SSL_SESSION_ID_LENGTH.
/// - sessionCacheSize (integer): Sets the maximum size of the server session cache, in number of
/// sessions. The default size (according to OpenSSL documentation) is 1024*20, which may be too
/// large for many applications, especially on embedded platforms with limited memory.
/// Specifying a size of 0 will set an unlimited cache size.
/// - sessionTimeout (integer): Sets the timeout (in seconds) of cached sessions on the server.
/// - extendedVerification (boolean): Enable or disable the automatic post-connection
/// extended certificate verification.
{
public:
typedef Poco::SharedPtr<PrivateKeyPassphraseHandler> PrivateKeyPassphraseHandlerPtr;
@@ -251,6 +285,9 @@ private:
static const std::string CFG_CERTIFICATE_HANDLER;
static const std::string VAL_CERTIFICATE_HANDLER;
static const std::string CFG_CACHE_SESSIONS;
static const std::string CFG_SESSION_ID_CONTEXT;
static const std::string CFG_SESSION_CACHE_SIZE;
static const std::string CFG_SESSION_TIMEOUT;
static const std::string CFG_EXTENDED_VERIFICATION;
friend class Poco::SingletonHolder<SSLManager>;

View File

@@ -1,7 +1,7 @@
//
// SecureSocketImpl.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SecureSocketImpl.h#10 $
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SecureSocketImpl.h#12 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
@@ -9,7 +9,7 @@
//
// Definition of the SecureSocketImpl class.
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -44,6 +44,7 @@
#include "Poco/Net/SocketImpl.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/X509Certificate.h"
#include "Poco/Net/Session.h"
#include <openssl/bio.h>
#include <openssl/ssl.h>
@@ -171,6 +172,27 @@ public:
const std::string& getPeerHostName() const;
/// Returns the peer host name.
Session::Ptr currentSession();
/// Returns the SSL session of the current connection,
/// for reuse in a future connection (if session caching
/// is enabled).
///
/// If no connection is established, returns null.
void useSession(Session::Ptr pSession);
/// Sets the SSL session to use for the next
/// connection. Setting a previously saved Session
/// object is necessary to enable session caching.
///
/// To remove the currently set session, a null pointer
/// can be given.
///
/// Must be called before connect() to be effective.
bool sessionWasReused();
/// Returns true iff a reused session was negotiated during
/// the handshake.
protected:
void acceptSSL();
/// Performs a server-side SSL handshake and certificate verification.
@@ -207,6 +229,7 @@ private:
Context::Ptr _pContext;
bool _needHandshake;
std::string _peerHostName;
Session::Ptr _pSession;
friend class SecureStreamSocketImpl;
};

View File

@@ -1,7 +1,7 @@
//
// SecureStreamSocket.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SecureStreamSocket.h#7 $
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SecureStreamSocket.h#9 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
@@ -9,7 +9,7 @@
//
// Definition of the SecureStreamSocket class.
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -43,6 +43,7 @@
#include "Poco/Net/NetSSL.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/Session.h"
#include "Poco/Net/X509Certificate.h"
@@ -92,6 +93,17 @@ public:
/// Before sending or receiving data, the socket
/// must be connected with a call to connect().
SecureStreamSocket(Context::Ptr pContext, Session::Ptr pSession);
/// Creates an unconnected secure stream socket
/// using the given SSL context.
///
/// Before sending or receiving data, the socket
/// must be connected with a call to connect().
///
/// The given Session is reused, if possible (client session
/// caching is enabled for the given Context, and the server
/// agrees to reuse the session).
explicit SecureStreamSocket(const SocketAddress& address);
/// Creates a secure stream socket using the default
/// client SSL context and connects it to
@@ -102,6 +114,15 @@ public:
/// client SSL context and connects it to
/// the socket specified by address.
SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext, Session::Ptr pSession);
/// Creates a secure stream socket using the given
/// client SSL context and connects it to
/// the socket specified by address.
///
/// The given Session is reused, if possible (client session
/// caching is enabled for the given Context, and the server
/// agrees to reuse the session).
SecureStreamSocket(const SocketAddress& address, const std::string& hostName);
/// Creates a secure stream socket using the default
/// client SSL context and connects it to
@@ -116,6 +137,17 @@ public:
///
/// The given host name is used for certificate verification.
SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext, Session::Ptr pSession);
/// Creates a secure stream socket using the given
/// client SSL context and connects it to
/// the socket specified by address.
///
/// The given host name is used for certificate verification.
///
/// The given Session is reused, if possible (client session
/// caching is enabled for the given Context, and the server
/// agrees to reuse the session).
SecureStreamSocket(const Socket& socket);
/// Creates the SecureStreamSocket with the SocketImpl
/// from another socket. The SocketImpl must be
@@ -158,6 +190,15 @@ public:
/// connection. The given StreamSocket must be connected.
/// A SSL handshake will be performed.
static SecureStreamSocket attach(const StreamSocket& streamSocket, Context::Ptr pContext, Session::Ptr pSession);
/// Creates a SecureStreamSocket over an existing socket
/// connection. The given StreamSocket must be connected.
/// A SSL handshake will be performed.
///
/// The given Session is reused, if possible (client session
/// caching is enabled for the given Context, and the server
/// agrees to reuse the session).
static SecureStreamSocket attach(const StreamSocket& streamSocket, const std::string& peerHostName);
/// Creates a SecureStreamSocket over an existing socket
/// connection. The given StreamSocket must be connected.
@@ -168,6 +209,15 @@ public:
/// connection. The given StreamSocket must be connected.
/// A SSL handshake will be performed.
static SecureStreamSocket attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext, Session::Ptr pSession);
/// Creates a SecureStreamSocket over an existing socket
/// connection. The given StreamSocket must be connected.
/// A SSL handshake will be performed.
///
/// The given Session is reused, if possible (client session
/// caching is enabled for the given Context, and the server
/// agrees to reuse the session).
Context::Ptr context() const;
/// Returns the SSL context used by this socket.
@@ -206,6 +256,27 @@ public:
/// handshake. In this case, completeHandshake() should be called
/// again, after the necessary condition has been met.
Session::Ptr currentSession();
/// Returns the SSL session of the current connection,
/// for reuse in a future connection (if session caching
/// is enabled).
///
/// If no connection is established, returns null.
void useSession(Session::Ptr pSession);
/// Sets the SSL session to use for the next
/// connection. Setting a previously saved Session
/// object is necessary to enable session caching.
///
/// To remove the currently set session, a null pointer
/// can be given.
///
/// Must be called before connect() to be effective.
bool sessionWasReused();
/// Returns true iff a reused session was negotiated during
/// the handshake.
protected:
SecureStreamSocket(SocketImpl* pImpl);

View File

@@ -1,7 +1,7 @@
//
// SecureStreamSocketImpl.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SecureStreamSocketImpl.h#9 $
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SecureStreamSocketImpl.h#11 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
@@ -9,7 +9,7 @@
//
// Definition of the SecureStreamSocketImpl class.
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -185,6 +185,27 @@ public:
/// the server-side handshake is completed, otherwise
/// a client-side handshake is performed.
Session::Ptr currentSession();
/// Returns the SSL session of the current connection,
/// for reuse in a future connection (if session caching
/// is enabled).
///
/// If no connection is established, returns null.
void useSession(Session::Ptr pSession);
/// Sets the SSL session to use for the next
/// connection. Setting a previously saved Session
/// object is necessary to enable session caching.
///
/// To remove the currently set session, a null pointer
/// can be given.
///
/// Must be called before connect() to be effective.
bool sessionWasReused();
/// Returns true iff a reused session was negotiated during
/// the handshake.
protected:
void acceptSSL();
/// Performs a SSL server-side handshake.
@@ -234,6 +255,24 @@ inline Context::Ptr SecureStreamSocketImpl::context() const
}
inline Session::Ptr SecureStreamSocketImpl::currentSession()
{
return _impl.currentSession();
}
inline void SecureStreamSocketImpl::useSession(Session::Ptr pSession)
{
_impl.useSession(pSession);
}
inline bool SecureStreamSocketImpl::sessionWasReused()
{
return _impl.sessionWasReused();
}
inline int SecureStreamSocketImpl::lastError()
{
return SocketImpl::lastError();

View File

@@ -0,0 +1,101 @@
//
// Session.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/Session.h#1 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: Session
//
// Definition of the Session class.
//
// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef NetSSL_Session_INCLUDED
#define NetSSL_Session_INCLUDED
#include "Poco/Net/NetSSL.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <openssl/ssl.h>
namespace Poco {
namespace Net {
class NetSSL_API Session: public Poco::RefCountedObject
/// This class encapsulates a SSL session object
/// used with session caching on the client side.
///
/// For session caching to work, a client must
/// save the session object from an existing connection,
/// if it wants to reuse it with a future connection.
{
public:
typedef Poco::AutoPtr<Session> Ptr;
SSL_SESSION* sslSession() const;
/// Returns the stored OpenSSL SSL_SESSION object.
protected:
Session(SSL_SESSION* pSession);
/// Creates a new Session object, using the given
/// SSL_SESSION object.
///
/// The SSL_SESSION's reference count is not changed.
~Session();
/// Destroys the Session.
///
/// Calls SSL_SESSION_free() on the stored
/// SSL_SESSION object.
private:
Session();
SSL_SESSION* _pSession;
friend class SecureSocketImpl;
};
//
// inlines
//
inline SSL_SESSION* Session::sslSession() const
{
return _pSession;
}
} } // namespace Poco::Net
#endif // NetSSL_Session_INCLUDED

View File

@@ -1,13 +1,13 @@
//
// Context.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/src/Context.cpp#11 $
// $Id: //poco/1.3/NetSSL_OpenSSL/src/Context.cpp#13 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: Context
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -41,6 +41,7 @@
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/File.h"
#include "Poco/Path.h"
#include "Poco/Timestamp.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
@@ -148,7 +149,31 @@ Context::~Context()
void Context::enableSessionCache(bool flag)
{
SSL_CTX_set_session_cache_mode(_pSSLContext, flag ? SSL_SESS_CACHE_SERVER : SSL_SESS_CACHE_OFF);
if (flag)
{
SSL_CTX_set_session_cache_mode(_pSSLContext, _usage == SERVER_USE ? SSL_SESS_CACHE_SERVER : SSL_SESS_CACHE_CLIENT);
}
else
{
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
}
}
void Context::enableSessionCache(bool flag, const std::string& sessionIdContext)
{
poco_assert (_usage == SERVER_USE);
poco_assert (sessionIdContext.length() <= SSL_MAX_SSL_SESSION_ID_LENGTH);
if (flag)
{
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_SERVER);
int rc = SSL_CTX_set_session_id_context(_pSSLContext, reinterpret_cast<const unsigned char*>(sessionIdContext.data()), static_cast<unsigned>(sessionIdContext.length()));
if (rc != 1) throw SSLContextException("cannot set session ID context");
}
else
{
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
}
}
@@ -158,10 +183,59 @@ bool Context::sessionCacheEnabled() const
}
void Context::setSessionCacheSize(std::size_t size)
{
poco_assert (_usage == SERVER_USE);
SSL_CTX_sess_set_cache_size(_pSSLContext, static_cast<long>(size));
}
std::size_t Context::getSessionCacheSize() const
{
poco_assert (_usage == SERVER_USE);
return static_cast<std::size_t>(SSL_CTX_sess_get_cache_size(_pSSLContext));
}
void Context::setSessionTimeout(long seconds)
{
poco_assert (_usage == SERVER_USE);
SSL_CTX_set_timeout(_pSSLContext, seconds);
}
long Context::getSessionTimeout() const
{
poco_assert (_usage == SERVER_USE);
return SSL_CTX_get_timeout(_pSSLContext);
}
void Context::flushSessionCache()
{
poco_assert (_usage == SERVER_USE);
Poco::Timestamp now;
SSL_CTX_flush_sessions(_pSSLContext, static_cast<long>(now.epochTime()));
}
void Context::enableExtendedCertificateVerification(bool flag)
{
_extendedCertificateVerification = flag;
}
void Context::disableStatelessSessionResumption()
{
#if defined(SSL_OP_NO_TICKET)
SSL_CTX_set_options(_pSSLContext, SSL_OP_NO_TICKET);
#endif
}
} } // namespace Poco::Net

View File

@@ -1,13 +1,13 @@
//
// HTTPSClientSession.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/src/HTTPSClientSession.cpp#6 $
// $Id: //poco/1.3/NetSSL_OpenSSL/src/HTTPSClientSession.cpp#8 $
//
// Library: NetSSL_OpenSSL
// Package: HTTPSClient
// Module: HTTPSClientSession
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -86,6 +86,14 @@ HTTPSClientSession::HTTPSClientSession(Context::Ptr pContext):
}
HTTPSClientSession::HTTPSClientSession(Context::Ptr pContext, Session::Ptr pSession):
HTTPClientSession(SecureStreamSocket(pContext, pSession)),
_pContext(pContext),
_pSession(pSession)
{
}
HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext):
HTTPClientSession(SecureStreamSocket(pContext)),
_pContext(pContext)
@@ -97,6 +105,18 @@ HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 por
}
HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext, Session::Ptr pSession):
HTTPClientSession(SecureStreamSocket(pContext, pSession)),
_pContext(pContext),
_pSession(pSession)
{
setHost(host);
setPort(port);
SecureStreamSocket sss(socket());
sss.setPeerHostName(host);
}
HTTPSClientSession::~HTTPSClientSession()
{
}
@@ -124,7 +144,16 @@ void HTTPSClientSession::connect(const SocketAddress& address)
{
if (getProxyHost().empty())
{
SecureStreamSocket sss(socket());
if (_pContext->sessionCacheEnabled())
{
sss.useSession(_pSession);
}
HTTPSession::connect(address);
if (_pContext->sessionCacheEnabled())
{
_pSession = sss.currentSession();
}
}
else
{
@@ -144,10 +173,20 @@ void HTTPSClientSession::connect(const SocketAddress& address)
throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason());
StreamSocket proxySocket(proxySession.detachSocket());
SecureStreamSocket secureSocket = SecureStreamSocket::attach(proxySocket, getHost(), _pContext);
SecureStreamSocket secureSocket = SecureStreamSocket::attach(proxySocket, getHost(), _pContext, _pSession);
attachSocket(secureSocket);
if (_pContext->sessionCacheEnabled())
{
_pSession = secureSocket.currentSession();
}
}
}
Session::Ptr HTTPSClientSession::sslSession()
{
return _pSession;
}
} } // namespace Poco::Net

View File

@@ -1,13 +1,13 @@
//
// SSLManager.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SSLManager.cpp#9 $
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SSLManager.cpp#11 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: SSLManager
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -70,6 +70,9 @@ const std::string SSLManager::VAL_CERTIFICATE_HANDLER("ConsoleCertificateHandler
const std::string SSLManager::CFG_SERVER_PREFIX("openSSL.server.");
const std::string SSLManager::CFG_CLIENT_PREFIX("openSSL.client.");
const std::string SSLManager::CFG_CACHE_SESSIONS("cacheSessions");
const std::string SSLManager::CFG_SESSION_ID_CONTEXT("sessionIdContext");
const std::string SSLManager::CFG_SESSION_CACHE_SIZE("sessionCacheSize");
const std::string SSLManager::CFG_SESSION_TIMEOUT("sessionTimeout");
const std::string SSLManager::CFG_EXTENDED_VERIFICATION("extendedVerification");
@@ -254,6 +257,21 @@ void SSLManager::initDefaultContext(bool server)
{
bool cacheSessions = config.getBool(prefix + CFG_CACHE_SESSIONS, false);
_ptrDefaultServerContext->enableSessionCache(cacheSessions);
std::string sessionIdContext = config.getString(prefix + CFG_SESSION_ID_CONTEXT, "");
if (!sessionIdContext.empty())
{
_ptrDefaultServerContext->enableSessionCache(cacheSessions, sessionIdContext);
}
if (config.hasProperty(prefix + CFG_SESSION_CACHE_SIZE))
{
int cacheSize = config.getInt(prefix + CFG_SESSION_CACHE_SIZE);
_ptrDefaultServerContext->setSessionCacheSize(cacheSize);
}
if (config.hasProperty(prefix + CFG_SESSION_TIMEOUT))
{
int timeout = config.getInt(prefix + CFG_SESSION_TIMEOUT);
_ptrDefaultServerContext->setSessionTimeout(timeout);
}
}
bool extendedVerification = config.getBool(prefix + CFG_EXTENDED_VERIFICATION, false);
if (server)

View File

@@ -1,13 +1,13 @@
//
// SecureSocketImpl.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SecureSocketImpl.cpp#18 $
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SecureSocketImpl.cpp#20 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureSocketImpl
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -165,6 +165,11 @@ void SecureSocketImpl::connectSSL(bool performHandshake)
}
SSL_set_bio(_pSSL, pBIO, pBIO);
if (_pSession)
{
SSL_set_session(_pSSL, _pSession->sslSession());
}
try
{
if (performHandshake && _pSocket->getBlocking())
@@ -424,4 +429,38 @@ void SecureSocketImpl::reset()
}
Session::Ptr SecureSocketImpl::currentSession()
{
if (_pSSL)
{
SSL_SESSION* pSession = SSL_get1_session(_pSSL);
if (pSession)
{
if (_pSession && pSession == _pSession->sslSession())
{
SSL_SESSION_free(pSession);
return _pSession;
}
else return new Session(pSession);
}
}
return 0;
}
void SecureSocketImpl::useSession(Session::Ptr pSession)
{
_pSession = pSession;
}
bool SecureSocketImpl::sessionWasReused()
{
if (_pSSL)
return SSL_session_reused(_pSSL) != 0;
else
return false;
}
} } // namespace Poco::Net

View File

@@ -1,13 +1,13 @@
//
// SecureStreamSocket.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SecureStreamSocket.cpp#7 $
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SecureStreamSocket.cpp#9 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureStreamSocket
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -60,6 +60,13 @@ SecureStreamSocket::SecureStreamSocket(Context::Ptr pContext):
}
SecureStreamSocket::SecureStreamSocket(Context::Ptr pContext, Session::Ptr pSession):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
useSession(pSession);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address):
StreamSocket(new SecureStreamSocketImpl(SSLManager::instance().defaultClientContext()))
{
@@ -82,6 +89,14 @@ SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, Context::Pt
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext, Session::Ptr pSession):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
useSession(pSession);
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
@@ -90,6 +105,15 @@ SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, const std::
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext, Session::Ptr pSession):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
static_cast<SecureStreamSocketImpl*>(impl())->setPeerHostName(hostName);
useSession(pSession);
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const Socket& socket):
StreamSocket(socket)
{
@@ -163,6 +187,16 @@ SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket,
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, Context::Ptr pContext, Session::Ptr pSession)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), pContext);
SecureStreamSocket result(pImpl);
result.useSession(pSession);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, const std::string& peerHostName)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), SSLManager::instance().defaultClientContext());
@@ -183,6 +217,17 @@ SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket,
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext, Session::Ptr pSession)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), pContext);
SecureStreamSocket result(pImpl);
result.setPeerHostName(peerHostName);
result.useSession(pSession);
pImpl->connectSSL();
return result;
}
Context::Ptr SecureStreamSocket::context() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->context();
@@ -219,4 +264,22 @@ int SecureStreamSocket::completeHandshake()
}
Session::Ptr SecureStreamSocket::currentSession()
{
return static_cast<SecureStreamSocketImpl*>(impl())->currentSession();
}
void SecureStreamSocket::useSession(Session::Ptr pSession)
{
static_cast<SecureStreamSocketImpl*>(impl())->useSession(pSession);
}
bool SecureStreamSocket::sessionWasReused()
{
return static_cast<SecureStreamSocketImpl*>(impl())->sessionWasReused();
}
} } // namespace Poco::Net

View File

@@ -1,13 +1,13 @@
//
// SecureStreamSocketImpl.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SecureStreamSocketImpl.cpp#9 $
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SecureStreamSocketImpl.cpp#10 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureStreamSocketImpl
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization

View File

@@ -0,0 +1,56 @@
//
// Session.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/src/Session.cpp#1 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: Session
//
// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/Session.h"
namespace Poco {
namespace Net {
Session::Session(SSL_SESSION* pSession):
_pSession(pSession)
{
}
Session::~Session()
{
SSL_SESSION_free(_pSession);
}
} } // namespace Poco::Net

View File

@@ -39,4 +39,10 @@
</invalidCertificateHandler>
</client>
</openSSL>
<testsuite>
<proxy>
<host>proxy.aon.at</host>
<port>8080</port>
</proxy>
</testsuite>
</AppConfig>

View File

@@ -328,7 +328,7 @@
</Filter>
</Filter>
<Filter
Name="HTTPServer"
Name="HTTPSServer"
Filter="">
<Filter
Name="Header Files"

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="TestSuite"
ProjectGUID="{B2B88092-5BCE-4AC0-941E-88167138B4A7}"
Keyword="Win32Proj"
@@ -453,7 +453,7 @@
</Filter>
</Filter>
<Filter
Name="HTTPServer"
Name="HTTPSServer"
>
<Filter
Name="Header Files"

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="TestSuite"
ProjectGUID="{B2B88092-5BCE-4AC0-941E-88167138B4A7}"
Keyword="Win32Proj"
@@ -442,7 +442,7 @@
</Filter>
</Filter>
<Filter
Name="HTTPServer"
Name="HTTPSServer"
>
<Filter
Name="Header Files"

View File

@@ -39,4 +39,10 @@
</invalidCertificateHandler>
</client>
</openSSL>
<testsuite>
<proxy>
<host>proxy.aon.at</host>
<port>8080</port>
</proxy>
</testsuite>
</AppConfig>

View File

@@ -1,7 +1,7 @@
//
// HTTPSClientSessionTest.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.cpp#5 $
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.cpp#6 $
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
@@ -43,10 +43,16 @@
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/Session.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/StreamCopier.h"
#include "Poco/Exception.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Thread.h"
#include "HTTPSTestServer.h"
#include <istream>
#include <ostream>
@@ -54,7 +60,9 @@
using namespace Poco::Net;
using Poco::Util::Application;
using Poco::StreamCopier;
using Poco::Thread;
class TestRequestHandler: public HTTPRequestHandler
@@ -319,7 +327,10 @@ void HTTPSClientSessionTest::testProxy()
{
HTTPSTestServer srv;
HTTPSClientSession s("secure.appinf.com");
s.setProxy("proxy.aon.at", 8080);
s.setProxy(
Application::instance().config().getString("testsuite.proxy.host"),
Application::instance().config().getInt("testsuite.proxy.port")
);
HTTPRequest request(HTTPRequest::HTTP_GET, "/public/poco/NetSSL.txt");
s.sendRequest(request);
X509Certificate cert = s.serverCertificate();
@@ -333,6 +344,96 @@ void HTTPSClientSessionTest::testProxy()
}
void HTTPSClientSessionTest::testCachedSession()
{
// ensure OpenSSL machinery is fully setup
Context::Ptr pDefaultServerContext = SSLManager::instance().defaultServerContext();
Context::Ptr pDefaultClientContext = SSLManager::instance().defaultClientContext();
Context::Ptr pServerContext = new Context(
Context::SERVER_USE,
Application::instance().config().getString("openSSL.server.privateKeyFile"),
Application::instance().config().getString("openSSL.server.privateKeyFile"),
Application::instance().config().getString("openSSL.server.caConfig"),
Context::VERIFY_NONE,
9,
true,
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
pServerContext->enableSessionCache(true, "TestSuite");
pServerContext->setSessionTimeout(10);
pServerContext->setSessionCacheSize(1000);
pServerContext->disableStatelessSessionResumption();
HTTPSTestServer srv(pServerContext);
Context::Ptr pClientContext = new Context(
Context::SERVER_USE,
Application::instance().config().getString("openSSL.client.privateKeyFile"),
Application::instance().config().getString("openSSL.client.privateKeyFile"),
Application::instance().config().getString("openSSL.client.caConfig"),
Context::VERIFY_RELAXED,
9,
true,
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
pClientContext->enableSessionCache(true);
HTTPSClientSession s1("localhost", srv.port(), pClientContext);
HTTPRequest request1(HTTPRequest::HTTP_GET, "/small");
s1.sendRequest(request1);
Session::Ptr pSession1 = s1.sslSession();
HTTPResponse response1;
std::istream& rs1 = s1.receiveResponse(response1);
assert (response1.getContentLength() == HTTPSTestServer::SMALL_BODY.length());
assert (response1.getContentType() == "text/plain");
std::ostringstream ostr1;
StreamCopier::copyStream(rs1, ostr1);
assert (ostr1.str() == HTTPSTestServer::SMALL_BODY);
HTTPSClientSession s2("localhost", srv.port(), pClientContext, pSession1);
HTTPRequest request2(HTTPRequest::HTTP_GET, "/small");
s2.sendRequest(request2);
Session::Ptr pSession2 = s2.sslSession();
HTTPResponse response2;
std::istream& rs2 = s2.receiveResponse(response2);
assert (response2.getContentLength() == HTTPSTestServer::SMALL_BODY.length());
assert (response2.getContentType() == "text/plain");
std::ostringstream ostr2;
StreamCopier::copyStream(rs2, ostr2);
assert (ostr2.str() == HTTPSTestServer::SMALL_BODY);
assert (pSession1 == pSession2);
HTTPRequest request3(HTTPRequest::HTTP_GET, "/small");
s2.sendRequest(request3);
Session::Ptr pSession3 = s2.sslSession();
HTTPResponse response3;
std::istream& rs3 = s2.receiveResponse(response3);
assert (response3.getContentLength() == HTTPSTestServer::SMALL_BODY.length());
assert (response3.getContentType() == "text/plain");
std::ostringstream ostr3;
StreamCopier::copyStream(rs3, ostr3);
assert (ostr3.str() == HTTPSTestServer::SMALL_BODY);
assert (pSession1 == pSession3);
Thread::sleep(15000); // wait for session to expire
pServerContext->flushSessionCache();
HTTPRequest request4(HTTPRequest::HTTP_GET, "/small");
s2.sendRequest(request4);
Session::Ptr pSession4 = s2.sslSession();
HTTPResponse response4;
std::istream& rs4 = s2.receiveResponse(response4);
assert (response4.getContentLength() == HTTPSTestServer::SMALL_BODY.length());
assert (response4.getContentType() == "text/plain");
std::ostringstream ostr4;
StreamCopier::copyStream(rs4, ostr4);
assert (ostr4.str() == HTTPSTestServer::SMALL_BODY);
assert (pSession1 != pSession4);
}
void HTTPSClientSessionTest::setUp()
{
}
@@ -358,6 +459,7 @@ CppUnit::Test* HTTPSClientSessionTest::suite()
CppUnit_addTest(pSuite, HTTPSClientSessionTest, testKeepAlive);
CppUnit_addTest(pSuite, HTTPSClientSessionTest, testInterop);
CppUnit_addTest(pSuite, HTTPSClientSessionTest, testProxy);
CppUnit_addTest(pSuite, HTTPSClientSessionTest, testCachedSession);
return pSuite;
}

View File

@@ -1,7 +1,7 @@
//
// HTTPSClientSessionTest.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.h#5 $
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.h#6 $
//
// Definition of the HTTPSClientSessionTest class.
//
@@ -57,6 +57,7 @@ public:
void testKeepAlive();
void testInterop();
void testProxy();
void testCachedSession();
void setUp();
void tearDown();

View File

@@ -1,7 +1,7 @@
//
// HTTPSStreamFactoryTest.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSStreamFactoryTest.cpp#2 $
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSStreamFactoryTest.cpp#3 $
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
@@ -35,6 +35,8 @@
#include "CppUnit/TestSuite.h"
#include "Poco/Net/HTTPSStreamFactory.h"
#include "Poco/Net/NetException.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/URI.h"
#include "Poco/Exception.h"
#include "Poco/StreamCopier.h"
@@ -46,6 +48,7 @@
using Poco::Net::HTTPSStreamFactory;
using Poco::Net::NetException;
using Poco::Net::HTTPException;
using Poco::Util::Application;
using Poco::URI;
using Poco::StreamCopier;
@@ -102,8 +105,11 @@ void HTTPSStreamFactoryTest::testRedirect()
void HTTPSStreamFactoryTest::testProxy()
{
HTTPSTestServer server;
HTTPSStreamFactory factory("proxy.aon.at", 8080);
URI uri("https://sourceforge.net/");
HTTPSStreamFactory factory(
Application::instance().config().getString("testsuite.proxy.host"),
Application::instance().config().getInt("testsuite.proxy.port")
);
URI uri("https://secure.appinf.com/public/poco/NetSSL.txt");
std::auto_ptr<std::istream> pStr(factory.open(uri));
std::ostringstream ostr;
StreamCopier::copyStream(*pStr.get(), ostr);

View File

@@ -1,7 +1,7 @@
//
// HTTPSTestServer.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSTestServer.cpp#3 $
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSTestServer.cpp#4 $
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
@@ -61,6 +61,17 @@ HTTPSTestServer::HTTPSTestServer():
}
HTTPSTestServer::HTTPSTestServer(Poco::Net::Context::Ptr pContext):
_socket(SocketAddress(), 64, pContext),
_thread("HTTPSTestServer"),
_stop(false)
{
_thread.start(*this);
_ready.wait();
_lastRequest.reserve(4000);
}
HTTPSTestServer::~HTTPSTestServer()
{
_stop = true;

View File

@@ -1,7 +1,7 @@
//
// HTTPSTestServer.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSTestServer.h#1 $
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/HTTPSTestServer.h#2 $
//
// Definition of the HTTPSTestServer class.
//
@@ -49,6 +49,9 @@ public:
HTTPSTestServer();
/// Creates the HTTPSTestServer.
explicit HTTPSTestServer(Poco::Net::Context::Ptr pContext);
/// Creates the HTTPSTestServer using the given Context.
~HTTPSTestServer();
/// Destroys the HTTPSTestServer.

View File

@@ -1,7 +1,7 @@
//
// TCPServerTest.cpp
//
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/TCPServerTest.cpp#3 $
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/TCPServerTest.cpp#5 $
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
@@ -39,6 +39,11 @@
#include "Poco/Net/TCPServerParams.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureServerSocket.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/Session.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/Thread.h"
#include <iostream>
@@ -52,7 +57,11 @@ using Poco::Net::StreamSocket;
using Poco::Net::SecureStreamSocket;
using Poco::Net::SecureServerSocket;
using Poco::Net::SocketAddress;
using Poco::Net::Context;
using Poco::Net::Session;
using Poco::Net::SSLManager;
using Poco::Thread;
using Poco::Util::Application;
namespace
@@ -300,6 +309,100 @@ void TCPServerTest::testReuseSocket()
}
void TCPServerTest::testReuseSession()
{
// ensure OpenSSL machinery is fully setup
Context::Ptr pDefaultServerContext = SSLManager::instance().defaultServerContext();
Context::Ptr pDefaultClientContext = SSLManager::instance().defaultClientContext();
Context::Ptr pServerContext = new Context(
Context::SERVER_USE,
Application::instance().config().getString("openSSL.server.privateKeyFile"),
Application::instance().config().getString("openSSL.server.privateKeyFile"),
Application::instance().config().getString("openSSL.server.caConfig"),
Context::VERIFY_NONE,
9,
true,
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
pServerContext->enableSessionCache(true, "TestSuite");
pServerContext->setSessionTimeout(10);
pServerContext->setSessionCacheSize(1000);
pServerContext->disableStatelessSessionResumption();
SecureServerSocket svs(0, 64, pServerContext);
TCPServer srv(new TCPServerConnectionFactoryImpl<EchoConnection>(), svs);
srv.start();
assert (srv.currentConnections() == 0);
assert (srv.currentThreads() == 0);
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 0);
Context::Ptr pClientContext = new Context(
Context::SERVER_USE,
Application::instance().config().getString("openSSL.client.privateKeyFile"),
Application::instance().config().getString("openSSL.client.privateKeyFile"),
Application::instance().config().getString("openSSL.client.caConfig"),
Context::VERIFY_RELAXED,
9,
true,
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
pClientContext->enableSessionCache(true);
SocketAddress sa("localhost", svs.address().port());
SecureStreamSocket ss1(sa, pClientContext);
assert (!ss1.sessionWasReused());
std::string data("hello, world");
ss1.sendBytes(data.data(), (int) data.size());
char buffer[256];
int n = ss1.receiveBytes(buffer, sizeof(buffer));
assert (n > 0);
assert (std::string(buffer, n) == data);
assert (srv.currentConnections() == 1);
assert (srv.currentThreads() == 1);
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 1);
Session::Ptr pSession = ss1.currentSession();
ss1.close();
Thread::sleep(300);
assert (srv.currentConnections() == 0);
ss1.useSession(pSession);
ss1.connect(sa);
assert (ss1.sessionWasReused());
assert (ss1.currentSession() == pSession);
ss1.sendBytes(data.data(), (int) data.size());
n = ss1.receiveBytes(buffer, sizeof(buffer));
assert (n > 0);
assert (std::string(buffer, n) == data);
assert (srv.currentConnections() == 1);
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 2);
ss1.close();
Thread::sleep(300);
assert (srv.currentConnections() == 0);
Thread::sleep(15000); // wait for session to expire
pServerContext->flushSessionCache();
ss1.useSession(pSession);
ss1.connect(sa);
assert (!ss1.sessionWasReused());
assert (ss1.currentSession() != pSession);
ss1.sendBytes(data.data(), (int) data.size());
n = ss1.receiveBytes(buffer, sizeof(buffer));
assert (n > 0);
assert (std::string(buffer, n) == data);
assert (srv.currentConnections() == 1);
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 3);
ss1.close();
Thread::sleep(300);
assert (srv.currentConnections() == 0);
}
void TCPServerTest::setUp()
{
}
@@ -318,6 +421,7 @@ CppUnit::Test* TCPServerTest::suite()
CppUnit_addTest(pSuite, TCPServerTest, testTwoConnections);
CppUnit_addTest(pSuite, TCPServerTest, testMultiConnections);
CppUnit_addTest(pSuite, TCPServerTest, testReuseSocket);
CppUnit_addTest(pSuite, TCPServerTest, testReuseSession);
return pSuite;
}

View File

@@ -1,7 +1,7 @@
//
// TCPServerTest.h
//
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/TCPServerTest.h#2 $
// $Id: //poco/1.3/NetSSL_OpenSSL/testsuite/src/TCPServerTest.h#3 $
//
// Definition of the TCPServerTest class.
//
@@ -50,6 +50,7 @@ public:
void testTwoConnections();
void testMultiConnections();
void testReuseSocket();
void testReuseSession();
void setUp();
void tearDown();

View File

@@ -39,4 +39,10 @@
</invalidCertificateHandler>
</client>
</openSSL>
<testsuite>
<proxy>
<host>proxy.aon.at</host>
<port>8080</port>
</proxy>
</testsuite>
</AppConfig>