diff -uNr lyskom-server-2.1.2.orig/configure.in lyskom-server-2.1.2/configure.in
--- lyskom-server-2.1.2.orig/configure.in	2003-08-29 13:20:22.000000000 +0200
+++ lyskom-server-2.1.2/configure.in	2005-03-08 12:52:46.000000000 +0100
@@ -67,6 +67,11 @@
         [use_inet6=yes],
         [use_inet6=no])
 
+AC_ARG_ENABLE([tls],
+        AC_HELP_STRING([--disable-tls], [disable TLS support]),
+        [use_tls=$enableval],
+        [use_tls=yes])
+
 AC_ARG_WITH([gcov],
         AC_HELP_STRING([--with-gcov], [instrument for gcov (requires gcc)]),
         [use_gcov=$withval],
@@ -206,6 +211,14 @@
     fi
 fi]
 
+[if test "$use_tls" = "yes"; then ]
+  dnl Unless we disable TLS, we need to link with gnutls.
+  AC_SEARCH_LIBS(gnutls_init, gnutls, , [
+		    LDFLAGS="$LDFLAGS `gnutlsconfig --libs`"
+		    AC_SEARCH_LIBS(gnutls_init, gnutls)
+		    ])
+[fi]
+
 # Do this test early since it may define _POSIX_SOURCE, which may
 # affect future tests.
 # FIXME (bug 210): is this needed, now that we use AM_C_PROTOTYPES?
diff -uNr lyskom-server-2.1.2.orig/doc/lyskomd.texi lyskom-server-2.1.2/doc/lyskomd.texi
--- lyskom-server-2.1.2.orig/doc/lyskomd.texi	2003-08-29 12:39:58.000000000 +0200
+++ lyskom-server-2.1.2/doc/lyskomd.texi	2005-03-07 11:07:18.000000000 +0100
@@ -711,6 +711,64 @@
 @item Log login: @var{bool}
 Should logins be logged to the log file?  Default value is off.
 
+@item TLS cert file: @var{path}
+Points to the certificate file (in PEM format) for use with TLS.
+Default is @file{cert.pem}
+
+@item TLS key file: @var{path}
+Points to the key file (in PEM format) for use with TLS.
+Default is @file{key.pem}
+
+@item TLS CA file: @var{path}
+Points to the CA file (in PEM format) for use with TLS. This should
+only be neccessary if you want to perform client certificate
+authentication (@pxref{TLS require client certificate,TLS require client certificate}).
+
+Default is @file{ca.pem}
+
+@item TLS CRL file: @var{path}
+Points to the CRL file (in PEM format) for use with TLS. This should
+only be neccessary if you want to perform client certificate
+authentication  (@pxref{TLS require client certificate,TLS require client certificate}).
+
+Default is @file{crl.pem}
+
+
+@anchor{TLS require client certificate}@item TLS require client certificate: @var{bool}
+If this is set, TLS will only be available for clients with trusted
+X509 certificate (this only affects TLS, normal, unsecure operations
+are still available to these clients).
+
+Default is off.
+
+
+@item TLS operation timeout: @var{timeval}
+This setting controls how long the server will wait for TLS
+negotiation (and termination) to finish before cancelling the
+operation. As the server can not handle requests from other users
+during this period, there is a potential DDOS issue here.
+
+Default is 4 seconds.
+
+
+@item TLS DH bits: @var{int}
+
+This setting controls the bits value that is used to generate primes
+for the Diffie-Hellman key exchange. It should be set to
+768, 1024, 2048, 3072 or 4096.
+
+Default is 1024 seconds.
+
+
+@item TLS DH regeneration frequency: @var{int}
+
+This setting controls how many times the parameters for the DH key
+exchange may be reused before being discarded.
+
+Default is 1024 times.
+
+
+
 @item Cache conference limit: @var{int}
 How many conference statuses the server cache should hold in main
 memory. Default is 20. This parameter should be set to at least the
diff -uNr lyskom-server-2.1.2.orig/doc/Protocol-A.texi lyskom-server-2.1.2/doc/Protocol-A.texi
--- lyskom-server-2.1.2.orig/doc/Protocol-A.texi	2003-08-29 14:40:05.000000000 +0200
+++ lyskom-server-2.1.2/doc/Protocol-A.texi	2005-03-07 09:22:40.000000000 +0100
@@ -3154,6 +3154,8 @@
 * set-connection-time-format::  r Use UTC or local timezone of server?    (120)
 * local-to-global-reverse::     r Map local text numbers to global ones   (121)
 * map-created-texts-reverse::   r Map texts created by a person to global (122)
+* tls-supported::               e Query server TLS support		  (123)
+* start-tls::                   e Start TLS negotiation                   (124)
 @end menu
 
 @ifnottex
@@ -8887,6 +8889,67 @@
 
 
 
