1 /** 2 This is CLIENT only at this point. Don't try to 3 bind/accept with these. 4 5 FIXME: Windows isn't implemented 6 7 On Windows, it uses Microsoft schannel so it doesn't 8 need openssl or gnutls as a dependency. 9 10 On other platforms, it uses the openssl api, which should 11 work with both openssl and gnutls. 12 13 14 btw, interesting: 15 http://msdn.microsoft.com/en-us/library/windows/desktop/aa364510%28v=vs.85%29.aspx 16 */ 17 module sslsocket; 18 19 20 public import std.socket; 21 22 // see also: 23 // http://msdn.microsoft.com/en-us/library/aa380536%28v=vs.85%29.aspx 24 25 // import deimos.openssl.ssl; 26 27 version=use_openssl; 28 29 version(use_openssl) { 30 alias SslClientSocket = OpenSslSocket; 31 32 extern(C) { 33 int SSL_library_init(); 34 void OpenSSL_add_all_ciphers(); 35 void OpenSSL_add_all_digests(); 36 void SSL_load_error_strings(); 37 38 struct SSL {} 39 struct SSL_CTX {} 40 struct SSL_METHOD {} 41 42 SSL_CTX* SSL_CTX_new(const SSL_METHOD* method); 43 SSL* SSL_new(SSL_CTX*); 44 int SSL_pending(SSL*); 45 int SSL_set_fd(SSL*, int); 46 int SSL_connect(SSL*); 47 int SSL_write(SSL*, const void*, int); 48 int SSL_read(SSL*, void*, int); 49 void SSL_free(SSL*); 50 void SSL_CTX_free(SSL_CTX*); 51 52 void SSL_set_verify(SSL*, int, void*); 53 enum SSL_VERIFY_NONE = 0; 54 55 SSL_METHOD* SSLv3_client_method(); 56 SSL_METHOD* TLS_client_method(); 57 SSL_METHOD* SSLv23_client_method(); 58 59 void ERR_print_errors_fp(FILE*); 60 } 61 62 import core.stdc.stdio; 63 64 shared static this() { 65 SSL_library_init(); 66 OpenSSL_add_all_ciphers(); 67 OpenSSL_add_all_digests(); 68 SSL_load_error_strings(); 69 } 70 71 pragma(lib, "crypto"); 72 pragma(lib, "ssl"); 73 74 class OpenSslSocket : Socket { 75 private SSL* ssl; 76 private SSL_CTX* ctx; 77 private void initSsl(bool verifyPeer) { 78 ctx = SSL_CTX_new(SSLv23_client_method()); 79 assert(ctx !is null); 80 81 ssl = SSL_new(ctx); 82 if(!verifyPeer) 83 SSL_set_verify(ssl, SSL_VERIFY_NONE, null); 84 SSL_set_fd(ssl, cast(int) this.handle); 85 } 86 87 bool dataPending() { 88 return SSL_pending(ssl) > 0; 89 } 90 91 @trusted 92 override void connect(Address to) { 93 super.connect(to); 94 if(SSL_connect(ssl) == -1) { 95 ERR_print_errors_fp(stderr); 96 int i; 97 printf("wtf\n"); 98 scanf("%d\n", i); 99 throw new Exception("ssl connect"); 100 } 101 } 102 103 @trusted 104 override ptrdiff_t send(const(void)[] buf, SocketFlags flags) { 105 auto retval = SSL_write(ssl, buf.ptr, cast(uint) buf.length); 106 if(retval == -1) { 107 ERR_print_errors_fp(stderr); 108 int i; 109 printf("wtf\n"); 110 scanf("%d\n", i); 111 throw new Exception("ssl send"); 112 } 113 return retval; 114 115 } 116 override ptrdiff_t send(const(void)[] buf) { 117 return send(buf, SocketFlags.NONE); 118 } 119 @trusted 120 override ptrdiff_t receive(void[] buf, SocketFlags flags) { 121 auto retval = SSL_read(ssl, buf.ptr, cast(int)buf.length); 122 if(retval == -1) { 123 ERR_print_errors_fp(stderr); 124 int i; 125 printf("wtf\n"); 126 scanf("%d\n", i); 127 throw new Exception("ssl send"); 128 } 129 return retval; 130 } 131 override ptrdiff_t receive(void[] buf) { 132 return receive(buf, SocketFlags.NONE); 133 } 134 135 this(AddressFamily af, SocketType type = SocketType.STREAM, bool verifyPeer = true) { 136 super(af, type); 137 initSsl(verifyPeer); 138 } 139 140 this(socket_t sock, AddressFamily af) { 141 super(sock, af); 142 initSsl(true); 143 } 144 145 ~this() { 146 SSL_free(ssl); 147 SSL_CTX_free(ctx); 148 } 149 } 150 } 151 152 version(ssl_test) 153 void main() { 154 auto sock = new SslClientSocket(AddressFamily.INET); 155 sock.connect(new InternetAddress("localhost", 443)); 156 sock.send("GET / HTTP/1.0\r\n\r\n"); 157 import std.stdio; 158 char[1024] buffer; 159 writeln(buffer[0 .. sock.receive(buffer)]); 160 }