diff options
Diffstat (limited to 'drivers/openssl')
-rw-r--r-- | drivers/openssl/stream_peer_ssl.cpp | 168 | ||||
-rw-r--r-- | drivers/openssl/stream_peer_ssl.h | 37 |
2 files changed, 104 insertions, 101 deletions
diff --git a/drivers/openssl/stream_peer_ssl.cpp b/drivers/openssl/stream_peer_ssl.cpp index aaedd7dde9..19a17ea0cd 100644 --- a/drivers/openssl/stream_peer_ssl.cpp +++ b/drivers/openssl/stream_peer_ssl.cpp @@ -1,111 +1,97 @@ #include "stream_peer_ssl.h" -int StreamPeerSSL::bio_create( BIO *b ) { - b->init = 1; - b->num = 0; - b->ptr = NULL; - b->flags = 0; - return 1; -} - -int StreamPeerSSL::bio_destroy( BIO *b ) { - - if ( b == NULL ) return 0; - b->ptr = NULL; /* sb_tls_remove() will free it */ - b->init = 0; - b->flags = 0; - return 1; -} - -int StreamPeerSSL::bio_read( BIO *b, char *buf, int len ) { - - if ( buf == NULL || len <= 0 ) return 0; - - StreamPeerSSL * sp = (StreamPeerSSL*)b->ptr; +Error StreamPeerSSL::connect(const String &p_host,int p_port,int p_flags) { - if (sp->base.is_null()) - return 0; - - - - BIO_clear_retry_flags( b ); - - Error err; - int ret=0; - if (sp->block) { - err = sp->base->get_data((const uint8_t*)buf,len); - if (err==OK) - ret=len; - } else { - - err = sp->base->get_partial_data((const uint8_t*)buf,len,ret); - if (err==OK && ret!=len) { - BIO_set_retry_write( b ); - } + // Set up a SSL_CTX object, which will tell our BIO object how to do its work + ctx = SSL_CTX_new(SSLv23_client_method()); + // Create our BIO object for SSL connections. + BIO* bio = BIO_new_ssl_connect(ctx); + // Failure? + if (bio == NULL) { + // We need to free up the SSL_CTX before we leave. + ERR_FAIL_COND_V(bio==NULL,ERR_CANT_CREATE); + } + // Makes ssl point to bio's SSL object. + BIO_get_ssl(bio, &ssl); + // Set the SSL to automatically retry on failure. + SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + // We're connection to google.com on port 443. + BIO_set_conn_hostname(bio, (p_host+":"+itos(p_port)).utf8().get_data()); + + // Same as before, try to connect. + if (BIO_do_connect(bio) <= 0) { + + ERR_EXPLAIN("Failed to connect to '"+p_host+"'' port "+itos(p_port)); + BIO_free_all(bio); + SSL_CTX_free(ctx); + ERR_FAIL_V(ERR_CANT_CONNECT); } - return ret; -} - -int StreamPeerSSL::bio_write( BIO *b, const char *buf, int len ) { - - if ( buf == NULL || len <= 0 ) return 0; - - StreamPeerSSL * sp = (StreamPeerSSL*)b->ptr; - - if (sp->base.is_null()) - return 0; - - BIO_clear_retry_flags( b ); + // Now we need to do the SSL handshake, so we can communicate. + if (BIO_do_handshake(bio) <= 0) { + ERR_EXPLAIN("Failed to handshake to '"+p_host+"'' port "+itos(p_port)); + BIO_free_all(bio); + SSL_CTX_free(ctx); + ERR_FAIL_V(ERR_CANT_CONNECT); + } - Error err; - int wrote=0; - if (sp->block) { - err = sp->base->put_data((const uint8_t*)buf,len); - if (err==OK) - wrote=len; - } else { - err = sp->base->put_partial_data((const uint8_t*)buf,len,wrote); - if (err==OK && wrote!=len) { - BIO_set_retry_write( b ); + // Create a buffer for grabbing information from the page. + char buf[1024]; + memset(buf, 0, sizeof(buf)); + // Create a buffer for the reqest we'll send to the server + char send[1024]; + memset(send, 0, sizeof(send)); + // Create our GET request. + strcat(send, "GET / HTTP/1.1\nHost:google.com\nUser Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)\nConnection: Close\n\n"); + // BIO_puts sends a null-terminated string to the server. In this case it's our GET request. + BIO_puts(bio, send); + // Loop while there's information to be read. + while (1) { + // BIO_read() reads data from the server into a buffer. It returns the number of characters read in. + int x = BIO_read(bio, buf, sizeof(buf) - 1); + // If we haven't read in anything, assume there's nothing more to be sent since we used Connection: Close. + if (x == 0) { + break; + } + // If BIO_read() returns a negative number, there was an error + else if (x < 0) { + // BIO_should_retry lets us know if we should keep trying to read data or not. + if (!BIO_should_retry(bio)) { + printf("\nRead Failed!\n"); + BIO_free_all(bio); + SSL_CTX_free(ctx); + return; + } + } + // We actually got some data, without errors! + else { + // Null-terminate our buffer, just in case + buf[x] = 0; + // Echo what the server sent to the screen + printf("%s", buf); } - } + // Free up that BIO object we created. + BIO_free_all(bio); + // Remember, we also need to free up that SSL_CTX object! + SSL_CTX_free(ctx); + // Return. - return wrote; } -long StreamPeerSSL::bio_ctrl( BIO *b, int cmd, long num, void *ptr ) { - if ( cmd == BIO_CTRL_FLUSH ) { - /* The OpenSSL library needs this */ - return 1; - } - return 0; -} +void StreamPeerSSL::initialize_ssl() { -int StreamPeerSSL::bio_gets( BIO *b, char *buf, int len ) { - return -1; + CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use + SSL_library_init(); // Initialize OpenSSL's SSL libraries + SSL_load_error_strings(); // Load SSL error strings + ERR_load_BIO_strings(); // Load BIO error strings + OpenSSL_add_all_algorithms(); // Load all available encryption algorithms } -int StreamPeerSSL::bio_puts( BIO *b, const char *str ) { - return StreamPeerSSL::bio_write( b, str, strlen( str ) ); -} +void StreamPeerSSL::finalize_ssl(){ -BIO_METHOD StreamPeerSSL::bio_methods = -{ - ( 100 | 0x400 ), /* it's a source/sink BIO */ - "sockbuf glue", - StreamPeerSSL::bio_write, - StreamPeerSSL::bio_read, - StreamPeerSSL::bio_puts, - StreamPeerSSL::bio_gets, - StreamPeerSSL::bio_ctrl, - StreamPeerSSL::bio_create, - StreamPeerSSL::bio_destroy -}; -StreamPeerSSL::StreamPeerSSL() { } diff --git a/drivers/openssl/stream_peer_ssl.h b/drivers/openssl/stream_peer_ssl.h index a126f6122c..74866c2da4 100644 --- a/drivers/openssl/stream_peer_ssl.h +++ b/drivers/openssl/stream_peer_ssl.h @@ -1,26 +1,43 @@ #ifndef STREAM_PEER_SSL_H #define STREAM_PEER_SSL_H +#ifdef OPENSSL_ENABLED + #include "io/stream_peer.h" +#include <openssl/applink.c> // To prevent crashing (see the OpenSSL FAQ) +#include <openssl/bio.h> // BIO objects for I/O +#include <openssl/ssl.h> // SSL and SSL_CTX for SSL connections +#include <openssl/err.h> // Error reporting +#include <stdio.h> // If you don't know what this is for stop reading now. class StreamPeerSSL : public StreamPeer { OBJ_TYPE(StreamPeerSSL,StreamPeer); +public: + + enum ConnectFlags { + + CONNECT_FLAG_BUG_WORKAROUNDS=1, + CONNECT_FLAG_NO_SSLV2=2, + CONNECT_FLAG_NO_SSLV3=4, + CONNECT_FLAG_NO_TLSV1=8, + CONNECT_FLAG_NO_COMPRESSION=16, + }; - Ref<StreamPeer> base; - bool block; - static BIO_METHOD bio_methods; + SSL_CTX* ctx; + SSL* ssl; + BIO* bio; - static int bio_create( BIO *b ); - static int bio_destroy( BIO *b ); - static int bio_read( BIO *b, char *buf, int len ); - static int bio_write( BIO *b, const char *buf, int len ); - static long bio_ctrl( BIO *b, int cmd, long num, void *ptr ); - static int bio_gets( BIO *b, char *buf, int len ); - static int bio_puts( BIO *b, const char *str ); public: + + + Error connect(const String &p_host,int p_port); + static void initialize_ssl(); + static void finalize_ssl(); + StreamPeerSSL(); }; +#endif #endif // STREAM_PEER_SSL_H |