1/* 2 * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de> 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8#include <SecureSocket.h> 9 10#ifdef OPENSSL_ENABLED 11# include <openssl/ssl.h> 12#endif 13 14 15//#define TRACE_SOCKET 16#ifdef TRACE_SOCKET 17# define TRACE(x...) printf(x) 18#else 19# define TRACE(x...) ; 20#endif 21 22 23#ifdef OPENSSL_ENABLED 24 25 26class BSecureSocket::Private { 27public: 28 SSL_CTX* fCTX; 29 SSL* fSSL; 30 BIO* fBIO; 31}; 32 33 34BSecureSocket::BSecureSocket() 35 : 36 fPrivate(NULL) 37{ 38} 39 40 41BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout) 42 : 43 fPrivate(NULL) 44{ 45 Connect(peer, timeout); 46} 47 48 49BSecureSocket::BSecureSocket(const BSecureSocket& other) 50 : 51 BSocket(other) 52{ 53 // TODO: this won't work this way! 54 fPrivate = (BSecureSocket::Private*)malloc(sizeof(BSecureSocket::Private)); 55 if (fPrivate != NULL) 56 memcpy(fPrivate, other.fPrivate, sizeof(BSecureSocket::Private)); 57 else 58 fInitStatus = B_NO_MEMORY; 59} 60 61 62BSecureSocket::~BSecureSocket() 63{ 64 free(fPrivate); 65} 66 67 68status_t 69BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) 70{ 71 if (fPrivate == NULL) { 72 fPrivate = (BSecureSocket::Private*)calloc(1, 73 sizeof(BSecureSocket::Private)); 74 if (fPrivate == NULL) 75 return B_NO_MEMORY; 76 } 77 78 status_t status = BSocket::Connect(peer, timeout); 79 if (status != B_OK) 80 return status; 81 82 fPrivate->fCTX = SSL_CTX_new(SSLv23_method()); 83 fPrivate->fSSL = SSL_new(fPrivate->fCTX); 84 fPrivate->fBIO = BIO_new_socket(fSocket, BIO_NOCLOSE); 85 SSL_set_bio(fPrivate->fSSL, fPrivate->fBIO, fPrivate->fBIO); 86 87 if (SSL_connect(fPrivate->fSSL) <= 0) { 88 TRACE("SSLConnection can't connect\n"); 89 BSocket::Disconnect(); 90 // TODO: translate ssl to Haiku error 91 return B_ERROR; 92 } 93 94 return B_OK; 95} 96 97 98void 99BSecureSocket::Disconnect() 100{ 101 if (IsConnected()) { 102 if (fPrivate->fSSL != NULL) { 103 SSL_shutdown(fPrivate->fSSL); 104 fPrivate->fSSL = NULL; 105 } 106 if (fPrivate->fCTX != NULL) { 107 SSL_CTX_free(fPrivate->fCTX); 108 fPrivate->fCTX = NULL; 109 } 110 if (fPrivate->fBIO != NULL) { 111 BIO_free(fPrivate->fBIO); 112 fPrivate->fBIO = NULL; 113 } 114 } 115 return BSocket::Disconnect(); 116} 117 118 119status_t 120BSecureSocket::WaitForReadable(bigtime_t timeout) const 121{ 122 if (fInitStatus != B_OK) 123 return fInitStatus; 124 if (!IsConnected()) 125 return B_ERROR; 126 127 if (SSL_pending(fPrivate->fSSL) > 0) 128 return B_OK; 129 130 return BSocket::WaitForReadable(timeout); 131} 132 133 134// #pragma mark - BDataIO implementation 135 136 137ssize_t 138BSecureSocket::Read(void* buffer, size_t size) 139{ 140 if (!IsConnected()) 141 return B_ERROR; 142 143 int bytesRead = SSL_read(fPrivate->fSSL, buffer, size); 144 if (bytesRead > 0) 145 return bytesRead; 146 147 // TODO: translate SSL error codes! 148 return B_ERROR; 149} 150 151 152ssize_t 153BSecureSocket::Write(const void* buffer, size_t size) 154{ 155 if (!IsConnected()) 156 return B_ERROR; 157 158 int bytesWritten = SSL_write(fPrivate->fSSL, buffer, size); 159 if (bytesWritten > 0) 160 return bytesWritten; 161 162 // TODO: translate SSL error codes! 163 return B_ERROR; 164} 165 166 167#else // OPENSSL_ENABLED 168 169 170// #pragma mark - No-SSL stubs 171 172 173BSecureSocket::BSecureSocket() 174{ 175} 176 177 178BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout) 179{ 180 fInitStatus = B_UNSUPPORTED; 181} 182 183 184BSecureSocket::BSecureSocket(const BSecureSocket& other) 185 : 186 BSocket(other) 187{ 188} 189 190 191BSecureSocket::~BSecureSocket() 192{ 193} 194 195 196status_t 197BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) 198{ 199 return fInitStatus = B_UNSUPPORTED; 200} 201 202 203void 204BSecureSocket::Disconnect() 205{ 206} 207 208 209status_t 210BSecureSocket::WaitForReadable(bigtime_t timeout) const 211{ 212 return B_UNSUPPORTED; 213} 214 215 216// #pragma mark - BDataIO implementation 217 218 219ssize_t 220BSecureSocket::Read(void* buffer, size_t size) 221{ 222 return B_UNSUPPORTED; 223} 224 225 226ssize_t 227BSecureSocket::Write(const void* buffer, size_t size) 228{ 229 return B_UNSUPPORTED; 230} 231 232 233#endif // !OPENSSL_ENABLED 234