aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
aheinecke@404:  * Software engineering by Intevation GmbH
aheinecke@404:  *
aheinecke@404:  * This file is Free Software under the GNU GPL (v>=2)
aheinecke@404:  * and comes with ABSOLUTELY NO WARRANTY!
aheinecke@404:  * See LICENSE.txt for details.
aheinecke@404:  */
aheinecke@45: #ifndef SSLCONNECTION_H
aheinecke@45: #define SSLCONNECTION_H
aheinecke@45: 
aheinecke@45: /**
aheinecke@45:  * @file sslconnection.h
aheinecke@45:  * @brief Qt wrapper around polarssl ssl api
aheinecke@45:  */
aheinecke@45: 
aheinecke@45: #include <QDebug>
aheinecke@45: #include <QUrl>
aheinecke@45: #include <QString>
aheinecke@45: #include <QByteArray>
aheinecke@45: 
aheinecke@45: #include <polarssl/entropy.h>
aheinecke@45: #include <polarssl/net.h>
aheinecke@45: #include <polarssl/ssl.h>
aheinecke@45: #include <polarssl/ctr_drbg.h>
aheinecke@45: #include <polarssl/error.h>
aheinecke@45: #include <polarssl/certs.h>
aheinecke@45: 
aheinecke@45: class SSLConnection
aheinecke@45: {
aheinecke@45: public:
aheinecke@45:     enum ErrorCode {
aheinecke@45:         NoError,
aheinecke@45:         NoConnection,
aheinecke@45:         SSLHandshakeFailed,
aheinecke@45:         InvalidCertificate,
aheinecke@45:         InvalidPinnedCertificate,
aheinecke@45:         InvalidResponse,
aheinecke@45:         ConnectionLost,
aheinecke@45:         Timeout,
aheinecke@45:         ErrUnknown
aheinecke@45:     };
aheinecke@45: 
aheinecke@45:     /**
aheinecke@45:      * @brief Construct a pinned SSL Connection
aheinecke@45:      *
aheinecke@45:      * @param[in] url the Url to connect to
aheinecke@45:      * @param[in] certificate optional certificate to validate https connection
aheinecke@45:      */
aheinecke@45:     SSLConnection(const QString& url,
aheinecke@45:                   const QByteArray& certificate = QByteArray());
aheinecke@45: 
aheinecke@45:     ~SSLConnection();
aheinecke@45: 
aheinecke@45:     /** @brief write */
aheinecke@45:     int write(const QByteArray& request);
aheinecke@45: 
aheinecke@45:     /**
aheinecke@46:      * @brief read at most len bytes and reset the connection
aheinecke@46:      *
aheinecke@46:      * @param [in] len Amount of bytes to read.
aheinecke@46:      *
aheinecke@46:      * @returns a byte array containing the data or
aheinecke@46:      * a NULL byte array on error*/
aheinecke@45:     QByteArray read(size_t len);
aheinecke@45: 
aheinecke@45:     bool initialized() { return mInitialized; }
aheinecke@45:     bool connected() { return mConnected; }
aheinecke@45: 
aheinecke@45:     ErrorCode getLastError() { return mErrorState; }
aheinecke@45: 
aheinecke@45:     /** @brief: Establish the connection
aheinecke@45:      *
aheinecke@45:      * @returns 0 on success otherwise a polarssl error or -1 is returned
aheinecke@45:      */
aheinecke@45:     int connect();
aheinecke@45: 
aheinecke@45: private:
aheinecke@45:     QUrl mUrl;
aheinecke@45:     QByteArray mPinnedCert;
aheinecke@45:     x509_crt mX509PinnedCert;
aheinecke@45:     entropy_context mEntropy;
aheinecke@45:     ctr_drbg_context mCtr_drbg;
aheinecke@45:     ssl_context mSSL;
aheinecke@46:     ssl_session mSavedSession;
aheinecke@45:     bool mInitialized;
aheinecke@46:     bool mConnected; /* A connection was established */
aheinecke@46:     bool mNeedsReset; /* The connection needs to be reset before the next
aheinecke@46:                          write */
aheinecke@45:     int mServerFD;
aheinecke@45:     SSLConnection::ErrorCode mErrorState;
aheinecke@45:     /* @brief: Initialize polarssl structures
aheinecke@45:      *
aheinecke@45:      * This wraps polarssl initialization functions
aheinecke@45:      * that can return an error.
aheinecke@45:      * Sets the error state accordingly.
aheinecke@45:      *
aheinecke@45:      * @returns: 0 on success a polarssl error otherwise.
aheinecke@45:      */
aheinecke@45:     int init();
aheinecke@46: 
aheinecke@46:     /* @brief Reset the connection.
aheinecke@46:      *
aheinecke@46:      * Resets the https connection and does another handshake.
aheinecke@46:      *
aheinecke@46:      * @returns: 0 on success a polarssl error or -1 otherwise. */
aheinecke@46:     int reset();
aheinecke@46: 
aheinecke@46:     /* @brief validates that the certificate matches the pinned one.
aheinecke@46:      *
aheinecke@46:      * Checks the peer certificate of mSSL and validates that the
aheinecke@46:      * certificate matches mPinnedCertificate.
aheinecke@46:      *
aheinecke@46:      * @returns: 0 on success a polarssl error or -1 otherwise. */
aheinecke@46:     int validateCertificate();
aheinecke@46: 
aheinecke@46:     /* @brief disconnects the connection */
aheinecke@46:     void disconnect();
aheinecke@45: };
aheinecke@45: 
aheinecke@45: #endif