+@node tls-supported
+@section tls-supported [123] (11) Experimental
+
+@findex tls-supported
+@example
+        1 123 
+        = 1
+@end example
+
+Queries whatever the server is willing to support TLS and returns
+successfully if the server is willing.
+
+@subheading Error codes
+
+
+@table @errorcode
+
+@item not-implemented
+Servers unwilling to engage in TLS negotiation may return
+not-implemented.
+
+@end table
+
+
+
+
+
+@node start-tls
+@section start-tls [124] (11) Experimental
+
+@findex start-tls
+@example
+        1 123 
+        = 1
+	1 124
+	<CLIENT INITIATES TLS NEGOTIATION>
+	= 1
+@end example
+
+Tells server to invoke TLS negotiation. Clients should only do this
+after querying if the server is willing to engage in TLS negotiation
+using @ref{tls-supported}.
+
+After sending the command sequence, the client should invoke TLS
+negotiation immediately.
+
+@subheading Error codes
+
+@table @errorcode
+
+@item not-implemented
+Servers unwilling to engage in TLS negotiation may return
+not-implemented.
+
+@end table
+
+
+
+
+
+
 @node Asynchronous Messages
 @chapter Asynchronous Messages
 
diff -uNr lyskom-server-2.1.2.orig/src/include/kom-errno.h lyskom-server-2.1.2/src/include/kom-errno.h
--- lyskom-server-2.1.2.orig/src/include/kom-errno.h	2003-08-23 18:54:39.000000000 +0200
+++ lyskom-server-2.1.2/src/include/kom-errno.h	2005-03-16 08:05:49.000000000 +0100
@@ -99,6 +99,7 @@
     KOM_WEIGHT_DENIED = 59,	/* You cannot increase your weight that much.*/
     KOM_WEIGHT_ZERO = 60,	/* You cannot increase your weight that much.*/
     KOM_BAD_BOOL = 61,          /* A Bool must be 0 or 1. */
+    KOM_TLS_DISABLED = 62,      /* TLS is disabled at this server. */
     KOM_num_errs		/* End marker */
 };
 
diff -uNr lyskom-server-2.1.2.orig/src/include/services.h lyskom-server-2.1.2/src/include/services.h
--- lyskom-server-2.1.2.orig/src/include/services.h	2003-08-25 19:51:10.000000000 +0200
+++ lyskom-server-2.1.2/src/include/services.h	2005-03-16 07:45:39.000000000 +0100
@@ -54,6 +54,9 @@
 extern  Success
 logout (void);	/* can never fail */
 
+extern Success
+start_tls(const String server_name);
+
 /* Change Conference */
 extern  Success
 change_conference (Conf_no conference);
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/ChangeLog lyskom-server-2.1.2/src/libraries/libisc-new/ChangeLog
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/ChangeLog	2003-08-25 19:51:15.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/ChangeLog	2005-03-04 11:50:36.000000000 +0100
@@ -1,3 +1,8 @@
+2005-03-04  Pontus Freyhult  <pont@soua.net>
+
+	* src/isc.h: Added declarations for isc_tls_support and
+	isc_sasl_support.
+
 2003-08-25  Per Cederqvist  <ceder@ceder.dyndns.org>
 
 	Don't crash if a write error occurs.
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/configure.in lyskom-server-2.1.2/src/libraries/libisc-new/configure.in
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/configure.in	2003-08-01 01:04:51.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/configure.in	2005-03-09 09:57:29.000000000 +0100
@@ -47,6 +47,11 @@
         [use_inet6=yes],
         [use_inet6=no])
 
