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