diff options
Diffstat (limited to 'core/io')
-rw-r--r-- | core/io/file_access_encrypted.cpp | 123 | ||||
-rw-r--r-- | core/io/file_access_encrypted.h | 6 | ||||
-rw-r--r-- | core/io/file_access_pack.cpp | 1 | ||||
-rw-r--r-- | core/io/http_client.cpp | 40 | ||||
-rw-r--r-- | core/io/http_client.h | 10 | ||||
-rw-r--r-- | core/io/stream_peer_ssl.cpp | 29 | ||||
-rw-r--r-- | core/io/stream_peer_ssl.h | 34 | ||||
-rw-r--r-- | core/io/stream_peer_tcp.cpp | 7 | ||||
-rw-r--r-- | core/io/stream_peer_tcp.h | 2 |
9 files changed, 219 insertions, 33 deletions
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 49487d4f8f..bcd4197e11 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -2,22 +2,74 @@ #include "aes256.h" #include "md5.h" #include "os/copymem.h" +#include "print_string.h" #define COMP_MAGIC 0x43454447 Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector<uint8_t>& p_key,Mode p_mode) { + print_line("open and parse!"); ERR_FAIL_COND_V(file!=NULL,ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(p_key.size()!=32,ERR_INVALID_PARAMETER); + + pos=0; + eofed=false; if (p_mode==MODE_WRITE_AES256) { - ERR_FAIL_COND_V(p_key.size()!=32,ERR_INVALID_PARAMETER); data.clear(); writing=true; file=p_base; mode=p_mode; key=p_key; + } else if (p_mode==MODE_READ) { + + key=p_key; + uint32_t magic = p_base->get_32(); + print_line("MAGIC: "+itos(magic)); + ERR_FAIL_COND_V(magic!=COMP_MAGIC,ERR_FILE_UNRECOGNIZED); + mode=Mode(p_base->get_32()); + ERR_FAIL_INDEX_V(mode,MODE_MAX,ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(mode==0,ERR_FILE_CORRUPT); + print_line("MODE: "+itos(mode)); + unsigned char md5d[16]; + p_base->get_buffer(md5d,16); + length=p_base->get_64(); + base=p_base->get_pos(); + ERR_FAIL_COND_V(p_base->get_len() < base+length, ERR_FILE_CORRUPT ); + int ds = length; + if (ds % 16) { + ds+=16-(ds % 16); + } + + data.resize(ds); + + int blen = p_base->get_buffer(data.ptr(),ds); + ERR_FAIL_COND_V(blen!=ds,ERR_FILE_CORRUPT); + + aes256_context ctx; + aes256_init(&ctx,key.ptr()); + + for(size_t i=0;i<ds;i+=16) { + + aes256_decrypt_ecb(&ctx,&data[i]); + } + + aes256_done(&ctx); + + data.resize(length); + + MD5_CTX md5; + MD5Init(&md5); + MD5Update(&md5,data.ptr(),data.size()); + MD5Final(&md5); + + + ERR_FAIL_COND_V(String::md5(md5.digest)!=String::md5(md5d),ERR_FILE_CORRUPT) ; + + + file=p_base; } return OK; @@ -57,6 +109,11 @@ void FileAccessEncrypted::close() { len+=16-(len % 16); } + MD5_CTX md5; + MD5Init(&md5); + MD5Update(&md5,data.ptr(),data.size()); + MD5Final(&md5); + compressed.resize(len); zeromem( compressed.ptr(), len ); for(int i=0;i<data.size();i++) { @@ -76,10 +133,6 @@ void FileAccessEncrypted::close() { file->store_32(COMP_MAGIC); file->store_32(mode); - MD5_CTX md5; - MD5Init(&md5); - MD5Update(&md5,compressed.ptr(),compressed.size()); - MD5Final(&md5); file->store_buffer(md5.digest,16); file->store_64(data.size()); @@ -88,9 +141,18 @@ void FileAccessEncrypted::close() { file->close(); memdelete(file); file=NULL; + data.clear(); + + } else { + file->close(); + memdelete(file); + data.clear(); + file=NULL; } + + } bool FileAccessEncrypted::is_open() const{ @@ -100,12 +162,12 @@ bool FileAccessEncrypted::is_open() const{ void FileAccessEncrypted::seek(size_t p_position){ - if (writing) { - if (p_position > (size_t)data.size()) - p_position=data.size(); + if (p_position > (size_t)data.size()) + p_position=data.size(); + + pos=p_position; + eofed=false; - pos=p_position; - } } @@ -116,38 +178,51 @@ void FileAccessEncrypted::seek_end(int64_t p_position){ size_t FileAccessEncrypted::get_pos() const{ return pos; - return 0; } size_t FileAccessEncrypted::get_len() const{ - if (writing) - return data.size(); - return 0; + return data.size(); } bool FileAccessEncrypted::eof_reached() const{ - if (!writing) { + return eofed; +} +uint8_t FileAccessEncrypted::get_8() const{ + ERR_FAIL_COND_V(writing,0); + if (pos>=data.size()) { + eofed=true; + return 0; } - return false; -} - -uint8_t FileAccessEncrypted::get_8() const{ + uint8_t b = data[pos]; + pos++; + return b; - return 0; } int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const{ + ERR_FAIL_COND_V(writing,0); - return 0; + int to_copy=MIN(p_length,data.size()-pos); + for(int i=0;i<to_copy;i++) { + + p_dst[i]=data[pos++]; + } + + if (to_copy<p_length) { + eofed=true; + } + + + return to_copy; } Error FileAccessEncrypted::get_error() const{ - return OK; + return eofed?ERR_FILE_EOF:OK; } void FileAccessEncrypted::store_buffer(const uint8_t *p_src,int p_length) { @@ -210,8 +285,4 @@ FileAccessEncrypted::~FileAccessEncrypted() { if (file) close(); - - if (file) { - memdelete(file); - } } diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index 90796eb2e9..3bdcc2dfd0 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -9,7 +9,8 @@ public: enum Mode { MODE_READ, - MODE_WRITE_AES256 + MODE_WRITE_AES256, + MODE_MAX }; private: @@ -22,7 +23,8 @@ private: size_t base; size_t length; Vector<uint8_t> data; - size_t pos; + mutable size_t pos; + mutable bool eofed; public: diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 45e6990ad2..6a28fa9dae 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -211,6 +211,7 @@ void FileAccessPack::seek(size_t p_position){ } f->seek(pf.offset+p_position); + pos=p_position; } void FileAccessPack::seek_end(int64_t p_position){ diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index f9da846844..59bc5802ea 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -27,14 +27,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "http_client.h" - +#include "io/stream_peer_ssl.h" Error HTTPClient::connect_url(const String& p_url) { return OK; } -Error HTTPClient::connect(const String &p_host,int p_port){ +Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl){ close(); conn_port=p_port; @@ -49,7 +49,11 @@ Error HTTPClient::connect(const String &p_host,int p_port){ } + ssl=p_ssl; connection=tcp_connection; + + + if (conn_host.is_valid_ip_address()) { //is ip Error err = tcp_connection->connect(IP_Address(conn_host),p_port); @@ -233,6 +237,17 @@ Error HTTPClient::poll(){ return OK; //do none } break; case StreamPeerTCP::STATUS_CONNECTED: { + if (ssl) { + Ref<StreamPeerSSL> ssl = StreamPeerSSL::create(); + Error err = ssl->connect(tcp_connection,true,conn_host); + if (err!=OK) { + close(); + status=STATUS_SSL_HANDSHAKE_ERROR; + return ERR_CANT_CONNECT; + } + print_line("SSL! TURNED ON!"); + connection=ssl; + } status=STATUS_CONNECTED; return OK; } break; @@ -525,9 +540,20 @@ HTTPClient::Status HTTPClient::get_status() const { return status; } +void HTTPClient::set_blocking_mode(bool p_enable) { + + blocking=p_enable; +} + +bool HTTPClient::is_blocking_mode_enabled() const{ + + return blocking; +} + + void HTTPClient::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect:Error","host","port"),&HTTPClient::connect); + ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl"),&HTTPClient::connect,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ObjectTypeDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String())); ObjectTypeDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text); @@ -542,9 +568,13 @@ void HTTPClient::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_response_body_length"),&HTTPClient::get_response_body_length); ObjectTypeDB::bind_method(_MD("read_response_body_chunk"),&HTTPClient::read_response_body_chunk); + ObjectTypeDB::bind_method(_MD("set_blocking_mode","enabled"),&HTTPClient::set_blocking_mode); + ObjectTypeDB::bind_method(_MD("is_blocking_mode_enabled"),&HTTPClient::is_blocking_mode_enabled); + ObjectTypeDB::bind_method(_MD("get_status"),&HTTPClient::get_status); ObjectTypeDB::bind_method(_MD("poll:Error"),&HTTPClient::poll); + BIND_CONSTANT( METHOD_GET ); BIND_CONSTANT( METHOD_HEAD ); BIND_CONSTANT( METHOD_POST ); @@ -564,6 +594,7 @@ void HTTPClient::_bind_methods() { BIND_CONSTANT( STATUS_REQUESTING ); // request in progress BIND_CONSTANT( STATUS_BODY ); // request resulted in body ); which must be read BIND_CONSTANT( STATUS_CONNECTION_ERROR ); + BIND_CONSTANT( STATUS_SSL_HANDSHAKE_ERROR ); BIND_CONSTANT( RESPONSE_CONTINUE ); @@ -637,7 +668,8 @@ HTTPClient::HTTPClient(){ body_left=0; chunk_left=0; response_num=0; - + ssl=false; + blocking=false; tmp_read.resize(4096); } diff --git a/core/io/http_client.h b/core/io/http_client.h index 2f22ba1fde..7e60052319 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -126,6 +126,8 @@ public: STATUS_REQUESTING, // request in progress STATUS_BODY, // request resulted in body, which must be read STATUS_CONNECTION_ERROR, + STATUS_SSL_HANDSHAKE_ERROR, + }; private: @@ -134,6 +136,8 @@ private: IP::ResolverID resolving; int conn_port; String conn_host; + bool ssl; + bool blocking; Vector<uint8_t> response_str; @@ -157,7 +161,7 @@ public: Error connect_url(const String& p_url); //connects to a full url and perform request - Error connect(const String &p_host,int p_port); + Error connect(const String &p_host,int p_port,bool p_ssl=false); void set_connection(const Ref<StreamPeer>& p_connection); @@ -177,6 +181,10 @@ public: ByteArray read_response_body_chunk(); // can't get body as partial text because of most encodings UTF8, gzip, etc. + void set_blocking_mode(bool p_enable); //useful mostly if running in a thread + bool is_blocking_mode_enabled() const; + + Error poll(); HTTPClient(); diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp new file mode 100644 index 0000000000..a7132d99ef --- /dev/null +++ b/core/io/stream_peer_ssl.cpp @@ -0,0 +1,29 @@ +#include "stream_peer_ssl.h" + + +StreamPeerSSL* (*StreamPeerSSL::_create)()=NULL; + + +StreamPeerSSL *StreamPeerSSL::create() { + + return _create(); +} + + +void StreamPeerSSL::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("accept:Error","stream:StreamPeer"),&StreamPeerSSL::accept); + ObjectTypeDB::bind_method(_MD("connect:Error","stream:StreamPeer","validate_certs","for_hostname"),&StreamPeerSSL::connect,DEFVAL(false),DEFVAL(String())); + ObjectTypeDB::bind_method(_MD("get_status"),&StreamPeerSSL::get_status); + ObjectTypeDB::bind_method(_MD("disconnect"),&StreamPeerSSL::disconnect); + BIND_CONSTANT( STATUS_DISCONNECTED ); + BIND_CONSTANT( STATUS_CONNECTED ); + BIND_CONSTANT( STATUS_ERROR_NO_CERTIFICATE ); + BIND_CONSTANT( STATUS_ERROR_HOSTNAME_MISMATCH ); + +} + +StreamPeerSSL::StreamPeerSSL() +{ +} diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h new file mode 100644 index 0000000000..be7504cd8f --- /dev/null +++ b/core/io/stream_peer_ssl.h @@ -0,0 +1,34 @@ +#ifndef STREAM_PEER_SSL_H +#define STREAM_PEER_SSL_H + +#include "io/stream_peer.h" + +class StreamPeerSSL : public StreamPeer { + OBJ_TYPE(StreamPeerSSL,StreamPeer); +protected: + static StreamPeerSSL* (*_create)(); + static void _bind_methods(); +public: + + enum Status { + STATUS_DISCONNECTED, + STATUS_CONNECTED, + STATUS_ERROR_NO_CERTIFICATE, + STATUS_ERROR_HOSTNAME_MISMATCH + }; + + virtual Error accept(Ref<StreamPeer> p_base)=0; + virtual Error connect(Ref<StreamPeer> p_base,bool p_validate_certs=false,const String& p_for_hostname=String())=0; + virtual Status get_status() const=0; + + virtual void disconnect()=0; + + static StreamPeerSSL* create(); + + + StreamPeerSSL(); +}; + +VARIANT_ENUM_CAST( StreamPeerSSL::Status ); + +#endif // STREAM_PEER_SSL_H diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 13a158ea4d..0e75e22767 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -34,9 +34,16 @@ void StreamPeerTCP::_bind_methods() { ObjectTypeDB::bind_method(_MD("connect","host","ip"),&StreamPeerTCP::connect); ObjectTypeDB::bind_method(_MD("is_connected"),&StreamPeerTCP::is_connected); + ObjectTypeDB::bind_method(_MD("get_status"),&StreamPeerTCP::get_status); ObjectTypeDB::bind_method(_MD("get_connected_host"),&StreamPeerTCP::get_connected_host); ObjectTypeDB::bind_method(_MD("get_connected_port"),&StreamPeerTCP::get_connected_port); ObjectTypeDB::bind_method(_MD("disconnect"),&StreamPeerTCP::disconnect); + + BIND_CONSTANT( STATUS_NONE ); + BIND_CONSTANT( STATUS_CONNECTING ); + BIND_CONSTANT( STATUS_CONNECTED ); + BIND_CONSTANT( STATUS_ERROR ); + } Ref<StreamPeerTCP> StreamPeerTCP::create_ref() { diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index 69c9d0c592..d447ded78b 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -73,4 +73,6 @@ public: ~StreamPeerTCP(); }; +VARIANT_ENUM_CAST( StreamPeerTCP::Status ); + #endif |