+AC_ARG_ENABLE([tls],
+        AC_HELP_STRING([--disable-tls], [disable TLS support]),
+        [use_tls=$enableval],
+        [use_tls=yes])
+
 AC_ARG_ENABLE([malloc-guards],
 	AC_HELP_STRING([--disable-malloc-guards], 
 	               [disable defensive guard areas (may crash lyskomd)]),
@@ -227,6 +232,34 @@
 		      [#include <sys/socket.h>])
 
 
+dnl Check for TLS library
+
+[if test "$use_tls" = "yes"; then]
+  AC_CHECK_HEADER(gnutls/gnutls.h, [havetlsh=yes; 
+                                  AC_DEFINE(HAVE_GNUTLS_H, 
+                                            1, 
+                                            [Define if you have gnutls/gnutls.h])], 
+                                 [
+			          CFLAGS="$CFLAGS `gnutlsconfig --cflags`"
+			          AC_CHECK_HEADER(gnutls/gnutls.h,
+                                            [havetlsh=yes
+					     AC_DEFINE(HAVE_GNUTLS_H,1)])
+			    ])
+
+  [if test "x$havetlsh" = "xyes" ; then]
+
+    AC_EGREP_HEADER(gnutls_certificate_credentials_t, gnutls/gnutls.h,
+        [AC_DEFINE(TLSTS,[_t],[Suffix for TLS functions.])])
+
+    AC_SEARCH_LIBS(gnutls_init, gnutls, AC_DEFINE(HAVE_GNUTLS, 1, [Define if you have GNU TLS]), [
+			    LDFLAGS="$LDFLAGS `gnutlsconfig --libs`"
+			    AC_SEARCH_LIBS(gnutls_init, gnutls, 
+					   AC_DEFINE(HAVE_GNUTLS,1))
+			    ])
+
+  [fi]
+[fi]
+
 [if test "$use_gcov" = "yes" -a -n "$GCC"; then]
         CMOD_CHECK_CC_OPT([-ftest-coverage], [test_coverage])
         CMOD_CHECK_CC_OPT([-fprofile-arcs], [profile_arcs])
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/intern.h lyskom-server-2.1.2/src/libraries/libisc-new/src/intern.h
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/intern.h	2003-08-07 23:07:01.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/intern.h	2005-03-16 07:53:03.000000000 +0100
@@ -27,6 +27,18 @@
 #ifndef __ISC_INTERNALS_H__
 #define __ISC_INTERNALS_H__
 
+
+#ifndef TLSTS
+#ifdef HAVE_GNUTLS
+/* Compatibility defintions for old gnutls*/
+typedef gnutls_session gnutls_session_t;
+typedef gnutls_anon_server_credentials gnutls_anon_server_credentials_t;
+typedef gnutls_dh_params gnutls_dh_params_t;
+typedef gnutls_certificate_credentials gnutls_certificate_credentials_t;
+typedef gnutls_transport_ptr gnutls_transport_ptr_t;
+#endif
+#endif
+
 /*
 ** Some nice defaults
 */
@@ -46,8 +58,20 @@
   oop_source              * event_source;
   oop_adapter_adns        * adns;
   isc_write_queue_change_cb *write_change_cb;
+
+#ifdef HAVE_GNUTLS
+  gnutls_dh_params dh_params;
+  int dh_params_use_count;
+  gnutls_anon_server_credentials anoncred;
+  gnutls_certificate_credentials x509_cred;
+  int scb_count;
+#endif
+
 };
 
+typedef size_t isc_read_func(struct isc_scb* scb, void* buf, size_t count);
+typedef size_t isc_write_func(struct isc_scb* scb, void* buf, size_t count);
+
 
 /*
 ** The Client Control Block
@@ -86,6 +110,15 @@
 
   isc_resolve_done_cb  *resolve_callback; /* Non-NULL when lookup pending. */
   oop_adns_query       *adns_query;
+
+  isc_read_func        *read_func;
+  isc_write_func       *write_func;
+#ifdef HAVE_GNUTLS
+  gnutls_session       tls_session;
+  int                  tls_active;
+  time_t               tls_handshake_begin;
+#endif
+
 };
 
 /*
@@ -348,4 +381,15 @@
 
 #endif /* USE_INET6 */
 
+
+extern void
+isc_tls_initialize(struct isc_mcb* mcb);
+
+
+extern void
+isc_tls_destroy(struct isc_scb_internal* sci);
+
+extern void
+isc_tls_deinitialize(struct isc_mcb* mcb);
+
 #endif
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_abort.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_abort.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_abort.c	2003-08-06 09:06:18.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_abort.c	2005-03-04 17:22:23.000000000 +0100
@@ -38,6 +38,11 @@
 #include <sys/socket.h>
 #include <time.h>
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_alloc.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_alloc.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_alloc.c	2003-08-06 09:06:18.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_alloc.c	2005-03-04 17:22:50.000000000 +0100
@@ -53,6 +53,10 @@
 #  endif
 #endif
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_compat.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_compat.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_compat.c	2003-08-06 09:06:18.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_compat.c	2005-03-04 17:33:18.000000000 +0100
@@ -25,6 +25,11 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_event.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_event.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_event.c	2003-08-25 19:51:16.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_event.c	2005-03-05 18:08:17.000000000 +0100
@@ -63,6 +63,10 @@
 #  include <strings.h>  /* Needed on AIX 4.2 due to bzero */
 #endif
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
@@ -108,6 +112,9 @@
 	return ISC_READ_NOMEM;
 
     do {
+      if(scb->read_func)
+	status = scb->read_func((struct isc_scb*) scb, buf, scb->pub.master->scfg->max.msgsize);
+      else
 	status = read(scb->pub.fd, buf, scb->pub.master->scfg->max.msgsize);
     } while (status < 0 && errno == EINTR);
     
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc.h lyskom-server-2.1.2/src/libraries/libisc-new/src/isc.h
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc.h	2003-08-06 09:01:09.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc.h	2005-03-07 11:04:11.000000000 +0100
@@ -55,6 +55,9 @@
 
 typedef void isc_write_queue_change_cb(int delta_bytes);
 
+    
+
+
 enum isc_resolve_status
 {
     isc_resolve_ok,		/* Name successfully looked up. */
@@ -298,4 +301,22 @@
 extern oop_source *
 isc_getoopsource(struct isc_scb *scb);
 
+
+extern int isc_sasl_support(void);
+
+/* TLS support functions */
+
+extern int isc_tls_support(void);
+extern int isc_tls_negotiate(struct isc_scb *scb);
+
+extern void 
+isc_tls_set_params( int dh_bits_param,
+		    int cert_req_param,
+		    double handshake_timeout_param,
+		    int dh_regenerate_every_param,
+		    char* certfile_param,
+		    char* cafile_param,
+		    char* keyfile_param, 
+		    char* crlfile_param);
+
 #endif /* __ISC_H__ */
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_master.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_master.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_master.c	2003-08-06 09:01:09.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_master.c	2005-03-07 08:37:43.000000000 +0100
@@ -42,6 +42,10 @@
 #  include <stdio.h>
 #endif
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
@@ -94,6 +98,8 @@
   mcb->event_source = event_source;
   mcb->write_change_cb = write_change_cb;
 
+  isc_tls_initialize(mcb);
+
   return mcb;
 }
 
