diff --git a/.gitattributes b/.gitattributes
index 10783a7144fcc537bde39a9f73c20f7e4a62ffe9..74299ea3efcd7a0e9302009af4004a2b511cafb0 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -17,6 +17,7 @@ testfont binary
 /lib/modules/LR.pmod/priority.pike foreign_ident
 /lib/modules/LR.pmod/rule.pike foreign_ident
 /lib/modules/LR.pmod/scanner.pike foreign_ident
+/lib/modules/SSL.pmod/asn1.pmod.pike foreign_ident
 /lib/modules/Sql.pmod/mysql.pike foreign_ident
 /lib/modules/Sql.pmod/mysql_result.pike foreign_ident
 /lib/modules/Sql.pmod/sql.pike foreign_ident
diff --git a/lib/modules/SSL.pmod/asn1.pmod.pike b/lib/modules/SSL.pmod/asn1.pmod.pike
new file mode 100644
index 0000000000000000000000000000000000000000..9e590d5e7f8d2d1410c1bf508076f703f4366c95
--- /dev/null
+++ b/lib/modules/SSL.pmod/asn1.pmod.pike
@@ -0,0 +1,110 @@
+/* asn1.pmod.pike
+ *
+ * Rudimentary support for decoding ASN.1 encoded data.
+ *
+ * $Id: asn1.pmod.pike,v 1.1 1997/03/15 04:46:01 nisse Exp $
+ */
+
+/* BER decoder
+ *
+ * Values are represented as arrays ({ tag, value }).
+ * Tag is either an integer tag number, or a string, in case
+ * the tag recognized.
+ *
+ * Values are strings, integers, or arrays */
+
+class ber_decode {
+  inherit ADT.struct;
+
+  array get_asn1()
+  {
+    int|string tag = get_int(1);
+    int len;
+    string contents;
+    mixed value;
+    
+    werror(sprintf("decoding tag %x\n", tag));
+    if ( (tag & 0x1f) == 0x1f)
+      throw( ({ "high tag numbers is not supported\n", backtrace() }) );
+    int len = get_int(1);
+    if (len & 0x80)
+      len = get_int(len & 0x7f);
+    
+    werror(sprintf("len : %d\n", len));
+
+    contents = get_fix_string(len);
+    werror(sprintf("contents: %O\n", contents));
+    if (tag & 0x20)
+    {
+      object seq = object_program(this_object())(contents);
+      value = ({ });
+      while(! seq->is_empty())
+      {
+	array elem = seq->get_asn1();
+	// werror(sprintf("elem: %O\n", elem));
+	value += ({ elem });
+      }
+    }
+    switch(tag & 0xdf)
+    {
+    case 1: /* Boolean */
+      if (strlen(contents) != 1)
+	throw( ({ "SSL.asn1: Invalid boolean value.\n", backtrace() }) );
+      tag = "BOOLEAN";
+      value = !!contents[0];
+      break;
+    case 2: /* Integer */
+      tag = "INTEGER";
+      value = Gmp.mpz(contents, 256);
+      if (contents[0] & 0x80)  /* Negative */
+	value -= Gmp.pow(256, strlen(contents));
+      break;
+    case 3: /* Bit string */
+      tag = "BIT STRING";
+      break;
+    case 4: /* Octet string */
+      tag = "OCTET STRING";
+      break;
+    case 5: /* Null */
+      if (strlen(contents))
+	throw( ({ "SSL.asn1: Invalid NULL value.\n", backtrace() }) );
+      break;
+    case 6: /* Object id */
+    {
+      tag = "Identifier";
+      if (value[0] <= 2)
+	value = ({ contents[0] / 40, contents[0] % 40 });
+      else
+	value = ({ 2, contents[0] - 80 });
+      int index = 1;
+      while(index < strlen(contents))
+      {
+	int id = 0;
+	do
+	{
+	  id = id << 7 | (contents[index] & 0x7f);
+	} while(contents[index++] & 0x80);
+	value += ({ id });
+      }
+      break;
+    }
+    case 9: /* Real */
+      tag = "REAL";
+      break;
+    case 10: /* Enumerated */
+      tag = "ENUMERATED";
+      break;
+    case 16: /* Sequence */
+      tag = "SEQUENCE";
+      break;
+    case 17: /* Set */
+      tag = "SET";
+      break;
+    default: /* Keep numeric tag */
+      break;
+    }
+      
+    return ({ tag, value });
+  }
+}
+
diff --git a/lib/modules/SSL.pmod/cipher.pike b/lib/modules/SSL.pmod/cipher.pike
index 3e90eacf6140240e0db4701b5af8277ce0d962a3..c1fb2eda6ea039a8dcd7e3ab32129e5314358380 100644
--- a/lib/modules/SSL.pmod/cipher.pike
+++ b/lib/modules/SSL.pmod/cipher.pike
@@ -14,12 +14,14 @@ class CipherSpec {
   int iv_size;
 }
 
