1 /* 2 * Copyright 2013-2015 Haiku, Inc. 3 * Copyright 2011-2015, Axel Dörfler, axeld@pinc-software.de. 4 * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de> 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include <SecureSocket.h> 10 11 #ifdef OPENSSL_ENABLED 12 # include <openssl/ssl.h> 13 #endif 14 15 #include <pthread.h> 16 17 #include <Certificate.h> 18 #include <FindDirectory.h> 19 #include <Path.h> 20 21 #include "CertificatePrivate.h" 22 23 24 //#define TRACE_SOCKET 25 #ifdef TRACE_SOCKET 26 # define TRACE(x...) printf(x) 27 #else 28 # define TRACE(x...) ; 29 #endif 30 31 32 #ifdef OPENSSL_ENABLED 33 34 35 class BSecureSocket::Private { 36 public: 37 Private(); 38 ~Private(); 39 40 status_t InitCheck(); 41 status_t ErrorCode(int returnValue); 42 43 static SSL_CTX* Context(); 44 static int VerifyCallback(int ok, X509_STORE_CTX* ctx); 45 46 private: 47 static void _CreateContext(); 48 49 public: 50 SSL* fSSL; 51 BIO* fBIO; 52 static int sDataIndex; 53 54 private: 55 static SSL_CTX* sContext; 56 // FIXME When do we SSL_CTX_free it? 57 static pthread_once_t sInitOnce; 58 }; 59 60 61 /* static */ SSL_CTX* BSecureSocket::Private::sContext = NULL; 62 /* static */ int BSecureSocket::Private::sDataIndex; 63 /* static */ pthread_once_t BSecureSocket::Private::sInitOnce 64 = PTHREAD_ONCE_INIT; 65 66 67 BSecureSocket::Private::Private() 68 : 69 fSSL(NULL), 70 fBIO(BIO_new(BIO_s_socket())) 71 { 72 } 73 74 75 BSecureSocket::Private::~Private() 76 { 77 // SSL_free also frees the underlying BIO. 78 if (fSSL != NULL) 79 SSL_free(fSSL); 80 else { 81 // The SSL session was never created (Connect() was not called or 82 // failed). We must free the BIO we created in the constructor. 83 BIO_free(fBIO); 84 } 85 } 86 87 88 status_t 89 BSecureSocket::Private::InitCheck() 90 { 91 if (fBIO == NULL) 92 return B_NO_MEMORY; 93 return B_OK; 94 } 95 96 97 status_t 98 BSecureSocket::Private::ErrorCode(int returnValue) 99 { 100 int error = SSL_get_error(fSSL, returnValue); 101 switch (error) { 102 case SSL_ERROR_NONE: 103 // Shouldn't happen... 104 return B_NO_ERROR; 105 case SSL_ERROR_ZERO_RETURN: 106 // Socket is closed 107 return B_CANCELED; 108 case SSL_ERROR_SSL: 109 // Probably no certificate 110 return B_NOT_ALLOWED; 111 112 case SSL_ERROR_WANT_READ: 113 case SSL_ERROR_WANT_WRITE: 114 case SSL_ERROR_WANT_CONNECT: 115 case SSL_ERROR_WANT_ACCEPT: 116 case SSL_ERROR_WANT_X509_LOOKUP: 117 case SSL_ERROR_SYSCALL: 118 default: 119 // TODO: translate SSL error codes! 120 fprintf(stderr, "SSL error: %d\n", error); 121 return B_ERROR; 122 } 123 } 124 125 126 /* static */ SSL_CTX* 127 BSecureSocket::Private::Context() 128 { 129 // We use lazy initialisation here, because reading certificates from disk 130 // and parsing them is a relatively long operation and uses some memory. 131 // We don't want programs that don't use SSL to waste resources with that. 132 pthread_once(&sInitOnce, _CreateContext); 133 134 return sContext; 135 } 136 137 138 /*! This is called each time a certificate verification occurs. It allows us to 139 catch failures and report them. 140 */ 141 /* static */ int 142 BSecureSocket::Private::VerifyCallback(int ok, X509_STORE_CTX* ctx) 143 { 144 // OpenSSL already checked the certificate again the certificate store for 145 // us, and tells the result of that in the ok parameter. 146 147 // If the verification succeeded, no need for any further checks. Let's 148 // proceed with the connection. 149 if (ok) 150 return ok; 151 152 // The certificate verification failed. Signal this to the BSecureSocket. 153 154 // First of all, get the affected BSecureSocket 155 SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, 156 SSL_get_ex_data_X509_STORE_CTX_idx()); 157 BSecureSocket* socket = (BSecureSocket*)SSL_get_ex_data(ssl, sDataIndex); 158 159 // Get the certificate that we could not validate (this may not be the one 160 // we got from the server, but something higher up in the certificate 161 // chain) 162 X509* x509 = X509_STORE_CTX_get_current_cert(ctx); 163 BCertificate::Private* certificate 164 = new(std::nothrow) BCertificate::Private(x509); 165 166 if (certificate == NULL) 167 return 0; 168 169 int error = X509_STORE_CTX_get_error(ctx); 170 const char* message = X509_verify_cert_error_string(error); 171 172 // Let the BSecureSocket (or subclass) decide if we should continue anyway. 173 BCertificate failedCertificate(certificate); 174 return socket->CertificateVerificationFailed(failedCertificate, message); 175 } 176 177 178 /* static */ void 179 BSecureSocket::Private::_CreateContext() 180 { 181 sContext = SSL_CTX_new(SSLv23_method()); 182 183 // Disable legacy protocols. They have known vulnerabilities. 184 SSL_CTX_set_options(sContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); 185 186 // Setup certificate verification 187 BPath certificateStore; 188 find_directory(B_SYSTEM_DATA_DIRECTORY, &certificateStore); 189 certificateStore.Append("ssl/CARootCertificates.pem"); 190 // TODO we may want to add a non-packaged certificate directory? 191 // (would make it possible to store user-added certificate exceptions 192 // there) 193 SSL_CTX_load_verify_locations(sContext, certificateStore.Path(), NULL); 194 SSL_CTX_set_verify(sContext, SSL_VERIFY_PEER, VerifyCallback); 195 196 // OpenSSL 1.0.2 and later: use the alternate "trusted first" algorithm to validate certificate 197 // chains. This makes the validation stop as soon as a recognized certificate is found in the 198 // chain, instead of validating the whole chain, then seeing if the root certificate is known. 199 #ifdef X509_V_FLAG_TRUSTED_FIRST 200 X509_VERIFY_PARAM* verifyParam = X509_VERIFY_PARAM_new(); 201 X509_VERIFY_PARAM_set_flags(verifyParam, X509_V_FLAG_TRUSTED_FIRST); 202 SSL_CTX_set1_param(sContext, verifyParam); 203 204 // TODO we need to free this after freeing the SSL context (which we currently never do) 205 // X509_VERIFY_PARAM_free(verifyParam); 206 #endif 207 208 // Get an unique index number for storing application data in SSL 209 // structs. We will store a pointer to the BSecureSocket class there. 210 sDataIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); 211 } 212 213 214 // # pragma mark - BSecureSocket 215 216 217 BSecureSocket::BSecureSocket() 218 : 219 fPrivate(new(std::nothrow) BSecureSocket::Private()) 220 { 221 fInitStatus = fPrivate != NULL ? fPrivate->InitCheck() : B_NO_MEMORY; 222 } 223 224 225 BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout) 226 : 227 fPrivate(new(std::nothrow) BSecureSocket::Private()) 228 { 229 fInitStatus = fPrivate != NULL ? fPrivate->InitCheck() : B_NO_MEMORY; 230 Connect(peer, timeout); 231 } 232 233 234 BSecureSocket::BSecureSocket(const BSecureSocket& other) 235 : 236 BSocket(other) 237 { 238 fPrivate = new(std::nothrow) BSecureSocket::Private(*other.fPrivate); 239 // TODO: this won't work this way! - write working copy constructor for 240 // Private. 241 242 if (fPrivate != NULL) 243 SSL_set_ex_data(fPrivate->fSSL, Private::sDataIndex, this); 244 else 245 fInitStatus = B_NO_MEMORY; 246 247 } 248 249 250 BSecureSocket::~BSecureSocket() 251 { 252 delete fPrivate; 253 } 254 255 256 status_t 257 BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) 258 { 259 status_t status = InitCheck(); 260 if (status != B_OK) 261 return status; 262 263 status = BSocket::Connect(peer, timeout); 264 if (status != B_OK) 265 return status; 266 267 return _Setup(); 268 } 269 270 271 void 272 BSecureSocket::Disconnect() 273 { 274 if (IsConnected()) { 275 if (fPrivate->fSSL != NULL) 276 SSL_shutdown(fPrivate->fSSL); 277 278 BSocket::Disconnect(); 279 } 280 } 281 282 283 status_t 284 BSecureSocket::WaitForReadable(bigtime_t timeout) const 285 { 286 if (fInitStatus != B_OK) 287 return fInitStatus; 288 if (!IsConnected()) 289 return B_ERROR; 290 291 if (SSL_pending(fPrivate->fSSL) > 0) 292 return B_OK; 293 294 return BSocket::WaitForReadable(timeout); 295 } 296 297 298 status_t 299 BSecureSocket::InitCheck() 300 { 301 if (fPrivate == NULL) 302 return B_NO_MEMORY; 303 304 status_t state = fPrivate->InitCheck(); 305 return state; 306 } 307 308 309 bool 310 BSecureSocket::CertificateVerificationFailed(BCertificate&, const char*) 311 { 312 // Until apps actually make use of the certificate API, let's keep the old 313 // behavior and accept all connections, even if the certificate validation 314 // didn't work. 315 return true; 316 } 317 318 319 // #pragma mark - BDataIO implementation 320 321 322 ssize_t 323 BSecureSocket::Read(void* buffer, size_t size) 324 { 325 if (!IsConnected()) 326 return B_ERROR; 327 328 int bytesRead = SSL_read(fPrivate->fSSL, buffer, size); 329 if (bytesRead >= 0) 330 return bytesRead; 331 332 return fPrivate->ErrorCode(bytesRead); 333 } 334 335 336 ssize_t 337 BSecureSocket::Write(const void* buffer, size_t size) 338 { 339 if (!IsConnected()) 340 return B_ERROR; 341 342 int bytesWritten = SSL_write(fPrivate->fSSL, buffer, size); 343 if (bytesWritten >= 0) 344 return bytesWritten; 345 346 return fPrivate->ErrorCode(bytesWritten); 347 } 348 349 350 status_t 351 BSecureSocket::_Setup() 352 { 353 // Do this only after BSocket::Connect has checked wether we're already 354 // connected. We don't want to kill an existing SSL session, as that would 355 // likely crash the protocol loop for it. 356 if (fPrivate->fSSL != NULL) { 357 SSL_free(fPrivate->fSSL); 358 } 359 360 fPrivate->fSSL = SSL_new(BSecureSocket::Private::Context()); 361 if (fPrivate->fSSL == NULL) { 362 BSocket::Disconnect(); 363 return B_NO_MEMORY; 364 } 365 366 BIO_set_fd(fPrivate->fBIO, fSocket, BIO_NOCLOSE); 367 SSL_set_bio(fPrivate->fSSL, fPrivate->fBIO, fPrivate->fBIO); 368 SSL_set_ex_data(fPrivate->fSSL, Private::sDataIndex, this); 369 370 int returnValue = SSL_connect(fPrivate->fSSL); 371 if (returnValue <= 0) { 372 TRACE("SSLConnection can't connect\n"); 373 BSocket::Disconnect(); 374 return fPrivate->ErrorCode(returnValue); 375 } 376 377 return B_OK; 378 } 379 380 381 #else // OPENSSL_ENABLED 382 383 384 // #pragma mark - No-SSL stubs 385 386 387 BSecureSocket::BSecureSocket() 388 { 389 } 390 391 392 BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout) 393 { 394 fInitStatus = B_UNSUPPORTED; 395 } 396 397 398 BSecureSocket::BSecureSocket(const BSecureSocket& other) 399 : 400 BSocket(other) 401 { 402 } 403 404 405 BSecureSocket::~BSecureSocket() 406 { 407 } 408 409 410 bool 411 BSecureSocket::CertificateVerificationFailed(BCertificate& certificate, const char*) 412 { 413 (void)certificate; 414 return false; 415 } 416 417 418 status_t 419 BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) 420 { 421 return fInitStatus = B_UNSUPPORTED; 422 } 423 424 425 void 426 BSecureSocket::Disconnect() 427 { 428 } 429 430 431 status_t 432 BSecureSocket::WaitForReadable(bigtime_t timeout) const 433 { 434 return B_UNSUPPORTED; 435 } 436 437 438 // #pragma mark - BDataIO implementation 439 440 441 ssize_t 442 BSecureSocket::Read(void* buffer, size_t size) 443 { 444 return B_UNSUPPORTED; 445 } 446 447 448 ssize_t 449 BSecureSocket::Write(const void* buffer, size_t size) 450 { 451 return B_UNSUPPORTED; 452 } 453 454 455 status_t 456 BSecureSocket::InitCheck() 457 { 458 return B_UNSUPPORTED; 459 } 460 461 462 status_t 463 BSecureSocket::_Setup() 464 { 465 return B_UNSUPPORTED; 466 } 467 468 469 #endif // !OPENSSL_ENABLED 470