@@ -139,7 +145,9 @@
   while (mcb->sessions)
     isc_destroy(mcb, &mcb->sessions->scb->pub);
 
+  isc_tls_deinitialize(mcb);
   oop_adns_delete(mcb->adns);
   isc_free(mcb->scfg);
   isc_free(mcb);
 }
+
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_message.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_message.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_message.c	2003-08-06 09:06:18.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_message.c	2005-03-04 17:32:14.000000000 +0100
@@ -41,6 +41,10 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_output.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_output.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_output.c	2003-08-25 19:51:16.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_output.c	2005-03-05 18:02:55.000000000 +0100
@@ -45,6 +45,10 @@
 #include <time.h>
 #include <assert.h>
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
@@ -137,6 +141,9 @@
   while ((msg = isc_topqueue(scb->wr_msg_q)) != NULL &&
 	 !failed && loopcnt < scb->cfg->max.dequeuelen)
   {
+    if (scb->write_func)
+      wlen = scb->write_func((struct isc_scb*) scb, msg->buffer, msg->length);
+      else
     wlen = write(scb->pub.fd, msg->buffer, msg->length);
 
     if (wlen < 0)
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_queue.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_queue.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_queue.c	2003-08-06 09:06:18.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_queue.c	2005-03-04 17:32:02.000000000 +0100
@@ -38,6 +38,11 @@
 #include <sys/socket.h>
 #include <assert.h>
 
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_relocate.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_relocate.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_relocate.c	2003-08-06 09:06:18.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_relocate.c	2005-03-04 17:33:09.000000000 +0100
@@ -34,6 +34,10 @@
 #include <time.h>
 
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_session.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_session.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_session.c	2003-08-25 19:51:16.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_session.c	2005-03-05 22:04:53.000000000 +0100
@@ -47,6 +47,10 @@
 #endif
 #include <assert.h>
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
@@ -189,6 +193,13 @@
   scb->resolve_callback = NULL;
   scb->adns_query = NULL;
   scb->pub.remote = EMPTY_STRING;
+  scb->read_func = NULL;
+  scb->write_func = NULL;
+
+#ifdef HAVE_GNUTLS
+  scb->tls_session = NULL;
+  scb->tls_active = 0;
+#endif
 
   scb->cfg = cfg;
   scb->pub.master = mcb;
@@ -402,6 +413,8 @@
     cb(scb, isc_resolve_aborted, 0);
   }
 
