/*************************************************************************** * Copyright (C) 2005 by Jeff Ferr * * root@sat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef J_SSLSOCKET6_H #define J_SSLSOCKET6_H #include "jinetaddress.h" #include "jserversocket6.h" #include "jsocketoptions.h" #include "jsslsocketinputstream.h" #include "jsslsocketoutputstream.h" #include "jconnection.h" #ifdef _WIN32 #include #else #include #include #include #include #include #include #endif #include /** * It's VERY important that these types really have the right sizes! * */ #define COMPILE_TIME_ASSERT(name, x) typedef int _dummy_ ## name[(x) * 2 - 1] COMPILE_TIME_ASSERT(uint8, sizeof(uint8_t) == 1); COMPILE_TIME_ASSERT(sint8, sizeof(int8_t) == 1); COMPILE_TIME_ASSERT(uint16, sizeof(uint16_t) == 2); COMPILE_TIME_ASSERT(sint16, sizeof(int16_t) == 2); COMPILE_TIME_ASSERT(uint32, sizeof(uint32_t) == 4); COMPILE_TIME_ASSERT(sint32, sizeof(int32_t) == 4); #undef COMPILE_TIME_ASSERT /** * Default values for RSA key generation * */ #define RSA_KEYSIZE 512 #define RSA_KEYEXP RSA_F4 /* 65537 */ namespace jsocket { class ServerSocket; /** * \brief Socket. * * \author Jeff Ferr */ class SSLSocket6 : public jsocket::Connection{ friend class SSLServerSocket6; //Socket * ServerSocket::Accept(); private: /** \brief Socket handler. */ jsocket_t _fd; /** \brief */ SSLSocketInputStream *_is; /** \brief */ SSLSocketOutputStream *_os; /** \brief */ sockaddr_in6 _lsock; /** \brief */ sockaddr_in6 _server_sock; /** \brief */ InetAddress *_address; /** \brief Bytes sent. */ int64_t _sent_bytes; /** \brief Bytes received. */ int64_t _receive_bytes; /** \brief */ int _timeout; /** * \brief Create a new socket. * */ void CreateSocket(); /** * \brief * */ void BindSocket(InetAddress *, int); /** * \brief Connect the socket. * */ void ConnectSocket(InetAddress *, int); /** * \brief * */ void InitStreams(int rbuf, int wbuf); /** * Create new CTX if none is available * */ virtual bool CheckContext(); /** * Create temp cert if no other is loaded * */ virtual bool CheckCert(); /** * Helper function: converts from X509 format to ASCII PEM format * */ int GetCertPEM(X509 *cert, std::string *pem); /** * \brief * */ bool Accept(); /** \brief SSL data */ SSL_CTX *ctx; /** \brief SSL data */ SSL *ssl; /** \brief Indicate CERT loaded or created */ bool have_cert; /** \brief keysize argument from constructor */ int rsa_keysize; /** \brief userdata */ char *ud; private: /** * \brief Constructor. * */ SSLSocket6(int handler_, struct sockaddr_in6 server_, int keysize = RSA_KEYSIZE, int timeout_ = 0, int rbuf_ = 65535, int wbuf_ = 4096); public: /** * \brief Constructor. * */ SSLSocket6(InetAddress *addr_, int port_, int keysize = RSA_KEYSIZE, int timeout_ = 0, int rbuf_ = 65535, int wbuf_ = 4096); /** * \brief Constructor. * */ SSLSocket6(InetAddress *addr_, int port_, InetAddress *local_addr_, int local_port_, int keysize = RSA_KEYSIZE, int timeout_ = 0, int rbuf_ = 65535, int wbuf_ = 4096); /** * \brief * */ SSLSocket6(std::string host_, int port_, int keysize = RSA_KEYSIZE, int timeout_ = 0, int rbuf_ = 65535, int wbuf_ = 4096); /** * \brief Constructor. * */ SSLSocket6(std::string host_, int port_, InetAddress *local_addr_, int local_port_, int keysize = RSA_KEYSIZE, int timeout_ = 0, int rbuf_ = 4096, int wbuf_ = 4096); /** * \brief Destrutor virtual. * */ virtual ~SSLSocket6(); virtual jsocket_t GetHandler(); /** * \brief Send bytes to a destination. * */ virtual int Send(const char *b_, int size_, bool block_ = true); /** * \brief Send bytes to a destination waiting a timeout. * */ virtual int Send(const char *b_, int size_, int time_); /** * \brief Receive bytes from a source. * * \return the number of bytes received, or 0 if the peer has shutdown (now throws). * * \exception SocketException an error occurred. * */ virtual int Receive(char *data_, int data_length_, bool block_ = true); /** * \brief Receive bytes from a source waiting a timeout. * */ virtual int Receive(char *data_, int data_length_, int time_); /** * \brief Close the socket. * */ virtual void Close(); /** * \brief * */ virtual jio::InputStream * GetInputStream(); /** * \brief * */ virtual jio::OutputStream * GetOutputStream(); /** * \brief * */ InetAddress * GetInetAddress(); /** * \brief Get the local port. * */ int GetLocalPort(); /** * \brief Get the port. * */ int GetPort(); /** * \brief Get the bytes sent to a destination. * */ virtual int64_t GetSentBytes(); /** * \brief Get de bytes received from a source. * */ virtual int64_t GetReadedBytes(); /** * \brief Get the socket options. * */ SocketOptions * GetSocketOptions(); /** * Cert files (if not set, a temporary RSA session cert will be created if needed) * * PEM format */ bool UseCert(const char *cert_file, const char *private_key_file); /** * As use_cert() but also give pasord for private_key_file (or get OpenSSL's standard prompt each time) * */ bool UseCertPassword(const char *cert_file, const char *private_key_file, std::string pasd); /** * Or specify a pasord callback given to OpenSSL that hands back the pasord to be used * during decryption. On invocation a pointer to userdata is provided. The pem_pasd_cb * must write the pasord into the provided buffer buf which is of size size. The actual * length of the pasord must be returned to the calling function. rwflag indicates * whether the callback is used for reading/decryption (rwflag=0) or writing/encryption * (rwflag=1). * * See man SSL_CTX_set_default_pasd_cb(3) for more information. */ bool UseCertCallback(const char *cert_file, const char *private_key_file, int pasd_cb(char *buf, int size, int rwflag, void *userdata), char *userdata = NULL); /** * Use Diffie-Hellman key exchange? * * See man SSL_CTX_set_tmp_dh_callback(3) for more information. */ bool UseDHFile(const char *dh_file); /** * Should the peer certificate be verified ? The arguments specifies the locations at which CA * certificates for verification purposes are located. The certificates available via ca_file * and ca_dir are trusted. * * See man SSL_CTX_load_verify_locations(3) for format information. */ bool UseVerification(const char *ca_file, const char *ca_dir); /** * Get information about peer certificate. Should be called after connect() or accept() when * using verification * */ struct peer_cert_info_t { // Issuer name std::string commonName; // CN std::string countryName; // C std::string localityName; // L std::string stateOrProvinceName; // ST std::string organizationName; // O std::string organizationalUnitName; // OU std::string title; // T std::string initials; // I std::string givenName; // G std::string surname; // S std::string description; // D std::string uniqueIdentifier; // UID std::string emailAddress; // Email // Expire dates std::string notBefore; std::string notAfter; // Misc. data long serialNumber; long version; std::string sgnAlgorithm; std::string keyAlgorithm; int keySize; }; bool GetPeerCertInfo(peer_cert_info_t *info); /** * Get peer certificate in PEM (ASCII) format. Should be called after connect() or accept() * when using verification. * * Returns the length of pem or -1 on errors */ int GetPeerCertPEM(std::string *pem); /** * \brief * */ virtual std::string what(); }; } #endif