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 + + = 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 + + * src/isc.h: Added declarations for isc_tls_support and + isc_sasl_support. + 2003-08-25 Per Cederqvist 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 ]) +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 #include +#ifdef HAVE_GNUTLS +#include +#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 +#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 #include + +#ifdef HAVE_GNUTLS +#include +#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 /* Needed on AIX 4.2 due to bzero */ #endif +#ifdef HAVE_GNUTLS +#include +#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 #endif +#ifdef HAVE_GNUTLS +#include +#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 #include +#ifdef HAVE_GNUTLS +#include +#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 #include +#ifdef HAVE_GNUTLS +#include +#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 #include + +#ifdef HAVE_GNUTLS +#include +#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 +#ifdef HAVE_GNUTLS +#include +#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 +#ifdef HAVE_GNUTLS +#include +#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 #include + +#ifdef HAVE_GNUTLS +#include +#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 #include + +#ifdef HAVE_GNUTLS +#include +#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 #include +#ifdef HAVE_GNUTLS +#include +#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 +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_STDDEF_H +# include +#endif +#ifdef HAVE_STDARG_H +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STRING_H +# include +#endif +#include +#ifndef NULL +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include + +#ifdef HAVE_GNUTLS +#include +#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", ¶m.server_name_len, + NULL}, {"Max conference name length", assign_int, NULL, 0, 1, "60", ¶m.conf_name_len, NULL}, @@ -474,6 +477,47 @@ ¶m.authentication_level, NULL}, + /* TLS options */ + + {"TLS cert file", + assign_path, unassign_path, 0, 1, "cert.pem", + ¶m.tls_cert_file, + NULL}, + + {"TLS key file", + assign_path, unassign_path, 0, 1, "key.pem", + ¶m.tls_key_file, + NULL}, + + {"TLS CA file", + assign_path, unassign_path, 0, 1, "ca.pem", + ¶m.tls_ca_file, + NULL}, + + {"TLS CRL file", + assign_path, unassign_path, 0, 1, "crl.pem", + ¶m.tls_crl_file, + NULL}, + + {"TLS require client certificate", + assign_bool, NULL, 0, 1, "off", + ¶m.tls_client_cert_required, NULL}, + + {"TLS operation timeout", + assign_timeval, NULL, 0, 1, "4", + ¶m.tls_handshake_timeout, + "seconds"}, + + {"TLS DH bits", + assign_int, NULL, 0, 1, "1024", + ¶m.tls_dh_bits, + NULL}, + + {"TLS DH regeneration frequency", + assign_int, NULL, 0, 1, "1024", + ¶m.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; +}