+  isc_tls_destroy(sci);
+
   isc_cancel_read_callback(sci);
   isc_cancel_stale_output_callback(sci);
   isc_cancel_idle_callback(sci);
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_socket.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_socket.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_socket.c	2003-08-06 10:33:57.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_socket.c	2005-03-04 17:32:45.000000000 +0100
@@ -56,6 +56,11 @@
 #include <assert.h>
 #include <stdlib.h>
 
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_stdout.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_stdout.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_stdout.c	2003-08-11 11:41:08.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_stdout.c	2005-03-04 17:32:31.000000000 +0100
@@ -35,6 +35,11 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_tcp.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_tcp.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_tcp.c	2003-08-06 09:06:18.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_tcp.c	2005-03-04 17:33:00.000000000 +0100
@@ -55,6 +55,10 @@
 #include <time.h>
 #include <assert.h>
 
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
 #include "oop.h"
 #include "adns.h"
 #include "oop-adns.h"
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_tls.c lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_tls.c
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/isc_tls.c	1970-01-01 01:00:00.000000000 +0100
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/isc_tls.c	2005-03-16 07:53:12.000000000 +0100
@@ -0,0 +1,464 @@
+/*
+** isc_tls.c                          Routines to handle TLS
+**
+** Copyright (C) 2005 by Pontus Freyhult
+**
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Library General Public
+** License as published by the Free Software Foundation; either
+** version 2 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Library General Public License for more details.
+**
+** You should have received a copy of the GNU Library General Public
+** License along with this library; if not, write to the Free
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+**
+** (See ChangeLog for recent history)
+*/
+
+#include <errno.h>
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif
+#ifdef HAVE_STDDEF_H
+#  include <stddef.h>
+#endif
+#ifdef HAVE_STDARG_H
+#  include <stdarg.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
+#include <fcntl.h>
+#ifndef NULL
+#  include <stdio.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+#include <time.h>
+#include <assert.h>
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
+#include "oop.h"
+#include "adns.h"
+#include "oop-adns.h"
+
+#include "s-string.h"
+
+#include "isc.h"
+#include "intern.h"
+#include "isc_addr.h"
+#include "unused.h"
+
+static int dh_bits = 1024;
+static int cert_req = 0;
+static double handshake_timeout = 4;
+static int dh_regenerate_every = 1024;
+static char* certfile = NULL;
+static char* cafile = NULL;
+static char* keyfile = NULL;
+static char* crlfile = NULL;
+
+
+static int mcb_count = 0;
+
+static void
+isc_generate_dh_params(struct isc_mcb *mcb)
+{
+#ifdef HAVE_GNUTLS
+  int ret = gnutls_dh_params_generate2(mcb->dh_params, dh_bits);
+  if (ret<0) 
+      fprintf(stderr, "TLS Failed to generate DH params (%s), ignoring.\n",
+	      gnutls_strerror(ret));
+
+  gnutls_certificate_set_dh_params(mcb->x509_cred, mcb->dh_params);
+  gnutls_anon_set_server_dh_params(mcb->anoncred, mcb->dh_params);
+#endif
+}
+
+static size_t
+isc_tls_no_func(struct isc_scb* scb, void* buf, size_t count)
+{
+  return EWOULDBLOCK;
+}
+
+static size_t
+isc_tls_read(struct isc_scb* scb, void* buf, size_t count)
+{
+  struct isc_scb_internal *sci = (struct isc_scb_internal*) scb; 
+  int ret = gnutls_record_recv(sci->tls_session, buf, count);
+
+  if (ret == GNUTLS_E_AGAIN)
+    errno = EAGAIN;
+  if (ret == GNUTLS_E_INTERRUPTED)
+    errno = EINTR;
+
+  return ret;
+}
+
+static size_t
+isc_tls_write(struct isc_scb* scb, void* buf, size_t count)
+{
+  struct isc_scb_internal *sci = (struct isc_scb_internal*) scb;
+  int ret = gnutls_record_send(sci->tls_session, buf, count);
+
+  if (ret == GNUTLS_E_AGAIN)
+    errno = EAGAIN;
+  if (ret == GNUTLS_E_INTERRUPTED)
+    errno = EINTR;
+
+  return ret;
+}
+
+static void 
+isc_tls_regenerate(struct isc_mcb* mcb)
+{
+  /* FIXME: Should we deinit and init here? */
+  /* gnutls_dh_params_deinit(mcb->dh_params); */
+  isc_generate_dh_params(mcb);
+  mcb->dh_params_use_count = 0;
+}
+
+int 
+isc_tls_support()
+{
+#ifndef HAVE_GNUTLS
+  return 0;
+#else
+  return 1;
+#endif
+}
+
+int 
+isc_sasl_support()
+{
+  return 0;
+}
+
+
+
+static void*
+isc_tls_negotiate_callback(oop_source* source,
+			   struct timeval UNUSED(tv), 
+			   void *data)
+{
+  struct isc_scb_internal *sci = (struct isc_scb_internal*)data;
+  
+#ifdef HAVE_GNUTLS
+
+  int ret = gnutls_handshake(sci->tls_session);
+
+  /* FIXME? The server will be locked until we finish the handshake
+   * or abort because of timeout.
+   */
+
+  if (ret>=0)
+    {
+      unsigned int certstat = 0;
+      
+      if (cert_req)
+	certstat = gnutls_certificate_verify_peers(sci->tls_session);
+
+      if (certstat & ( GNUTLS_CERT_INVALID |
+		       GNUTLS_CERT_SIGNER_NOT_FOUND |
+		       GNUTLS_CERT_REVOKED ))
+	fprintf( stderr, 
+		 "TLS client cetificate verification requested and client\n"
+		 "certificate is not valid (%s).\n",
+		 gnutls_strerror(certstat));
+      else
+	{
+	  sci->read_func = &isc_tls_read;
+	  sci->write_func = &isc_tls_write;
+	}
+    }
+  else
+    {
+      if ((ret == GNUTLS_E_AGAIN ||
+	   ret == GNUTLS_E_INTERRUPTED ))
+	{
+	  if((time(NULL) - sci->tls_handshake_begin) 
+	     < handshake_timeout) 
+	    {
+	      struct timeval at;
+	      int timeerr = gettimeofday(&at, NULL);
+	      
+	      if (timeerr)
+		{
+		  perror("gettimeofday failed");
+		  source->on_time(source, 
+				  OOP_TIME_NOW,
+				  isc_tls_negotiate_callback,
+				  data);	  
+		}	      
+	      else
+		{
+		  at.tv_sec ++; /* Wait a little before */
+		  source->on_time(source, 
+				  at,
+				  isc_tls_negotiate_callback,
+				  data);	  
+		}
+	    }
+	  else /* No time left */
+	    {
+	      fprintf(stderr, "TLS negotiation timed out.\n");
+
+	      sci->read_func = NULL;
+	      sci->write_func = NULL;
+	      
+	    }
+	} /* Another error? */
+      else
+	{
+	  fprintf(stderr, "TLS negotiation failed: %s\n",
+		  gnutls_strerror(ret));
+	  
+	  sci->read_func = NULL;
+	  sci->write_func = NULL;
+	}
+    }
+#endif
+  return OOP_CONTINUE;
+}
+
+
+int 
+isc_tls_negotiate(struct isc_scb *scb)
+{
+  int ret = -1;
+#ifdef HAVE_GNUTLS
+  struct isc_scb_internal *sci = (struct isc_scb_internal*)scb;
+  const int kx_prio[] = { GNUTLS_KX_ANON_DH,  GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS,
+        GNUTLS_KX_DHE_RSA, GNUTLS_KX_RSA_EXPORT,  0 };
+
+  if (sci->tls_active) /* Already active, don't mess up */
+    return 0;
+
+  sci->tls_active = 1;
+
+  if (scb->master->dh_params_use_count > dh_regenerate_every)
+      isc_tls_regenerate(scb->master);
+
+  scb->master->dh_params_use_count++;
+
+  ret = gnutls_init(&sci->tls_session, GNUTLS_SERVER);
+
+
+  if (ret<0) /* Give up? */
+    {
+      fprintf(stderr, "TLS initialization failed (%s) giving up.\n",
+	      gnutls_strerror(ret));
+
+      return ret;
+    }
+
+  ret = gnutls_set_default_priority(sci->tls_session);
+  if (ret<0) 
+      fprintf(stderr, "TLS Failed to set default priorities (%s), ignoring.\n",
+	      gnutls_strerror(ret));
+
+
+  ret = gnutls_credentials_set(sci->tls_session, GNUTLS_CRD_CERTIFICATE, scb->master->x509_cred);
+  if (ret<0) 
+      fprintf(stderr, "TLS Failed to add certificate credentials (%s), ignoring.\n",
+	      gnutls_strerror(ret));
+
+
+
+  ret = gnutls_credentials_set(sci->tls_session, GNUTLS_CRD_ANON, scb->master->anoncred);
+  if (ret<0) 
+      fprintf(stderr, "TLS Failed to add anonymous credentials (%s), ignoring.\n",
+	      gnutls_strerror(ret));
+
+  ret = gnutls_kx_set_priority(sci->tls_session, kx_prio);
+  if (ret<0) 
+      fprintf(stderr, "TLS Failed to set priorities of key exchange algorithms (%s), ignoring.\n",
+	      gnutls_strerror(ret));
+
+  gnutls_dh_set_prime_bits(sci->tls_session, dh_bits);
+
+  if (cert_req)
+    gnutls_certificate_server_set_request(sci->tls_session, GNUTLS_CERT_REQUIRE);
+  else
+    gnutls_certificate_server_set_request(sci->tls_session, GNUTLS_CERT_REQUEST);
+
+  /* Probably not needed */
+  /* 
+   * gnutls_transport_set_push_function(sci->tls_session,write);
+   * gnutls_transport_set_pull_function(sci->tls_session,read);
+   */
+
+  gnutls_transport_set_ptr(sci->tls_session, (gnutls_transport_ptr_t) sci->pub.fd);
+
+  sci->tls_handshake_begin = time(NULL);
+
+  fprintf(stderr, "TLS negotiation starting.\n");
+
+  sci->read_func = &isc_tls_no_func; /* Make sure our data are not stolen */
+
+
+  scb->master->event_source->on_time(scb->master->event_source, 
+				     OOP_TIME_NOW, 
+				     isc_tls_negotiate_callback,
+				     scb);
+
+#endif
+  return ret;
+}
+
+
+void 
+isc_tls_initialize(struct isc_mcb *mcb)
+{
+#ifdef HAVE_GNUTLS
+
+  if (!mcb_count)
+    gnutls_global_init();
+
+  mcb_count++;
+
+  gnutls_certificate_allocate_credentials(&mcb->x509_cred);
+
+  if (cafile)
+    gnutls_certificate_set_x509_trust_file(mcb->x509_cred, cafile,
+					   GNUTLS_X509_FMT_PEM);
+  
+  if (crlfile)
+    gnutls_certificate_set_x509_crl_file(mcb->x509_cred, crlfile,
+					 GNUTLS_X509_FMT_PEM);
+  
+  if(keyfile && certfile)
+    gnutls_certificate_set_x509_key_file(mcb->x509_cred, certfile, keyfile,
+					 GNUTLS_X509_FMT_PEM);
+
+  gnutls_anon_allocate_server_credentials(&mcb->anoncred);  
+
+  gnutls_dh_params_init(&mcb->dh_params);
+
+  isc_tls_regenerate(mcb);
+    
+
+#endif /* HAVE_GNUTLS */
+}
+
+
+void 
+isc_tls_deinitialize(struct isc_mcb *mcb)
+{
+#ifdef HAVE_GNUTLS
+  /* 
+   * FIXME: A (probably theoretical problem)
+   * is if there is a problem shutting down a gnutls_session
+   * and this gets called before that is completed.
+   */
+
+     mcb_count--;
+
+     gnutls_certificate_free_crls(mcb->x509_cred);
+     gnutls_certificate_free_cas(mcb->x509_cred);
+     gnutls_certificate_free_keys(mcb->x509_cred);
+     /* gnutls_certificate_free_ca_names(mcb->x509_cred); */
+     gnutls_certificate_free_credentials(mcb->x509_cred);
+
+     gnutls_anon_free_server_credentials(mcb->anoncred);
+     
+     gnutls_dh_params_deinit(mcb->dh_params);
+     
+     if (!mcb_count)
+       gnutls_global_deinit();    
+
+#endif /* HAVE_GNUTLS */
+}
+
+void 
+isc_tls_set_params( int dh_bits_param,
+		    int cert_req_param,
+		    double handshake_timeout_param,
+		    int dh_regenerate_every_param,
+		    char* certfile_param,
+		    char* cafile_param,
+		    char* keyfile_param, 
+		    char* crlfile_param)
+{
+  dh_bits = dh_bits_param;
+  cert_req = cert_req_param;
+  certfile = certfile_param;
+  cafile = cafile_param;
+  keyfile = keyfile_param;
+  crlfile = crlfile_param;
+  handshake_timeout = handshake_timeout_param;
+  dh_regenerate_every = dh_regenerate_every_param;
+} 
+
+
+
+static void*
+isc_tls_die_callback(oop_source* source,
+		     struct timeval UNUSED(tv), 
+		     void *data)
+{
+#ifdef HAVE_GNUTLS
+  gnutls_session sess = (gnutls_session) data;
+
+  int ret = gnutls_bye(sess, GNUTLS_SHUT_RDWR);
+
+  if (ret<0) /* Problem? */
+    {
+      if ((ret  == GNUTLS_E_AGAIN ||
+	   ret == GNUTLS_E_INTERRUPTED))
+	{
+	  source->on_time(source, 
+			  OOP_TIME_NOW, 
+			  isc_tls_die_callback,
+			  data);
+
+	  return OOP_CONTINUE;
+	}
+      else
+	{
+	  fprintf(stderr, "TLS shutdown failed: %s\n",
+		  gnutls_strerror(ret));
+	  /* FIXME: Should we really call deinit? */
+	}
+    }
+  else
+    gnutls_deinit(data);    
+
+#endif
+  return OOP_CONTINUE;
+}
+
+
+void
+isc_tls_destroy(struct isc_scb_internal* sci)
+{
+#ifdef HAVE_GNUTLS
+  if(sci->tls_session)
+    /* FIXME: We pass a pointer, this would probably break if 
+     * gnutls_session_t changes (i.e. becomes a struct instead of a
+     * pointer to a struct). That is unlikely, though.
+     */
+    sci->pub.master->event_source->on_time(sci->pub.master->event_source, 
+					   OOP_TIME_NOW, 
+					   isc_tls_die_callback,
+					   sci->tls_session);   
+#endif
+}
diff -uNr lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/Makefile.am lyskom-server-2.1.2/src/libraries/libisc-new/src/Makefile.am
--- lyskom-server-2.1.2.orig/src/libraries/libisc-new/src/Makefile.am	2003-08-06 09:29:18.000000000 +0200
+++ lyskom-server-2.1.2/src/libraries/libisc-new/src/Makefile.am	2005-03-05 16:04:18.000000000 +0100
@@ -25,7 +25,7 @@
 	isc_event.c isc_session.c isc_abort.c isc_alloc.c isc_master.c \
 	isc_output.c isc_queue.c isc_message.c \
 	isc_stdout.c isc_socket.c isc_tcp.c unused.h intern.h \