+#if 0
 class mac_none
 {
   /* Dummy MAC algorithm */
 //  string hash_raw(string data) { return ""; }
   string hash(string data, object seq_num) { return ""; }
 }
+#endif
 
 class mac_sha
 {
@@ -72,6 +74,7 @@ class mac_md5 {
   program algorithm = Crypto.md5;
 }
 
+#if 0
 class crypt_none
 {
   /* Dummy stream cipher */
@@ -79,6 +82,7 @@ class crypt_none
   object set_decrypt_key(string k) { return this_object(); }  
   string crypt(string s) { return s; }
 }
+#endif
 
 class des
 {
@@ -143,7 +147,7 @@ array lookup(int suite)
     res->bulk_cipher_algorithm = Crypto.rc4;
     res->cipher_type = CIPHER_stream;
     res->is_exportable = 1;
-    res->key_material = 5;
+    res->key_material = 16;
     res->iv_size = 0;
     break;
   case CIPHER_des:
@@ -168,7 +172,7 @@ array lookup(int suite)
     res->iv_size = 8;
     break;
   case CIPHER_null:
-    res->bulk_cipher_algorithm = crypt_none;
+    res->bulk_cipher_algorithm = 0;
     res->cipher_type = CIPHER_stream;
     res->is_exportable = 1;
     res->key_material = 0;
@@ -189,7 +193,7 @@ array lookup(int suite)
     res->hash_size = 16;
     break;
   case 0:
-    res->mac_algorithm = mac_none;
+    res->mac_algorithm = 0;
     res->hash_size = 0;
     break;
   default:
diff --git a/lib/modules/SSL.pmod/connection.pike b/lib/modules/SSL.pmod/connection.pike
index d3e95429b1eb99ad7b354800f813a142bd0e2499..d5ccf40ff39349392ed2142661a4f62cbc90a3a7 100644
--- a/lib/modules/SSL.pmod/connection.pike
+++ b/lib/modules/SSL.pmod/connection.pike
@@ -15,7 +15,7 @@ int closing;
 inherit "constants";
 inherit "handshake";
 
-constant Queue = (program) "queue";
+constant Queue = ADT.queue;
 constant State = (program) "state";
 
 inherit Queue : alert;
@@ -182,7 +182,7 @@ string|int got_data(string s)
 
     if (packet->is_alert)
     { /* Reply alert */
-      werror("Bad recieved packet\n");
+      werror("SSL.connection: Bad recieved packet\n");
       send_packet(packet);
       if (packet->level == ALERT_fatal)
 	return -1;
diff --git a/lib/modules/SSL.pmod/context.pike b/lib/modules/SSL.pmod/context.pike
index b5b3ad9fa9bf3de38e5675a451d234ea9d9a0614..e08b6352a9bf4163eda7b23c2a587c33f80d0521 100644
--- a/lib/modules/SSL.pmod/context.pike
+++ b/lib/modules/SSL.pmod/context.pike
@@ -28,7 +28,7 @@ array(int) preferred_suites =
    SSL_rsa_with_rc4_128_md5,
    SSL_rsa_with_3des_ede_cbc_sha,
    SSL_rsa_with_des_cbc_sha,
-//   SSL_rsa_export_with_rc4_40_md5,
+   SSL_rsa_export_with_rc4_40_md5,
    SSL_rsa_with_null_sha,
    SSL_rsa_with_null_md5
 });
@@ -37,7 +37,7 @@ array(int) preferred_compressors =
 ({ COMPRESSION_null });
 
 constant Session = (program) "session";
-constant Queue = (program) "queue";
+constant Queue = ADT.queue;
 
 int use_cache = 1;
 int session_lifetime = 600; /* Time to remember a session, in seconds */
diff --git a/lib/modules/SSL.pmod/handshake.pike b/lib/modules/SSL.pmod/handshake.pike
index e8776e424515c66c7c66aedc0d0d304f273bf325..b7c99ea5178c27f8b328df9605019e8858932d82 100644
--- a/lib/modules/SSL.pmod/handshake.pike
+++ b/lib/modules/SSL.pmod/handshake.pike
@@ -37,7 +37,7 @@ int reuse;
 string my_random;
 string other_random;
 
-constant Struct = (program) "struct";
+constant Struct = ADT.struct;
 constant Session = (program) "session";
 constant Packet = (program) "packet";
 constant Alert = (program) "alert";
@@ -76,16 +76,22 @@ int reply_new_session(array(int) cipher_suites, array(int) compression_methods)
 {
   reuse = 0;
   session = context->new_session();
-
-//  werror(sprintf("ciphers: me: %O, client: %O\n",
-//		   context->preferred_suites, cipher_suites)); 
+  multiset(int) common_suites;
+  
+  werror(sprintf("ciphers: me: %O, client: %O\n",
+		   context->preferred_suites, cipher_suites)); 
 //  werror(sprintf("compr: me: %O, client: %O\n",
 //		   context->preferred_compressors, compression_methods)); 
-  cipher_suites &= context->preferred_suites;
-  if (sizeof(cipher_suites))
-    session->set_cipher_suite(cipher_suites[0]);
-  else
+  
+  common_suites = mkmultiset(cipher_suites & context->preferred_suites);
+  werror(sprintf("intersection: %O\n", common_suites));
+  if (sizeof(common_suites))
   {
+    int suite;
+    foreach(context->preferred_suites, suite)
+      if (common_suites[suite]) break;
+    session->set_cipher_suite(suite);
+  } else {
     send_packet(Alert(ALERT_fatal, ALERT_handshake_failure));
     return -1;
   }
@@ -245,11 +251,11 @@ int handle_handshake(int type, string data, string raw)
 			 "Version %d.%d hello detected\n", @version));
 
 	if (strlen(id))
