diff --git a/lib/modules/SSL.pmod/asn1.pmod.pike b/lib/modules/SSL.pmod/asn1.pmod.pike index 9e590d5e7f8d2d1410c1bf508076f703f4366c95..28f0af9ff475d80d2cc3211c8af4f49a957b2fd1 100644 --- a/lib/modules/SSL.pmod/asn1.pmod.pike +++ b/lib/modules/SSL.pmod/asn1.pmod.pike @@ -2,7 +2,7 @@ * * Rudimentary support for decoding ASN.1 encoded data. * - * $Id: asn1.pmod.pike,v 1.1 1997/03/15 04:46:01 nisse Exp $ + * $Id: asn1.pmod.pike,v 1.2 1997/03/15 07:10:53 nisse Exp $ */ /* BER decoder @@ -72,7 +72,7 @@ class ber_decode { case 6: /* Object id */ { tag = "Identifier"; - if (value[0] <= 2) + if (contents[0] < 120) value = ({ contents[0] / 40, contents[0] % 40 }); else value = ({ 2, contents[0] - 80 }); diff --git a/lib/modules/SSL.pmod/https.pike b/lib/modules/SSL.pmod/https.pike index 38379b83cd043c13c3d28a26a0ba5dd0bde0250d..0a5939bd7515e262b8e3719f01be9dbb6a3e7634 100644 --- a/lib/modules/SSL.pmod/https.pike +++ b/lib/modules/SSL.pmod/https.pike @@ -158,8 +158,8 @@ int main() { werror(sprintf("Cert: '%s'\n", Crypto.string_to_hex(my_certificate))); werror(sprintf("Key: '%s'\n", Crypto.string_to_hex(my_key))); -// werror(sprintf("Decoded cert: %O\n", ber_decode(my_certificate)->get_asn1())); - array key = asn1.ber_decode(my_key)->get_asn1()[1]; +// werror(sprintf("Decoded cert: %O\n", SSL.asn1.ber_decode(my_certificate)->get_asn1())); + array key = SSL.asn1.ber_decode(my_key)->get_asn1()[1]; werror(sprintf("Decoded key: %O\n", key)); object n = key[1][1]; object e = key[2][1]; @@ -183,3 +183,9 @@ int main() else return -17; } + +void create() +{ + werror("https->create\n"); + sslport::create(); +} diff --git a/lib/modules/SSL.pmod/sslfile.pike b/lib/modules/SSL.pmod/sslfile.pike new file mode 100644 index 0000000000000000000000000000000000000000..a153cab49724680f021e8e3a38ec028de1568d7e --- /dev/null +++ b/lib/modules/SSL.pmod/sslfile.pike @@ -0,0 +1,195 @@ +/* sslfile.pike + * + */ + +inherit Stdio.File : socket; +inherit "connection" : connection; + +object context; + +string read_buffer; /* Data that is recieved before there is any + * read_callback */ +string write_buffer; /* Data to be written */ +function(mixed,string:void) read_callback; +function(mixed:void) write_callback; +function(mixed:void) close_callback; +function(mixed:void) accept_callback; + +int connected; /* 1 if the connect callback has been called */ + +private void die(int status) +{ + if (status < 0) + { + /* Other end closed without sending a close_notify alert */ + context->purge_session(this_object()); + werror("SSL.sslfile: Killed\n"); + } + if (close_callback) + close_callback(socket::query_id()); +} + +/* Return 0 if the connection is still alive, + * 1 if it was closed politely, and -1 if it died unexpectedly + */ +private int try_write() +{ + int|string data = to_write(); +// werror(sprintf("sslport->try_write: %O\n", data)); + if (stringp(data)) + { + write_buffer += data; + if (strlen(write_buffer)) + { + int written = socket::write(write_buffer); + if (written > 0) + write_buffer = write_buffer[written..]; + else + werror("SSL.sslfile->try_write: write failed\n"); + } + return 0; + } + socket::close(); + return data; +} + +void close() +{ + send_packet(Alert(ALERT_warning, ALERT_close_notify)); + try_write(); + read_callback = 0; + write_callback = 0; + close_callback = 0; +} + +int write(string s) +{ + object packet; + int res; + while(strlen(s)) + { + packet = Packet(); + packet->content_type = PACKET_application_data; + packet->fragment = s[..PACKET_MAX_SIZE-1]; + send_packet(packet); + s = s[PACKET_MAX_SIZE..]; + } + (res = try_write()) && die(res); +} + +string read(mixed ...args) +{ + throw( ({ "SSL->sslfile: read() is not supported.\n", backtrace() }) ); +} + +private void ssl_read_callback(mixed id, string s) +{ + werror(sprintf("SSL.sslfile->ssl_read_callback\n")); + string|int data = got_data(s); + if (stringp(data)) + { + werror(sprintf("SSL.sslfile: application_data: '%s'\n", data)); + if (strlen(data)) + { + read_buffer += data; + if (!connected) + { + connected = 1; + if (accept_callback) + accept_callback(this_object()); + } + if (read_callback && strlen(read_buffer)) + { + read_callback(id, read_buffer + data); + read_buffer = ""; + } + } + } + else + { + if (data < 0) + /* Fatal error, remove from session cache */ + context->purge_session(this_object()); + } + try_write() || (close_callback && close_callback()); +} + +private void ssl_write_callback(mixed id) +{ + werror("SSL.sslport: ssl_write_callback\n"); + int res; + if ( !(res = try_write()) && !strlen(write_buffer) + && handshake_finished && write_callback) + { + write_callback(id); + res = try_write(); + } + if (res) + die(res); +} + +private void ssl_close_callback(mixed id) +{ + werror("SSL.sslport: ssl_close_callback\n"); + socket::close(); + die(-1); +} + +void set_accept_callback(function(mixed:void) w) +{ + accept_callback = w; +} + +void set_read_callback(function(mixed,string:void) r) +{ + read_callback = r; +} + +void set_write_callback(function(mixed:void) w) +{ + write_callback = w; +} + +void set_close_callback(function(mixed:void) c) +{ + close_callback = c; +} + +void set_nonblocking(function ...args) +{ + switch (sizeof(args)) + { + case 0: + break; + case 3: + set_read_callback(args[0]); + set_write_callback(args[1]); + set_close_callback(args[2]); + break; + default: + throw( ({ "SSL.sslfile->set_blocking: Wrong number of arguments\n", + backtrace() }) ); + } +} + +void set_blocking() +{ + throw( ({ "SSL.sslfile->set_blocking: Not supported\n", + backtrace() }) ); +} + +object accept() +{ + /* Dummy method, for compatibility with Stdio.Port */ + return this_object(); +} + +void create(object f, object c) +{ + context = c; + read_buffer = write_buffer = ""; + socket::assign(f); + socket::set_nonblocking(ssl_read_callback, ssl_write_callback, ssl_close_callback); + connection::create(1); +} +