-	isc_relocate.c isc_compat.c isc_addr.h
+	isc_relocate.c isc_compat.c isc_tls.c isc_addr.h
 
 noinst_HEADERS = isc.h
 
diff -uNr lyskom-server-2.1.2.orig/src/server/fncdef.txt lyskom-server-2.1.2/src/server/fncdef.txt
--- lyskom-server-2.1.2.orig/src/server/fncdef.txt	2003-08-25 19:51:18.000000000 +0200
+++ lyskom-server-2.1.2/src/server/fncdef.txt	2005-03-16 07:45:14.000000000 +0100
@@ -174,6 +174,9 @@
 104  success map_created_texts   num	num num	: text_mapping
 105  success set_keep_commented  num num
 106  success set_pers_flags      num pers_flags
+#
+# Protocol version 11
+#
 107  success query_read_texts    num num num num : membership
 108  success get_membership      num num num num num : membership_list
 109  success mark_as_unread	 num num
@@ -190,6 +193,7 @@
 120  success set_connection_time_format num
 121  success local_to_global_reverse   num num num : text_mapping_reverse
 122  success map_created_texts_reverse num num num : text_mapping_reverse
+123  success start_tls c_string (param.server_name_len)
 
 #ifdef DEBUG_CALLS
 1000 success get_memory_info          : memory_info