-	  werror(sprintf("Looking up session %s\n", id));
+	  werror(sprintf("SSL.handshake: Looking up session %s\n", id));
 	session = strlen(id) && context->lookup_session(id);
 	if (session)
 	{
-	  werror(sprintf("Reusing session %s\n", id));
+	  werror(sprintf("SSL.handshake: Reusing session %s\n", id));
 	  /* Reuse session */
 	  reuse = 1;
 	  if (! ( (cipher_suites & ({ session->cipher_suite }))
diff --git a/lib/modules/SSL.pmod/https.pike b/lib/modules/SSL.pmod/https.pike
index 1b73024001011eca298a70e129e2b29fe2681dc4..38379b83cd043c13c3d28a26a0ba5dd0bde0250d 100644
--- a/lib/modules/SSL.pmod/https.pike
+++ b/lib/modules/SSL.pmod/https.pike
@@ -90,10 +90,11 @@ class no_random {
   }
 }
 
+#if 0
 /* ad-hoc asn.1-decoder */
 
 class ber_decode {
-  inherit "struct";
+  inherit ADT.struct;
 
   array get_asn1()
   {
@@ -128,6 +129,7 @@ class ber_decode {
       return ({ tag, contents });
   }
 }
+#endif
 
 /* PKCS#1 Private key structure:
 
@@ -157,13 +159,13 @@ 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 = ber_decode(my_key)->get_asn1()[1];
+  array key = asn1.ber_decode(my_key)->get_asn1()[1];
   werror(sprintf("Decoded key: %O\n", key));
-  object n = Gmp.mpz(key[1][1], 256);
-  object e = Gmp.mpz(key[2][1], 256);
-  object d = Gmp.mpz(key[3][1], 256);
-  object p = Gmp.mpz(key[4][1], 256);
-  object q = Gmp.mpz(key[5][1], 256);
+  object n = key[1][1];
+  object e = key[2][1];
+  object d = key[3][1];
+  object p = key[4][1];
+  object q = key[5][1];
 
   werror(sprintf("n =  %s\np =  %s\nq =  %s\npq = %s\n",
 		 n->digits(), p->digits(), q->digits(), (p*q)->digits()));
@@ -173,5 +175,11 @@ int main()
   certificates = ({ my_certificate });
   random = no_random()->read;
   werror("Starting\n");
-  return bind(PORT, my_accept_callback) ? -17 : 17;
+  if (!bind(PORT, my_accept_callback))
+  {
+    perror("");
+    return 17;
+  }
+  else
+    return -17;
 }
diff --git a/lib/modules/SSL.pmod/sslport.pike b/lib/modules/SSL.pmod/sslport.pike
index 47cc3303c8714201243e9d94bc0e30cdfe9ae560..18e8b25031d371d185f7baf61d2be1c32c42068f 100644
--- a/lib/modules/SSL.pmod/sslport.pike
+++ b/lib/modules/SSL.pmod/sslport.pike
@@ -90,11 +90,11 @@ class sslfile
   
   private void ssl_read_callback(mixed id, string s)
   {
-    werror(sprintf("sslfile->ssl_read_callback\n"));
+    werror(sprintf("SSL.sslfile->ssl_read_callback\n"));
     string|int data = got_data(s);
     if (stringp(data))
     {
-      werror(sprintf("sslfile: application_data: '%s'\n", data));
+      werror(sprintf("SSL.sslfile: application_data: '%s'\n", data));
       if (strlen(data))
       {
 	read_buffer += data;
diff --git a/lib/modules/SSL.pmod/state.pike b/lib/modules/SSL.pmod/state.pike
index 13e19c194a3b0b3be2172a3a5f198ba0a793b59c..895445ef441c6c504261a34b9c52b2591182c22f 100644
--- a/lib/modules/SSL.pmod/state.pike
+++ b/lib/modules/SSL.pmod/state.pike
@@ -27,10 +27,12 @@ void create(object s)
  * there was an error, otherwise 0. */
 object decrypt_packet(object packet)
 {
+  werror(sprintf("SSL.state->decrypt_packet: data = '%s'\n", packet->fragment));
+  
   if (crypt)
   {
     string msg;
-//    werror("Trying decrypt..\n");
+    werror("SSL.state: Trying decrypt..\n");
     msg = crypt->crypt(packet->fragment); 
     if (! msg)
       return Alert(ALERT_fatal, ALERT_unexpected_message);
@@ -40,11 +42,11 @@ object decrypt_packet(object packet)
     packet->fragment = msg;
   }
 
-//  werror(sprintf("Decrypted_packet '%s'\n", packet->fragment));
+  werror(sprintf("SSL.state: Decrypted_packet '%s'\n", packet->fragment));
 
   if (mac)
   {
-//    werror("Trying mac verification...\n");
+    werror("SSL.state: Trying mac verification...\n");
     int length = strlen(packet->fragment) - session->cipher_spec->hash_size;
     string digest = packet->fragment[length ..];
     packet->fragment = packet->fragment[.. length - 1];
@@ -56,7 +58,7 @@ object decrypt_packet(object packet)
 
   if (compress)
   {
-//    werror("Trying decompression...\n");
+    werror("SSL.state: Trying decompression...\n");
     string msg;
     msg = compress(packet->fragment);
     if (!msg)