diff -uNr lyskom-server-2.1.2.orig/src/server/param.h lyskom-server-2.1.2/src/server/param.h
--- lyskom-server-2.1.2.orig/src/server/param.h	2003-08-23 18:54:47.000000000 +0200
+++ lyskom-server-2.1.2/src/server/param.h	2005-03-16 08:09:58.000000000 +0100
@@ -98,6 +98,7 @@
     int broadcast_len;
     int regexp_len;
     int stat_name_len;
+    int server_name_len;
     int max_marks_person;
     int max_marks_text;
     int max_recipients;
@@ -140,6 +141,17 @@
     Bool allow_reinvite;
     unsigned long max_conf;
     unsigned long max_text;
+
+    char* tls_crl_file;
+    char* tls_ca_file;
+    char* tls_cert_file;
+    char* tls_key_file;
+
+    struct timeval tls_handshake_timeout;
+    int tls_dh_bits;
+    int tls_dh_regenerate_frequency;
+    Bool tls_client_cert_required;
+
 };
 
 extern struct kom_par param;
diff -uNr lyskom-server-2.1.2.orig/src/server/ramkomd.c lyskom-server-2.1.2/src/server/ramkomd.c
--- lyskom-server-2.1.2.orig/src/server/ramkomd.c	2003-08-23 18:54:48.000000000 +0200
+++ lyskom-server-2.1.2/src/server/ramkomd.c	2005-03-07 12:51:25.000000000 +0100
@@ -450,6 +450,18 @@
     read_configuration(config_file);
     initialize_aux_items(param.aux_def_file);
 
+    isc_tls_set_params(param.tls_dh_bits, 
+		       param.tls_client_cert_required,
+		       param.tls_handshake_timeout.tv_sec + 
+		       param.tls_handshake_timeout.tv_usec*1e-6,
+		       param.tls_dh_regenerate_frequency,
+		       param.tls_cert_file,
+		       param.tls_ca_file,
+		       param.tls_key_file,
+		       param.tls_crl_file);
+
+
+
 #ifdef HAVE_LOCALE_H
     if (param.use_locale != NULL)
 	if (setlocale(LC_CTYPE, param.use_locale) == NULL)
diff -uNr lyskom-server-2.1.2.orig/src/server/server-config.c lyskom-server-2.1.2/src/server/server-config.c
--- lyskom-server-2.1.2.orig/src/server/server-config.c	2003-08-29 12:45:09.000000000 +0200
+++ lyskom-server-2.1.2/src/server/server-config.c	2005-03-16 08:09:27.000000000 +0100
@@ -353,6 +353,9 @@
 
     /* String limits */
 
+    {"Max server name length",
+	 assign_int,     NULL,             0, 1, "120", &param.server_name_len,
+         NULL},
     {"Max conference name length",
 	 assign_int,     NULL,             0, 1, "60", &param.conf_name_len,
          NULL},
@@ -474,6 +477,47 @@
          &param.authentication_level,
          NULL},
 
+    /* TLS options */
+
+    {"TLS cert file",
+         assign_path,    unassign_path,    0, 1, "cert.pem",
+         &param.tls_cert_file,
+         NULL},
+
+    {"TLS key file",
+         assign_path,    unassign_path,    0, 1, "key.pem",
+         &param.tls_key_file,
+         NULL},
+
+    {"TLS CA file",
+         assign_path,    unassign_path,    0, 1, "ca.pem",
+         &param.tls_ca_file,
+         NULL},
+
+    {"TLS CRL file",
+         assign_path,    unassign_path,    0, 1, "crl.pem",
+         &param.tls_crl_file,
+         NULL},
+
+    {"TLS require client certificate",
+        assign_bool,     NULL,             0, 1, "off", 
+         &param.tls_client_cert_required, NULL},
+
+    {"TLS operation timeout",
+	assign_timeval, NULL,             0, 1, "4",
+         &param.tls_handshake_timeout,
+         "seconds"},
+
+    {"TLS DH bits",
+         assign_int,     NULL,             0, 1, "1024", 
+          &param.tls_dh_bits,
+          NULL},
+
+    {"TLS DH regeneration frequency",
+         assign_int,     NULL,             0, 1, "1024", 
+          &param.tls_dh_regenerate_frequency,
+          NULL},
+    
     /* Cache configuration */
 
     {"Cache conference limit",
diff -uNr lyskom-server-2.1.2.orig/src/server/session.c lyskom-server-2.1.2/src/server/session.c
--- lyskom-server-2.1.2.orig/src/server/session.c	2003-08-23 18:54:48.000000000 +0200
+++ lyskom-server-2.1.2/src/server/session.c	2005-03-16 07:45:21.000000000 +0100
@@ -1067,3 +1067,21 @@
     active_connection->use_utc = use_utc;
     return OK;
 }
+
+extern Success
+start_tls(const String server_name)
+{
+  CHK_CONNECTION(FAILURE);
+
+  kom_log("TLS negotiation requested\n");
+  if (isc_tls_support())
+    if (isc_tls_negotiate(active_connection->isc_session) >= 0) 
+      return OK;	
+    else
+      kom_log("TLS setup failed\n");
+  
+  err_stat = 0;
+  kom_errno = KOM_TLS_DISABLED;
+
+  return FAILURE;
+}
