[cvslog] [CVS] Module eggdrop1.8: Change committed

cvs at eggheads.org cvs at eggheads.org
Tue Oct 19 06:13:44 CST 2010


CVSROOT    : /usr/local/cvsroot
Module     : eggdrop1.8
Commit time: 2010-10-19 12:13:43 UTC
Committer  : Rumen Stoyanov <pseudo at egg6.net>

Modified files:
     Makefile.in aclocal.m4 config.h.in configure configure.ac
     eggdrop.conf doc/CONTENTS doc/Changes1.8 doc/tcl-commands.doc
     doc/html/egg-core.html doc/html/mod-server.html
     doc/html/tcl-commands.html doc/settings/core.settings
     doc/settings/mod.server help/cmds1.help help/core.help
     help/set/cmds1.help src/Makefile.in src/botcmd.c src/botnet.c
     src/chanprog.c src/cmds.c src/dcc.c src/dccutil.c src/eggdrop.h
     src/main.c src/mem.c src/modules.c src/net.c src/patch.h
     src/proto.h src/tcl.c src/tcldcc.c src/tclhash.c src/tclhash.h
     src/userent.c src/users.h src/compat/Makefile.in
     src/md5/Makefile.in src/md5/md5.h src/md5/md5c.c
     src/mod/Makefile.in src/mod/module.h src/mod/ctcp.mod/ctcp.c
     src/mod/filesys.mod/filedb3.c src/mod/filesys.mod/filesys.c
     src/mod/irc.mod/msgcmds.c src/mod/irc.mod/help/msg/irc.help
     src/mod/server.mod/cmdsserv.c src/mod/server.mod/server.c
     src/mod/server.mod/server.h src/mod/server.mod/servmsg.c
     src/mod/server.mod/tclserv.c src/mod/server.mod/help/server.help
     src/mod/server.mod/help/set/server.help src/mod/share.mod/share.c

Added files:
     ssl.conf doc/TLS src/tls.c

Log message:

Added full SSL support including Tcl commands.
Added support for certificate authentication.
Added support for botnet and partyline encryption using ssl.
Documented the new features and commands.
Fixed add_server() problems with IPv6 addresses in the server list.

---------------------- diff included ----------------------
Index: eggdrop1.8/Makefile.in
diff -u eggdrop1.8/Makefile.in:1.1.1.1 eggdrop1.8/Makefile.in:1.2
--- eggdrop1.8/Makefile.in:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/Makefile.in	Tue Oct 19 06:13:32 2010
@@ -2,7 +2,7 @@
 #  This is the Makefile for EGGDROP (the IRC bot)
 #  You should never need to edit this.
 #
-# $Id: Makefile.in,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+# $Id: Makefile.in,v 1.2 2010/10/19 12:13:32 pseudo Exp $
 
 SHELL = @SHELL@
 top_srcdir = @top_srcdir@
@@ -70,7 +70,7 @@
 # Extra libraries
 # XLIBS will be linked with everything
 # MODULE_XLIBS will only be linked with the module objects
-XLIBS = @TCL_LIBS@ @LIBS@
+XLIBS = @SSL_LIBS@ @TCL_LIBS@ @LIBS@
 MODULE_XLIBS = @MODULE_XLIBS@
 
 # You shouldn't need to edit anything below this line.
@@ -291,6 +291,20 @@
 	fi
 	@echo "stamp" >EGGMOD.stamp
 
+sslcert:
+	@if test ! -d $(DEST); then \
+		echo "You haven't installed eggdrop yet.";\
+		echo "Please run \"make install\" first.";\
+		exit 1;\
+	fi
+	@if test -f $(DEST)/eggdrop.key; then \
+		cp $(DEST)/eggdrop.key $(DEST)/eggdrop.key~old; \
+	fi
+	@if test -f $(DEST)/eggdrop.crt; then \
+		cp $(DEST)/eggdrop.crt $(DEST)/eggdrop.crt~old; \
+	fi
+	@openssl req -new -x509 -nodes -days 365 -keyout $(DEST)/eggdrop.key -out $(DEST)/eggdrop.crt -config ssl.conf; \
+
 install: ainstall
 
 dinstall: eggdrop ainstall
Index: eggdrop1.8/aclocal.m4
diff -u eggdrop1.8/aclocal.m4:1.7 eggdrop1.8/aclocal.m4:1.8
--- eggdrop1.8/aclocal.m4:1.7	Thu Oct 14 03:49:47 2010
+++ eggdrop1.8/aclocal.m4	Tue Oct 19 06:13:32 2010
@@ -16,7 +16,7 @@
 dnl along with this program; if not, write to the Free Software
 dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 dnl
-dnl $Id: aclocal.m4,v 1.7 2010/10/14 09:49:47 pseudo Exp $
+dnl $Id: aclocal.m4,v 1.8 2010/10/19 12:13:32 pseudo Exp $
 dnl
 
 
@@ -1904,3 +1904,139 @@
     ])
   ])
 ])
+
+
+dnl EGG_TLS_ENABLE
+dnl
+AC_DEFUN([EGG_TLS_ENABLE],
+[
+  AC_MSG_CHECKING([whether to enable TLS support])
+  AC_ARG_ENABLE(tls,
+    [  --enable-tls            enable TLS support (autodetect)],
+    [enable_tls="$enableval"])
+  AC_ARG_ENABLE(tls,
+    [  --disable-tls           disable TLS support ], [enable_tls="$enableval"],
+    [enable_tls="autodetect"])
+
+  AC_MSG_RESULT([$enable_tls])
+])
+
+
+dnl EGG_TLS_WITHSSL
+dnl
+AC_DEFUN(EGG_TLS_WITHSSL,
+[
+  save_LIBS="$LIBS"
+  AC_ARG_WITH(sslinc, [  --with-sslinc=PATH      Path to OpenSSL headers], [
+    if test "$enable_tls" != "no"; then
+      if test -d "$withval"; then
+        save_CC="$CC"
+        save_CPP="$CPP"
+        CC="$CC -I$withval"
+        CPP="$CPP -I$withval"
+        AC_CHECK_HEADERS([openssl/ssl.h openssl/x509v3.h], [sslinc="-I$withval"], [
+          AC_MSG_WARN([Invalid path to OpenSSL headers. $withval/openssl/ doesn't contain the required files.])
+          sslinc=""
+          break
+        ], [[
+          #ifdef CYGWIN_HACKS
+          #  ifndef __int64
+          #    define __int64 long long
+          #  endif
+          #endif
+        ]])
+        AC_SUBST(SSL_INCLUDES, [$sslinc])
+        CC="$save_CC"
+        CPP="$save_CPP"
+      else
+        AC_MSG_WARN([Invalid path to OpenSSL headers. $withval is not a directory.])
+      fi
+    fi
+  ])
+
+  AC_ARG_WITH(ssllib, [  --with-ssllib=PATH      Path to OpenSSL libraries],
+  [
+    if test "$enable_tls" != "no"; then
+      if test -d "$withval"; then
+        AC_CHECK_LIB(ssl, SSL_accept, , [havessllib="no"], [-L$withval])
+        AC_CHECK_LIB(crypto, X509_digest, , [havessllib="no"], [-L$withval])
+        if test "$havessllib" = "no"; then
+          AC_MSG_WARN([Invalid path to OpenSSL libs. $withval doesn't contain the required files.])
+        else
+          AC_SUBST(SSL_LIBS, [-L$withval])
+        fi
+      else
+        AC_MSG_WARN([You have specified an invalid path to OpenSSL libs. $withval is not a directory.])
+      fi
+    fi
+  ])
+])
+
+
+dnl EGG_TLS_DETECT
+dnl
+AC_DEFUN([EGG_TLS_DETECT],
+[
+  if test "$enable_tls" != "no"; then
+    if test -z "$SSL_INCLUDES"; then
+      AC_CHECK_HEADERS([openssl/ssl.h openssl/x509v3.h], , [havesslinc="no"], [
+        #ifdef CYGWIN_HACKS
+        #  ifndef __int64
+        #    define __int64 long long
+        #  endif
+        #endif
+      ])
+    fi
+    if test -z "$SSL_LIBS"; then
+      AC_CHECK_LIB(ssl, SSL_accept, , [havessllib="no"], [-lcrypto])
+      AC_CHECK_LIB(crypto, X509_digest, , [havessllib="no"], [-lssl])
+      AC_CHECK_FUNCS([EVP_md5 EVP_sha1 hex_to_string string_to_hex], , [[
+        havessllib="no"
+        break
+      ]])
+    fi
+    if test "$enable_tls" = "yes"; then
+      if test "$havesslinc" = "no"; then
+        AC_MSG_WARN([Cannot find OpenSSL headers.])
+        AC_MSG_WARN([Please specify the path to the openssl include dir using --with-sslinc=path])
+      fi
+      if test "$havessllib" = "no"; then
+        AC_MSG_WARN([Cannot find OpenSSL libraries.])
+        AC_MSG_WARN([Please specify the path to libssl and libcrypto using --with-ssllib=path])
+      fi
+    fi
+    AC_MSG_CHECKING([for OpenSSL])
+    if test "$havesslinc" = "no" || test "$havessllib" = "no"; then
+      AC_MSG_RESULT([no])
+      LIBS="$save_LIBS"
+    else
+      AC_MSG_RESULT([yes])
+      if test "$EGG_CYGWIN" = "yes"; then
+        AC_CHECK_TYPE([__int64], , [
+          AC_DEFINE([__int64], [long long], [Define this to a 64-bit type on Cygwin to satisfy OpenSSL dependencies.])
+        ])
+      fi
+      AC_DEFINE(TLS, 1, [Define this to enable SSL support.])
+      EGG_MD5_COMPAT
+    fi
+  fi
+])
+
+
+dnl EGG_MD5_COMPAT
+dnl
+AC_DEFUN([EGG_MD5_COMPAT],
+[
+  save_CC="$CC"
+  save_CPP="$CPP"
+  CC="$CC $sslinc"
+  CPP="$CPP $sslinc"
+  AC_CHECK_HEADERS([openssl/md5.h], [
+    AC_CHECK_FUNCS([MD5_Init MD5_Update MD5_Final], , [havesslmd5="no"])
+  ])
+  if test "$havesslmd5" != "no"; then
+    AC_DEFINE(HAVE_OPENSSL_MD5, 1, [Define this if your OpenSSL library has MD5 cipher support.])
+  fi
+  CC="$save_CC"
+  CPP="$save_CPP"
+])
Index: eggdrop1.8/config.h.in
diff -u eggdrop1.8/config.h.in:1.5 eggdrop1.8/config.h.in:1.6
--- eggdrop1.8/config.h.in:1.5	Thu Oct 14 03:49:47 2010
+++ eggdrop1.8/config.h.in	Tue Oct 19 06:13:32 2010
@@ -84,6 +84,12 @@
 /* Define to 1 if you have the `dprintf' function. */
 #undef HAVE_DPRINTF
 
+/* Define to 1 if you have the `EVP_md5' function. */
+#undef HAVE_EVP_MD5
+
+/* Define to 1 if you have the `EVP_sha1' function. */
+#undef HAVE_EVP_SHA1
+
 /* Define to 1 if you have the <fcntl.h> header file. */
 #undef HAVE_FCNTL_H
 
@@ -102,6 +108,9 @@
 /* Define to 1 if you have the `getrusage' function. */
 #undef HAVE_GETRUSAGE
 
+/* Define to 1 if you have the `hex_to_string' function. */
+#undef HAVE_HEX_TO_STRING
+
 /* Define to 1 if you have the in6addr_any constant. */
 #undef HAVE_IN6ADDR_ANY
 
@@ -126,6 +135,9 @@
 /* Define to 1 if you have the `isascii' function. */
 #undef HAVE_ISASCII
 
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
 /* Define to 1 if you have the `dl' library (-ldl). */
 #undef HAVE_LIBDL
 
@@ -141,6 +153,9 @@
 /* Define to 1 if you have the `socket' library (-lsocket). */
 #undef HAVE_LIBSOCKET
 
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
+
 /* Define to 1 if you have the <limits.h> header file. */
 #undef HAVE_LIMITS_H
 
@@ -165,6 +180,15 @@
 /* Define to 1 if you have the `mbrlen' function. */
 #undef HAVE_MBRLEN
 
+/* Define to 1 if you have the `MD5_Final' function. */
+#undef HAVE_MD5_FINAL
+
+/* Define to 1 if you have the `MD5_Init' function. */
+#undef HAVE_MD5_INIT
+
+/* Define to 1 if you have the `MD5_Update' function. */
+#undef HAVE_MD5_UPDATE
+
 /* Define to 1 if you have the `memcpy' function. */
 #undef HAVE_MEMCPY
 
@@ -189,6 +213,18 @@
 /* Define to 1 if you have the `NSLinkModule' function. */
 #undef HAVE_NSLINKMODULE
 
+/* Define this if your OpenSSL library has MD5 cipher support. */
+#undef HAVE_OPENSSL_MD5
+
+/* Define to 1 if you have the <openssl/md5.h> header file. */
+#undef HAVE_OPENSSL_MD5_H
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define to 1 if you have the <openssl/x509v3.h> header file. */
+#undef HAVE_OPENSSL_X509V3_H
+
 /* Define to 1 if you have the `rand' function. */
 #undef HAVE_RAND
 
@@ -249,6 +285,9 @@
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if you have the `string_to_hex' function. */
+#undef HAVE_STRING_TO_HEX
+
 /* Define to 1 if you have the `strncasecmp' function. */
 #undef HAVE_STRNCASECMP
 
@@ -402,6 +441,9 @@
 /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
 #undef TIME_WITH_SYS_TIME
 
+/* Define this to enable SSL support. */
+#undef TLS
+
 /* Define to 1 if your <sys/time.h> declares `struct tm'. */
 #undef TM_IN_SYS_TIME
 
@@ -449,6 +491,9 @@
 /* Define to 1 if you need to in order for `stat' and other things to work. */
 #undef _POSIX_SOURCE
 
+/* Define this to a 64-bit type on Cygwin to satisfy OpenSSL dependencies. */
+#undef __int64
+
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const
 
Index: eggdrop1.8/configure
diff -u eggdrop1.8/configure:1.8 eggdrop1.8/configure:1.9
--- eggdrop1.8/configure:1.8	Thu Oct 14 03:49:47 2010
+++ eggdrop1.8/configure	Tue Oct 19 06:13:32 2010
@@ -604,6 +604,8 @@
 MOD_UPDIR
 DEST
 EGGVERSION
+SSL_LIBS
+SSL_INCLUDES
 DEBCFLGS
 CFLGS
 TCL_LIBS
@@ -707,6 +709,9 @@
 enable_debug_context
 with_handlen
 enable_ipv6
+enable_tls
+with_sslinc
+with_ssllib
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1350,6 +1355,10 @@
   --with-handlen=VALUE    set the maximum length a handle on the bot can be
   --enable-ipv6           enable IPv6 support (autodetect)
   --disable-ipv6          disable IPv6 support
+  --enable-tls            enable TLS support (autodetect)
+  --disable-tls           disable TLS support
+  --with-sslinc=PATH      Path to OpenSSL headers
+  --with-ssllib=PATH      Path to OpenSSL libraries
 
 Some influential environment variables:
   CC          C compiler command
@@ -7984,6 +7993,7 @@
 
 
 
+
 # Check for IPv6
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for system IPv6 support" >&5
@@ -8186,6 +8196,421 @@
 
 
 
+# Check for TLS
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable TLS support" >&5
+$as_echo_n "checking whether to enable TLS support... " >&6; }
+  # Check whether --enable-tls was given.
+if test "${enable_tls+set}" = set; then :
+  enableval=$enable_tls; enable_tls="$enableval"
+fi
+
+  # Check whether --enable-tls was given.
+if test "${enable_tls+set}" = set; then :
+  enableval=$enable_tls; enable_tls="$enableval"
+else
+  enable_tls="autodetect"
+fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_tls" >&5
+$as_echo "$enable_tls" >&6; }
+
+
+  save_LIBS="$LIBS"
+
+# Check whether --with-sslinc was given.
+if test "${with_sslinc+set}" = set; then :
+  withval=$with_sslinc;
+    if test "$enable_tls" != "no"; then
+      if test -d "$withval"; then
+        save_CC="$CC"
+        save_CPP="$CPP"
+        CC="$CC -I$withval"
+        CPP="$CPP -I$withval"
+        for ac_header in openssl/ssl.h openssl/x509v3.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
+          #ifdef CYGWIN_HACKS
+          #  ifndef __int64
+          #    define __int64 long long
+          #  endif
+          #endif
+
+"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ sslinc="-I$withval"
+else
+
+          { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Invalid path to OpenSSL headers. $withval/openssl/ doesn't contain the required files." >&5
+$as_echo "$as_me: WARNING: Invalid path to OpenSSL headers. $withval/openssl/ doesn't contain the required files." >&2;}
+          sslinc=""
+          break
+
+fi
+
+done
+
+        SSL_INCLUDES=$sslinc
+
+        CC="$save_CC"
+        CPP="$save_CPP"
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Invalid path to OpenSSL headers. $withval is not a directory." >&5
+$as_echo "$as_me: WARNING: Invalid path to OpenSSL headers. $withval is not a directory." >&2;}
+      fi
+    fi
+
+fi
+
+
+
+# Check whether --with-ssllib was given.
+if test "${with_ssllib+set}" = set; then :
+  withval=$with_ssllib;
+    if test "$enable_tls" != "no"; then
+      if test -d "$withval"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_accept in -lssl" >&5
+$as_echo_n "checking for SSL_accept in -lssl... " >&6; }
+if test "${ac_cv_lib_ssl_SSL_accept+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lssl -L$withval $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SSL_accept ();
+int
+main ()
+{
+return SSL_accept ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ssl_SSL_accept=yes
+else
+  ac_cv_lib_ssl_SSL_accept=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_accept" >&5
+$as_echo "$ac_cv_lib_ssl_SSL_accept" >&6; }
+if test "x$ac_cv_lib_ssl_SSL_accept" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSSL 1
+_ACEOF
+
+  LIBS="-lssl $LIBS"
+
+else
+  havessllib="no"
+fi
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_digest in -lcrypto" >&5
+$as_echo_n "checking for X509_digest in -lcrypto... " >&6; }
+if test "${ac_cv_lib_crypto_X509_digest+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypto -L$withval $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char X509_digest ();
+int
+main ()
+{
+return X509_digest ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_crypto_X509_digest=yes
+else
+  ac_cv_lib_crypto_X509_digest=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_X509_digest" >&5
+$as_echo "$ac_cv_lib_crypto_X509_digest" >&6; }
+if test "x$ac_cv_lib_crypto_X509_digest" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPTO 1
+_ACEOF
+
+  LIBS="-lcrypto $LIBS"
+
+else
+  havessllib="no"
+fi
+
+        if test "$havessllib" = "no"; then
+          { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Invalid path to OpenSSL libs. $withval doesn't contain the required files." >&5
+$as_echo "$as_me: WARNING: Invalid path to OpenSSL libs. $withval doesn't contain the required files." >&2;}
+        else
+          SSL_LIBS=-L$withval
+
+        fi
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You have specified an invalid path to OpenSSL libs. $withval is not a directory." >&5
+$as_echo "$as_me: WARNING: You have specified an invalid path to OpenSSL libs. $withval is not a directory." >&2;}
+      fi
+    fi
+
+fi
+
+
+
+  if test "$enable_tls" != "no"; then
+    if test -z "$SSL_INCLUDES"; then
+      for ac_header in openssl/ssl.h openssl/x509v3.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
+        #ifdef CYGWIN_HACKS
+        #  ifndef __int64
+        #    define __int64 long long
+        #  endif
+        #endif
+
+"
+eval as_val=\$$as_ac_Header
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  havesslinc="no"
+fi
+
+done
+
+    fi
+    if test -z "$SSL_LIBS"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_accept in -lssl" >&5
+$as_echo_n "checking for SSL_accept in -lssl... " >&6; }
+if test "${ac_cv_lib_ssl_SSL_accept+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lssl -lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SSL_accept ();
+int
+main ()
+{
+return SSL_accept ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ssl_SSL_accept=yes
+else
+  ac_cv_lib_ssl_SSL_accept=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_accept" >&5
+$as_echo "$ac_cv_lib_ssl_SSL_accept" >&6; }
+if test "x$ac_cv_lib_ssl_SSL_accept" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSSL 1
+_ACEOF
+
+  LIBS="-lssl $LIBS"
+
+else
+  havessllib="no"
+fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X509_digest in -lcrypto" >&5
+$as_echo_n "checking for X509_digest in -lcrypto... " >&6; }
+if test "${ac_cv_lib_crypto_X509_digest+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypto -lssl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char X509_digest ();
+int
+main ()
+{
+return X509_digest ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_crypto_X509_digest=yes
+else
+  ac_cv_lib_crypto_X509_digest=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_X509_digest" >&5
+$as_echo "$ac_cv_lib_crypto_X509_digest" >&6; }
+if test "x$ac_cv_lib_crypto_X509_digest" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPTO 1
+_ACEOF
+
+  LIBS="-lcrypto $LIBS"
+
+else
+  havessllib="no"
+fi
+
+      for ac_func in EVP_md5 EVP_sha1 hex_to_string string_to_hex
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+        havessllib="no"
+        break
+
+fi
+done
+
+    fi
+    if test "$enable_tls" = "yes"; then
+      if test "$havesslinc" = "no"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find OpenSSL headers." >&5
+$as_echo "$as_me: WARNING: Cannot find OpenSSL headers." >&2;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please specify the path to the openssl include dir using --with-sslinc=path" >&5
+$as_echo "$as_me: WARNING: Please specify the path to the openssl include dir using --with-sslinc=path" >&2;}
+      fi
+      if test "$havessllib" = "no"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find OpenSSL libraries." >&5
+$as_echo "$as_me: WARNING: Cannot find OpenSSL libraries." >&2;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please specify the path to libssl and libcrypto using --with-ssllib=path" >&5
+$as_echo "$as_me: WARNING: Please specify the path to libssl and libcrypto using --with-ssllib=path" >&2;}
+      fi
+    fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL" >&5
+$as_echo_n "checking for OpenSSL... " >&6; }
+    if test "$havesslinc" = "no" || test "$havessllib" = "no"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+      LIBS="$save_LIBS"
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+      if test "$EGG_CYGWIN" = "yes"; then
+        ac_fn_c_check_type "$LINENO" "__int64" "ac_cv_type___int64" "$ac_includes_default"
+if test "x$ac_cv_type___int64" = x""yes; then :
+
+else
+
+
+$as_echo "#define __int64 long long" >>confdefs.h
+
+
+fi
+
+      fi
+
+$as_echo "#define TLS 1" >>confdefs.h
+
+
+  save_CC="$CC"
+  save_CPP="$CPP"
+  CC="$CC $sslinc"
+  CPP="$CPP $sslinc"
+  for ac_header in openssl/md5.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "openssl/md5.h" "ac_cv_header_openssl_md5_h" "$ac_includes_default"
+if test "x$ac_cv_header_openssl_md5_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_OPENSSL_MD5_H 1
+_ACEOF
+
+    for ac_func in MD5_Init MD5_Update MD5_Final
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  havesslmd5="no"
+fi
+done
+
+
+fi
+
+done
+
+  if test "$havesslmd5" != "no"; then
+
+$as_echo "#define HAVE_OPENSSL_MD5 1" >>confdefs.h
+
+  fi
+  CC="$save_CC"
+  CPP="$save_CPP"
+
+    fi
+  fi
+
+
+
 # Substitute Makefile variables.
 
   EGGVERSION=`grep 'char.egg_version' $srcdir/src/main.c | $AWK '{gsub(/(\"|\;)/, "", $4); print $4}'`
Index: eggdrop1.8/configure.ac
diff -u eggdrop1.8/configure.ac:1.4 eggdrop1.8/configure.ac:1.5
--- eggdrop1.8/configure.ac:1.4	Wed Aug 11 09:57:50 2010
+++ eggdrop1.8/configure.ac	Tue Oct 19 06:13:32 2010
@@ -1,11 +1,11 @@
 dnl configure.ac: this file is processed by autoconf to produce ./configure.
 dnl
-dnl $Id: configure.ac,v 1.4 2010/08/11 15:57:50 thommey Exp $
+dnl $Id: configure.ac,v 1.5 2010/10/19 12:13:32 pseudo Exp $
 
 AC_PREREQ(2.60)
 AC_INIT([Eggdrop],[1.8.0],[bugs at eggheads.org])
 AC_COPYRIGHT([Copyright (C) 1999 - 2010 Eggheads Development Team])
-AC_REVISION($Revision: 1.4 $)
+AC_REVISION($Revision: 1.5 $)
 AC_CONFIG_SRCDIR(src/eggdrop.h)
 AC_CONFIG_AUX_DIR(misc)
 AC_CONFIG_HEADER(config.h)
@@ -187,12 +187,19 @@
 # Let the user set the handlen with a configure option
 EGG_ARG_HANDLEN
 
+
 # Check for IPv6
 EGG_IPV6_STATUS
 EGG_IPV6_ENABLE
 EGG_IPV6_COMPAT
 
 
+# Check for TLS
+EGG_TLS_ENABLE
+EGG_TLS_WITHSSL
+EGG_TLS_DETECT
+
+
 # Substitute Makefile variables.
 EGG_SUBST_EGGVERSION
 EGG_SUBST_DEST
Index: eggdrop1.8/doc/CONTENTS
diff -u eggdrop1.8/doc/CONTENTS:1.2 eggdrop1.8/doc/CONTENTS:1.3
--- eggdrop1.8/doc/CONTENTS:1.2	Thu Aug  5 12:12:04 2010
+++ eggdrop1.8/doc/CONTENTS	Tue Oct 19 06:13:32 2010
@@ -1,4 +1,4 @@
-$Id: CONTENTS,v 1.2 2010/08/05 18:12:04 pseudo Exp $
+$Id: CONTENTS,v 1.3 2010/10/19 12:13:32 pseudo Exp $
 
 Directory Contents - doc/
 Last revised: July 29, 2010
@@ -40,6 +40,10 @@
     This document provides information about IPv6 support which is a new
     eggdrop feature since version 1.8.0.
 
+  TLS
+    This document provides information about TLS support which is a new
+    eggdrop feature since version 1.8.0.
+
   KNOWN-PROBLEMS
     See this file for a list of things that are broken but aren't getting
     fixed anytime soon
Index: eggdrop1.8/doc/Changes1.8
diff -u eggdrop1.8/doc/Changes1.8:1.19 eggdrop1.8/doc/Changes1.8:1.20
--- eggdrop1.8/doc/Changes1.8:1.19	Thu Oct 14 03:49:47 2010
+++ eggdrop1.8/doc/Changes1.8	Tue Oct 19 06:13:32 2010
@@ -1,4 +1,4 @@
-$Id: Changes1.8,v 1.19 2010/10/14 09:49:47 pseudo Exp $
+$Id: Changes1.8,v 1.20 2010/10/19 12:13:32 pseudo Exp $
 
 Eggdrop Changes (since version 1.8.0)
 
@@ -6,6 +6,13 @@
 
 1.8.0 (CVS):
 
+  - Added full SSL support including Tcl commands.
+  - Added support for certificate authentication.
+  - Added support for botnet and partyline encryption using ssl.
+  - Documented the new features and commands.
+  - Fixed add_server() problems with IPv6 addresses in the server list.
+    Patch by: pseudo
+
   - Fixed dns.mod on QNX6/Mac OS X/Solaris
   - Rewrote dns.mod's autoconf checks to detect the resolver library properly
     on Darwin/Solaris.
Index: eggdrop1.8/doc/TLS
diff -u /dev/null eggdrop1.8/doc/TLS:1.1
--- /dev/null	Tue Oct 19 06:13:43 2010
+++ eggdrop1.8/doc/TLS	Tue Oct 19 06:13:32 2010
@@ -0,0 +1,173 @@
+$Id: TLS,v 1.1 2010/10/19 12:13:32 pseudo Exp $
+
+TLS support
+Last revised: Oct 17, 2010
+    _____________________________________________________________________
+
+                         TLS support
+
+
+  This document provides information about TLS support which is a new
+  eggdrop feature since version 1.8.0.
+
+  Contents:
+    1. About
+    2. Installation
+    3. Usage
+       3a. IRC
+       3b. Botnet
+       3c. Secure DCC
+       3d. Scripts
+    4. Keys, certificates and authentication
+    5. SSL settings
+
+
+  1. About
+
+    Eggdrop can be optionally compiled with TLS support. This requires a
+    recent version of the OpenSSL library installed on your system.
+    TLS support includes encryption for IRC, DCC, botnet, telnet and scripted
+    connections as well as certificate authentication for users and bots.
+
+
+  2. Installation
+
+    ./configure and install as usual, the configure script will detect if your
+    system meets the requirements and will enable TLS automatically. You can
+    override the autodetection and manually disable TLS with 
+    ./configure --disable-tls. You can't forcefully enable it though.
+    The configure script will look for OpenSSL at the default system locations.
+    If you have it installed at a non-standard location or locally in your
+    home directory, you'll need to specify the paths to header and library
+    files with the --with-sslinc and --with-ssllib options. You can also use
+    these if you want to override the default OpenSSL installation with a
+    custom one, as they take precedence over any system-wide paths.
+
+
+  3. Usage
+
+    By default, without additional configuration, TLS support will provide
+    opportunistic encryption for botnet links. For other connection types,
+    TLS must be requested explicitly.
+    Secure connections are created the same way as plaintext ones. The only
+    difference is that you must prefix the port number with a plus sign.
+    A port number that could be normally omitted, would have to be included
+    to enable TLS. Scripts can also switch a regular, plaintext connection
+    to TLS, using the starttls Tcl command.
+
+  3a. IRC
+
+    To connect to IRC using SSL, specify the port number and prefix it with
+    a plus sign. Example: .jump irc.server.com +6697. The same goes for
+    the server list in the config file.
+
+  3b. Botnet
+
+    Botnet links between TLS-enabled bots will automatically switch to SSL.
+    In this case however, the nickname and password will be sent before SSL
+    negotiation takes place (the password is not send as cleartext anyway).
+    If one of the bots doesn't support TLS, the connection will fall back to
+    plain text. To require SSL explicitly, you need to open a ssl telnet
+    port on your hub and prefix the port number with + when adding it on your
+    leafs. For SSL-only bot links, all communication is encrypted, including
+    sending the nickname and password. If SSL negotiation fails, the
+    connection is deliberately aborted and no clear text is ever sent.
+
+  3c. Secure DCC
+
+    Eggdrop supports the SDCC protocol, allowing you to establish DCC chat
+    and file transfers over SSL. Example: /ctcp bot schat
+    Note, that currently the only IRC client supporting SDCC is KVIrc. For
+    information on how to initiate secure DCC chat from KVIrc (rather than
+    from the bot with /ctcp bot chat), consult the KVIrc documentation.
+
+  3d. Scripts
+
+    Scripts can open or connect to SSL ports the usual way specifying the
+    port with a plus sign. Alternatively, the connection could be
+    established as plaintext and later switched on with the starttls Tcl
+    command. (Note that the other side should also switch to SSL at the same
+    time - the synchronization is the script's job, not eggdrop's.)
+
+
+  4. Keys, certificates and authentication
+
+    You need a private key and a digital certificate whenever your bot will
+    act as a server in a connection of any type. Common examples are hub
+    bots and SSL listening ports. General information about certificates and
+    public key infrastructure can be obtained from Internet. This document
+    only contains eggdrop-specific information on the subject.
+    The easy way to create a key and a certificate is to type 'make sslcert'
+    after compiling your bot. This will generate a 2048-bit private key
+    (eggdrop.key) and a certificate (eggdrop.crt) after you fill in the
+    required fields.
+    To authenticate with a certificate instead of using password, you should
+    make a ssl certificate for yourself and enable ssl-cert-auth in the config
+    file. Then either connect to the bot using SSL and type ".fprint +" or
+    enter your certificate fingerprint with .fprint SHA1-FINGERPRINT.
+    To generate a ssl certificate for yourself, you can run the following
+    command from the eggdrop source directory:
+
+      openssl req -new -x509 -nodes -keyout my.key -out my.crt -config ssl.conf
+
+    When asked about bot's handle, put your handle instead. How to use your
+    new certificate to connect to eggdrop, depends on your irc client.
+    To connect to your bot from the command line, you can use the OpenSSL
+    ssl client:
+
+      openssl s_client -cert my.crt -key my.key -connect host:sslport 
+    
+
+  5. SSL Settings
+ 
+    There are some new settings allowing control over certificate
+    verification and authorization.
+
+       ssl-privatekey
+         file containing Eggdrop's private key, required for the certificate.
+
+       ssl-certificate
+         Specify the filename where your SSL certificate is located.
+         if your bot will accept SSL connections, it must have a certificate.
+
+       ssl-verify-depth
+         maximum verification depth when checking certificate validity.
+         Determines the maximum certificate chain length to allow.
+
+       ssl-capath
+       ssl-cafile
+         specify the location of certificate authorities certificates. These
+         are used for verification. Both can be active at the same time.
+         If you don't set this, validation of the issuer won't be possible and
+         depending on verification settings, the peer certificate might fail
+         verification.
+
+       ssl-ciphers
+         specify the list of ciphers (in order of preference) allowed for
+         use with ssl.
+
+       ssl-cert-auth
+         enables or disables certificate authorization for partyline/botnet.
+         This works only for SSL connections (SDCC or telnet over SSL).
+         A setting of 1 means optional authorization: If the user/bot has a
+         fingerprint set and it matches the certificate SHA1 fingerprint,
+         access is granted, otherwise ordinary password authentication takes
+         place.
+         If you set this to 2 however, users without a fingerprint set or
+         with a fingerprint not matching the certificate, will not be
+         allowed to enter the partyline with SSL. In addition to this user and
+         bot certificates will be required to have an UID field matching the
+         handle of the user/bot.
+
+       ssl-verify-dcc
+       ssl-verify-bots
+       ssl-verify-server
+       ssl-verify-clients
+         control ssl certificate verification. A value of 0 disables
+         verification completely. A value of 1 enables full verification.
+         Higher values enable specific exceptions like allowing self-signed
+         or expired certificates. Details are documented in eggdrop.conf.
+
+    _____________________________________________________________________
+	
+  Copyright (C) 2010 Eggheads Development Team
Index: eggdrop1.8/doc/html/egg-core.html
diff -u eggdrop1.8/doc/html/egg-core.html:1.2 eggdrop1.8/doc/html/egg-core.html:1.3
--- eggdrop1.8/doc/html/egg-core.html:1.2	Thu Aug  5 12:12:04 2010
+++ eggdrop1.8/doc/html/egg-core.html	Tue Oct 19 06:13:32 2010
@@ -1,5 +1,5 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<!-- $Id: egg-core.html,v 1.2 2010/08/05 18:12:04 pseudo Exp $ -->
+<!-- $Id: egg-core.html,v 1.3 2010/10/19 12:13:32 pseudo Exp $ -->
 
 <html>
   <head>
@@ -39,9 +39,11 @@
 
             <li><a href="#sect1g">More advanced settings</a></li>
 
-            <li><a href="#sect1h">Modules</a></li>
+            <li><a href="#sect1h">SSL settings</a></li>
 
-            <li><a href="#sect1i">Scripts</a></li>
+            <li><a href="#sect1i">Modules</a></li>
+
+            <li><a href="#sect1j">Scripts</a></li>
           </ol>
         </li>
       </ol>
@@ -596,6 +598,12 @@
             <p><strong>listen 3333 all</strong></p>
           </blockquote>
 
+          <p>You can setup a SSL port by prepending a plus sign to it:</p>
+
+          <blockquote>
+            <p><strong>listen +5555 all</strong></p>
+          </blockquote>
+
           <p>You need to un-comment this line and change the port number in
           order to open the listen port. You should not keep this set to
           3333.</p>
@@ -729,6 +737,7 @@
           prefix the host with a &quot;!&quot;.</p>
         </dd>
 
+
         <dt><strong>set nat-ip &quot;127.0.0.1&quot;</strong></dt>
 
         <dd>
@@ -894,7 +903,166 @@
       </dl>
     </blockquote>
 
-    <p><a name="sect1h"></a>1h. <strong>Modules</strong></p>
+    <p><a name="sect1h"></a>1h. <strong>SSL settings</strong></p>
+    
+    <blockquote>
+      <p>Settings in this section take effect when eggdrop is compiled with
+      TLS support.</p>
+      
+      <dl>
+        <dt><strong>set ssl-privatekey &quot;eggdrop.key&quot;</strong></dt>
+
+        <dd>
+          <p>Specifies a file containing your private key, needed for the
+          SSL certificate (see below). You can create one issuing the
+          following command:</p>
+          
+         <blockquote>
+<pre>
+openssl genrsa -out eggdrop.key 2048
+</pre>
+        </blockquote>
+
+         
+        <p>It will create a 2048 bit RSA key, strong enough for eggdrop.
+        This is required for SSL hubs/listen ports, secure file transfer and
+        /ctcp botnick schat
+        For your convenience, you can type 'make sslcert' after 'make
+        install' and you'll get a key and a certificate in your DEST
+        directory.</p>
+        </dd>
+
+        <dt><strong>set ssl-certificate &quot;eggdrop.crt&quot;</strong></dt>
+
+        <dd>
+          <p>Specifies the file where your SSL certificate is located. If
+          you don't set this, eggdrop will not be able to act as a server in
+          SSL connections, as with most ciphers a certificate and a private
+          key are required on the server side. Must be in PEM format.
+          If you don't have one, you can create it using the following
+          command:</p>
+          
+         <blockquote>
+<pre>
+openssl req -new -key eggdrop.key -x509 -out eggdrop.crt -days 365
+</pre>
+        </blockquote>
+
+         
+        <p>This is required for SSL hubs/listen ports, secure file transfer
+        and /ctcp botnick schat
+        For your convenience, you can type 'make sslcert' after 'make
+        install' and you'll get a key and a certificate in your DEST
+        directory.</p>
+        </dd>
+
+        <dt><strong>set ssl-verify-depth 9</strong></dt>
+
+        <dd>
+          <p>Sets the maximum depth for the certificate chain verification
+          that will be allowed for ssl. When certificate verification is
+          enabled, any chain exceeding this depth will fail verification.</p>
+        </dd>
+
+        <dt><strong>set ssl-cafile &quot;/etc/ssl/&quot;</strong></dt>
+
+        <dd>
+          <p>Specify the location where CA certificates for verification
+          purposes are located. These certificates are trusted. If you
+          don't set this or ssl-cafile, certificate verification will not
+          work.</p>
+        </dd>
+
+        <dt><strong>set ssl-cafile &quot;&quot;</strong></dt>
+
+        <dd>
+          <p>Specify a file which contains CA certificates for verification
+          purposes. These certificates are trusted. If you don't set this
+          or ssl-cafile, certificate verification will not work.</p>
+        </dd>
+
+        <dt><strong>set ssl-ciphers &quot;&quot;</strong></dt>
+
+        <dd>
+          <p>Specify the list of ciphers (in order of preference) allowed
+          for use with ssl. The cipher list is one or more cipher strings
+          separated by colons, commas or spaces. Unavailable ciphers are
+          silently ignored unless no useable cipher could be found. For the
+          list of possible cipher strings and their meanings, please refer
+          to the ciphers(1) manual.</p>
+          <p><strong>Note:</strong> if you set this, the value replaces any
+          ciphers OpenSSL might use by default. To include the default
+          ciphers, you can put DEFAULT as a cipher string in the list.</p>
+          
+          <p>Examples:</p>
+          
+          <blockquote>
+            <p><strong>set ssl-ciphers &quot;DEFAULT ADH&quot;</strong></p>
+          </blockquote>
+          
+          <p>This will make eggdrop allow the default OpenSSL selection plus
+          anonymous DH ciphers.</p>
+
+          <blockquote>
+            <p><strong>set ssl-ciphers &quot;ALL&quot;</strong></p>
+          </blockquote>
+          
+          <p>This will make eggdrop allow all ciphers supported by OpenSSL,
+          in a reasonable order.</p>
+        </dd>
+
+        <dt><strong>set ssl-cert-auth &quot;0&quot;</strong></dt>
+
+        <dd>
+          <p>Enable certificate authorization. Set to 1 to allow users and
+          bots to identify automatically by their certificate fingerprints.
+          Setting it to 2 to will force fingerprint logins. With a value of
+          2, users without a fingerprint set or with a certificate UID not
+          matching their handle won't be allowed to login on SSL enabled
+          telnet ports. Fingerprints must be set in advance with the .fprint
+          and .chfinger commands. Note that this setting has no effect on 
+          plain-text ports.</p>
+        </dd>
+
+        <p> You can control SSL certificate verification using the variables
+        below. All of them are flag-based. You can set them by adding
+        together the numbers for all exceptions you want to enable. By
+        default certificate verification is disabled and all certificates
+        are assumed to be valid.</p>
+
+        <p> The numbers are the following:<blockquote>
+          1  - enable certificate verification<br>
+          2  - allow self-signed certificates<br>
+          4  - don't check peer common or alt names<br>
+          8  - allow expired certificates<br>
+          16 - allow certificates which are not valid yet<br>
+          32 - allow revoked certificates<br>
+        </blockquote>A value of 0 disables verification.</p>
+
+        <dt><strong>set ssl-verify-dcc &quot;0&quot;</strong></dt>
+
+        <dd>
+          <p>Control certificate verification for DCC chats (only /dcc chat
+          botnick)</p>
+        </dd>
+
+        <dt><strong>set ssl-verify-bots &quot;0&quot;</strong></dt>
+
+        <dd>
+          <p>Control certificate verification for linking to hub bots</p>
+        </dd>
+
+        <dt><strong>set ssl-verify-clients &quot;0&quot;</strong></dt>
+
+        <dd>
+          <p>Control certificate verification for SSL listening ports.
+          This includes leaf bots connecting, users telneting in and
+          /ctcp bot chat.</p>
+        </dd>
+      </dl>
+    </blockquote>
+
+    <p><a name="sect1i"></a>1i. <strong>Modules</strong></p>
 
     <blockquote>
       <p>After the core settings, you should start loading modules. Modules
@@ -938,7 +1106,7 @@
       </dl>
     </blockquote>
 
-    <p><a name="sect1i"></a>1i. <strong>Scripts</strong></p>
+    <p><a name="sect1j"></a>1j. <strong>Scripts</strong></p>
 
     <blockquote>
       <p>The scripts section should be placed at the end of the config file.
Index: eggdrop1.8/doc/html/mod-server.html
diff -u eggdrop1.8/doc/html/mod-server.html:1.1.1.1 eggdrop1.8/doc/html/mod-server.html:1.2
--- eggdrop1.8/doc/html/mod-server.html:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/doc/html/mod-server.html	Tue Oct 19 06:13:32 2010
@@ -1,5 +1,5 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<!-- $Id: mod-server.html,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $ -->
+<!-- $Id: mod-server.html,v 1.2 2010/10/19 12:13:32 pseudo Exp $ -->
 
 <html>
   <head>
@@ -127,6 +127,7 @@
 <pre>
         you.need.to.change.this:6667
         another.example.com:7000:password
+        ssl.example.net:+6697
 </pre>
         <p><strong>}</strong></p>
 
@@ -141,9 +142,12 @@
           <p>set servers {<br>
            &nbsp; irc.netw.ork<br>
            &nbsp; irc.krow.ten:6668<br>
+           &nbsp; ssl.secu.re:+6697<br>
            }</p>
 
            <p>The format is: server[:port[:password]]</p>
+           <p>Prefix the port with a plus sign to attempt a SSL connection:
+           server:+port[:password]</p>
 
            <p>Both the port and password fields are optional; however, if you
            want to set a password you must also set a port. If a port isn&#39;t
Index: eggdrop1.8/doc/html/tcl-commands.html
diff -u eggdrop1.8/doc/html/tcl-commands.html:1.4 eggdrop1.8/doc/html/tcl-commands.html:1.5
--- eggdrop1.8/doc/html/tcl-commands.html:1.4	Sun Oct 10 12:22:47 2010
+++ eggdrop1.8/doc/html/tcl-commands.html	Tue Oct 19 06:13:32 2010
@@ -1,5 +1,5 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<!-- $Id: tcl-commands.html,v 1.4 2010/10/10 18:22:47 pseudo Exp $ -->
+<!-- $Id: tcl-commands.html,v 1.5 2010/10/19 12:13:32 pseudo Exp $ -->
 
 <html>
   <head>
@@ -3751,6 +3751,48 @@
           
           <p><strong>Module:</strong> core</p>
         </dd>
+
+
+        <dt><strong><a name="cmd_istls"></a>istls &lt;idx&gt;</strong></dt>*
+
+        <dd>
+          <p><strong>Description:</strong> checks if a connection is
+          encrypted or cleartext. This command is available on TLS-enabled
+          bots only.
+
+          <p><strong>Returns:</strong> 1 if the idx is a TLS connection, 0
+          if it's plaintext.</p>
+          
+          <p><strong>Module:</strong> core</p>
+        </dd>
+
+
+        <dt><strong><a name="cmd_starttls"></a>starttls &lt;idx&gt;</strong></dt>*
+
+        <dd>
+          <p><strong>Description:</strong> establishes a secure (using TLS)
+          connection over idx. The TLS connection should be first negotiated
+          over the plaintext link, or by other means. Both parties must switch
+          to TLS simultaneously.</p>
+
+          <p><strong>Returns:</strong> nothing</p>
+          
+          <p><strong>Module:</strong> core</p>
+        </dd>
+
+
+        <dt><strong><a name="cmd_tlsstatus"></a>tlsstatus &lt;idx&gt;</strong></dt>*
+
+        <dd>
+          <p><strong>Description:</strong> provides information about an
+          established TLS connection. This includes certificate and cipher
+          information as well as protocol version. This command is
+          available on TLS-enabled bots only.</p>
+
+          <p><strong>Returns:</strong> a flat list of name-value pairs</p>
+          
+          <p><strong>Module:</strong> core</p>
+        </dd>
       </dl>
     </blockquote>
 
Index: eggdrop1.8/doc/settings/core.settings
diff -u eggdrop1.8/doc/settings/core.settings:1.2 eggdrop1.8/doc/settings/core.settings:1.3
--- eggdrop1.8/doc/settings/core.settings:1.2	Thu Aug  5 12:12:04 2010
+++ eggdrop1.8/doc/settings/core.settings	Tue Oct 19 06:13:32 2010
@@ -1,4 +1,4 @@
-$Id: core.settings,v 1.2 2010/08/05 18:12:04 pseudo Exp $
+$Id: core.settings,v 1.3 2010/10/19 12:13:32 pseudo Exp $
 
 Eggdrop Core Settings
 Last revised: April 17, 2003
@@ -65,21 +65,20 @@
       If you don't want to use the timezone setting for scripting purposes
       only, but instead everywhere possible, then use this setting.
 
-
-    set vhost4 "virtual.host.com"
     set vhost4 "99.99.0.0"
+    set vhost4 "virtual.host.com"
       If you're using virtual hosting (your machine has more than 1 IP), you
       may want to specify the particular IP to bind to. You can specify either
-      by hostname or by IP. Note that this is not used for listening.  Use the
+      by hostname or by IP. Note that this is not used for listening. Use the
       'listen-addr' variable to specify the listening address.
 
 
     set vhost6 "2001:db8:618:5c0:263::"
     set vhost6 "my.ipv6.host.com"
-     IPv6 vhost to bind to for outgoing IPv6 connections. You can set it
-     to any valid IPv6 address or hostname, resolving to an IPv6 address.
-     Note that this is not used for listening. Use the 'listen-addr'
-     variable to specify the listening address.
+      IPv6 vhost to bind to for outgoing IPv6 connections. You can set it
+      to any valid IPv6 address or hostname, resolving to an IPv6 address.
+      Note that this is not used for listening. Use the 'listen-addr'
+      variable to specify the listening address.
 
 
     set listen-addr "99.99.0.0"
@@ -335,6 +334,10 @@
 
         listen 3333 all
 
+      You can setup a SSL port by prepending a plus sign to it:
+
+        listen +5555 all
+
       You need to un-comment this line and change the port number in order to
       open the listen port. You should not keep this set to 3333.
 
@@ -540,6 +543,109 @@
       Do NOT set this, if your network/server does not support cidr!
 
 
+  ##### SSL SETTINGS #####
+
+  Settings in this section take effect when eggdrop is compiled with TLS
+  support.
+
+
+    set ssl-privatekey "eggdrop.key"
+      File containing your private key, needed for the SSL certificate
+      (see below). You can create one issuing the following command:
+
+        openssl genrsa -out eggdrop.key 2048
+
+      It will create a 2048 bit RSA key, strong enough for eggdrop.
+      This is required for SSL hubs/listen ports, secure file transfer and
+      /ctcp botnick schat
+      For your convenience, you can type 'make sslcert' after 'make install'
+      and you'll get a key and a certificate in your DEST directory.
+
+
+    set ssl-certificate "eggdrop.crt"
+      Specify the filename where your SSL certificate is located. If you
+      don't set this, eggdrop will not be able to act as a server in SSL
+      connections, as with most ciphers a certificate and a private key
+      are required on the server side. Must be in PEM format.
+      If you don't have one, you can create it using the following command:
+
+        openssl req -new -key eggdrop.key -x509 -out eggdrop.crt -days 365
+
+      This is required for SSL hubs/listen ports, secure file transfer and
+      /ctcp botnick schat
+      For your convenience, you can type 'make sslcert' after 'make install'
+      and you'll get a key and a certificate in your DEST directory.
+
+
+    set ssl-verify-depth 9
+      Sets the maximum depth for the certificate chain verification that shall
+      be allowed for ssl. When certificate verification is enabled, any chain
+      exceeding this depth will fail verification.
+
+
+    set ssl-capath "/etc/ssl/"
+    set ssl-cafile ""
+      Specify the location at which CA certificates for verification purposes
+      are located. These certificates are trusted. If you don't set this,
+      certificate verification will not work.
+
+
+    set ssl-ciphers ""
+      Specify the list of ciphers (in order of preference) allowed for use with
+      ssl. The cipher list is one or more cipher strings separated by colons,
+      commas or spaces. Unavailable ciphers are silently ignored unless no
+      useable cipher could be found. For the list of possible cipher strings
+      and their meanings, please refer to the ciphers(1) manual.
+      Note: if you set this, the value replaces any ciphers OpenSSL might use by
+      default. To include the default ciphers, you can put DEFAULT as a cipher
+      string in the list.
+      For example:
+
+        set ssl-ciphers "DEFAULT ADH"
+
+      This will make eggdrop allow the default OpenSSL selection plus anonymous
+      DH ciphers.
+
+        set ssl-ciphers "ALL"
+
+      This will make eggdrop allow all ciphers supported by OpenSSL, in a
+      reasonable order.
+
+
+    set ssl-cert-auth 0
+      Enable certificate authorization. Set to 1 to allow users and bots to
+      identify automatically by their certificate fingerprints. Setting it
+      to 2 to will force fingerprint logins. With a value of 2, users without
+      a fingerprint set or with a certificate UID not matching their handle
+      won't be allowed to login on SSL enabled telnet ports. Fingerprints
+      must be set in advance with the .fprint and .chfinger commands.
+      NOTE: this setting has no effect on plain-text ports.
+
+    You can control SSL certificate verification using the following variables.
+    All of them are flag-based. You can set them by adding together the numbers
+    for all exceptions you want to enable. By default certificate verification
+    is disabled and all certificates are assumed to be valid.
+
+    The numbers are the following:
+      1  - enable certificate verification
+      2  - allow self-signed certificates
+      4  - don't check peer common or alt names
+      8  - allow expired certificates
+      16 - allow certificates which are not valid yet
+      32 - allow revoked certificates
+    A value of 0 disables verification.
+
+    set ssl-verify-dcc 0
+      Control certificate verification for DCC chats (only /dcc chat botnick)
+
+    set ssl-verify-bots 0
+      Control certificate verification for linking to hubs
+
+    set ssl-verify-clients 0
+      Control cerfificate verification for SSL listening ports. This includes
+      leaf bots connecting, users telneting in and /ctcp bot chat.
+
+
   ##### MODULES #####
 
   After the core settings, you should start loading modules. Modules are
Index: eggdrop1.8/doc/settings/mod.server
diff -u eggdrop1.8/doc/settings/mod.server:1.1.1.1 eggdrop1.8/doc/settings/mod.server:1.2
--- eggdrop1.8/doc/settings/mod.server:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/doc/settings/mod.server	Tue Oct 19 06:13:32 2010
@@ -1,4 +1,4 @@
-$Id: mod.server,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+$Id: mod.server,v 1.2 2010/10/19 12:13:32 pseudo Exp $
 
 Server Module
 Last revised: February 12, 2003
@@ -78,6 +78,7 @@
     set servers {
       you.need.to.change.this:6667
       another.example.com:7000:password
+      ssl.example.net:+6697
     }
       This is the bot's server list. The bot will start at the first server
       listed, and cycle through them whenever it gets disconnected. You need
@@ -85,6 +86,8 @@
 
       The format is:
         server[:port[:password]]
+      Prefix the port with a plus sign to attempt a SSL connection:
+        server:+port[:password]
 
       Both the port and password fields are optional; however, if you want to
       set a password you must also set a port. If a port isn't specified it
@@ -95,17 +98,36 @@
       Set the default port which should be used if none is specified with
       '.jump' or in 'set servers'.
 
+
     set msg-rate 2
       Number of seconds to wait between transmitting queued lines to the
       server. Lower this value at your own risk.  ircd is known to start
       flood control at 512 bytes/2 seconds.
 
+
+    set ssl-verify-servers 0
+      Control certificate verification for servers. You can set this by adding
+      together the numbers for all exceptions you want to enable. By default
+      certificate verification is disabled and all certificates are assumed to
+      be valid. The numbers are the following:
+      
+      The numbers are the following:
+        1  - enable certificate verification
+        2  - allow self-signed certificates
+        4  - don't check peer common or alt names
+        8  - allow expired certificates
+        16 - allow certificates which are not valid yet
+        32 - allow revoked certificates
+      A value of 0 disables verification.
+
+
     set server-cycle-wait 60
       This setting defines how long Eggdrop should wait before moving from one
       server to another on disconnect. If you set 0 here, Eggdrop will not wait
       at all and will connect instantly. Setting this too low could result in
       your bot being K:Lined.
 
+
     set never-give-up 1
       This settings makes the bot cycle forever through the server list until
       it successfully connects to one.
Index: eggdrop1.8/doc/tcl-commands.doc
diff -u eggdrop1.8/doc/tcl-commands.doc:1.3 eggdrop1.8/doc/tcl-commands.doc:1.4
--- eggdrop1.8/doc/tcl-commands.doc:1.3	Sun Oct 10 12:22:47 2010
+++ eggdrop1.8/doc/tcl-commands.doc	Tue Oct 19 06:13:32 2010
@@ -1,4 +1,4 @@
-$Id: tcl-commands.doc,v 1.3 2010/10/10 18:22:47 pseudo Exp $
+$Id: tcl-commands.doc,v 1.4 2010/10/19 12:13:32 pseudo Exp $
 
 Eggdrop Tcl Commands
 Last revised: November 23, 2009
@@ -804,9 +804,10 @@
     Returns: string of the type "+ntik key" for the channel specified
     Module: irc
 
-  jump [server [port [password]]]
+  jump [server [[+]port [password]]]
     Description: jumps to the server specified, or (if none is specified)
-      the next server in the bot's serverlist
+      the next server in the bot's serverlist. If you prefix the port with
+      a plus sign (e.g. +6697), SSL connection will be attempted.
     Returns: nothing
     Module: server
 
@@ -1028,16 +1029,19 @@
     Returns: nothing
     Module: core
 
-  connect <host> <port>
+  connect <host> <[+]port>
     Description: makes an outgoing connection attempt and creates a dcc
       entry for it. A 'control' command should be used immediately after
-      a successful 'connect' so no input is lost.
+      a successful 'connect' so no input is lost. If the port is prefixed
+      with a plus sign, SSL encrypted connection will be attempted.
     Returns: idx of the new connection
     Module: core
 
   listen <port> <type> [options] [flag]
     Description: opens a listening port to accept incoming telnets; type
-      must be one of "bots", "all", "users", "script", or "off":
+      must be one of "bots", "all", "users", "script", or "off".
+      Prefixing the port with a plus sign will make eggdrop accept SSL
+      connections on it.
 
         listen <port> bots [mask]
           Description: accepts connections from bots only; the optional mask
@@ -1608,6 +1612,27 @@
 |    Module: core
 
 
+| istls <idx>
+|  Description: checks if a connection is encrypted or cleartext. This
+|    command is available on TLS-enabled bots only.
+|  Returns: 1 if the idx is a TLS connection, 0 if it's plaintext.
+|  Module: core
+
+| starttls <idx>
+|  Description: establishes a secure (using TLS) connection over idx. The
+|    TLS connection should be first negotiated over the plaintext link,
+|    or using other means. Both parties must switch to TLS simultaneously.
+|    This command is available on TLS-enabled bots only.
+|  Returns: nothing
+|  Module: core
+
+| tlsstatus <idx>
+|  Description: provides information about an established TLS connection
+|    This includes certificate and cipher information as well as protocol
+|    version. This command is available on TLS-enabled bots only.
+|  Returns: a flat list of name-value pairs
+|  Module: core
+
 *** GLOBAL VARIABLES ***
 
   NOTE: All config file variables are also global.
Index: eggdrop1.8/eggdrop.conf
diff -u eggdrop1.8/eggdrop.conf:1.4 eggdrop1.8/eggdrop.conf:1.5
--- eggdrop1.8/eggdrop.conf:1.4	Mon Sep 27 13:38:11 2010
+++ eggdrop1.8/eggdrop.conf	Tue Oct 19 06:13:32 2010
@@ -1,7 +1,7 @@
 #! /path/to/executable/eggdrop
 # ^- This should contain a fully qualified path to your Eggdrop executable.
 #
-# $Id: eggdrop.conf,v 1.4 2010/09/27 19:38:11 pseudo Exp $
+# $Id: eggdrop.conf,v 1.5 2010/10/19 12:13:32 pseudo Exp $
 #
 # This is a sample Eggdrop configuration file which includes all possible
 # settings that can be used to configure your bot.
@@ -68,7 +68,7 @@
 # IPv4/IPv6 address (or hostname) to bind for listening. If you don't set
 # this variable, eggdrop will listen on all available IPv4 or IPv6 interfaces,
 # depending on the 'prefer-ipv6' variable (see below).
-# Note that eggdrop will accept IPv4 connecions with IPv6 sockets too.
+# Note that eggdrop will accept IPv4 connections with IPv6 sockets too.
 #set listen-addr "99.99.0.0"
 #set listen-addr "2001:db8:618:5c0:263::"
 #set listen-addr "virtual.host.com"
@@ -276,6 +276,10 @@
 #
 #   listen 3333 all
 #
+# You can setup a SSL port by prepending a plus sign to it:
+#
+#   listen +5555 all
+#
 # You need to un-comment this line and change the port number in order to open
 # the listen port. You should not keep this set to 3333.
 #listen 3333 all
@@ -342,6 +346,103 @@
 set resolve-timeout 7
 
 
+##### SSL SETTINGS #####
+
+# Settings in this section take effect when eggdrop is compiled with TLS
+# support.
+
+# File containing your private key, needed for the SSL certificate
+# (see below). You can create one issuing the following command:
+#
+#   openssl genrsa -out eggdrop.key 2048
+#
+# It will create a 2048 bit RSA key, strong enough for eggdrop.
+# This is required for SSL hubs/listen ports, secure file transfer and
+# /ctcp botnick schat
+# For your convenience, you can type 'make sslcert' after 'make install'
+# and you'll get a key and a certificate in your DEST directory.
+#set ssl-privatekey "eggdrop.key"
+
+# Specify the filename where your SSL certificate is located. If you
+# don't set this, eggdrop will not be able to act as a server in SSL
+# connections, as with most ciphers a certificate and a private key
+# are required on the server side. Must be in PEM format.
+# If you don't have one, you can create it using the following command:
+#
+#   openssl req -new -key eggdrop.key -x509 -out eggdrop.crt -days 365
+#
+# This is required for SSL hubs/listen ports, secure file transfer and
+# /ctcp botnick schat
+# For your convenience, you can type 'make sslcert' after 'make install'
+# and you'll get a key and a certificate in your DEST directory.
+#set ssl-certificate "eggdrop.crt"
+
+# Sets the maximum depth for the certificate chain verification that will
+# be allowed for ssl. When certificate verification is enabled, any chain
+# exceeding this depth will fail verification.
+#set ssl-verify-depth 9
+
+# Specify the location at which CA certificates for verification purposes
+# are located. These certificates are trusted. If you don't set this,
+# certificate verification will not work.
+set ssl-capath "/etc/ssl/"
+#set ssl-cafile ""
+
+# Specify the list of ciphers (in order of preference) allowed for use with
+# ssl. The cipher list is one or more cipher strings separated by colons,
+# commas or spaces. Unavailable ciphers are silently ignored unless no useable
+# cipher could be found. For the list of possible cipher strings and their
+# meanings, please refer to the ciphers(1) manual.
+# Note: if you set this, the value replaces any ciphers OpenSSL might use by
+# default. To include the default ciphers, you can put DEFAULT as a cipher
+# string in the list.
+# For example:
+#
+#   set ssl-ciphers "DEFAULT ADH"
+#
+# This will make eggdrop allow the default OpenSSL selection plus anonymous
+# DH ciphers.
+#
+#   set ssl-ciphers "ALL"
+#
+# This will make eggdrop allow all ciphers supported by OpenSSL, in a
+# reasonable order.
+#set ssl-ciphers ""
+
+# Enable certificate authorization. Set to 1 to allow users and bots to
+# identify automatically by their certificate fingerprints. Setting it
+# to 2 to will force fingerprint logins. With a value of 2, users without
+# a fingerprint set or with a certificate UID not matching their handle
+# won't be allowed to login on SSL enabled telnet ports. Fingerprints
+# must be set in advance with the .fprint and .chfinger commands.
+# NOTE: this setting has no effect on plain-text ports.
+#set ssl-cert-auth 0
+
+# You can control SSL certificate verification using the following variables.
+# All of them are flag-based. You can set them by adding together the numbers
+# for all exceptions you want to enable. By default certificate verification
+# is disabled and all certificates are assumed to be valid. The numbers are
+# the following:
+#
+# Enable certificate verification - 1
+# Allow self-signed certificates - 2
+# Don't check peer common or alt names - 4
+# Allow expired certificates - 8
+# Allow certificates which are not valid yet - 16
+# Allow revoked certificates - 32
+# A value of 0 disables verification.
+
+# Control certificate verification for DCC chats (only /dcc chat botnick)
+#set ssl-verify-dcc 0
+
+# Control certificate verification for linking to hubs
+#set ssl-verify-bots 0
+
+# Control cerfificate verification for SSL listening ports. This includes
+# leaf bots connecting, users telneting in and /ctcp bot chat.
+#set ssl-verify-clients 0
+
+
 ##### MORE ADVANCED SETTINGS #####
 
 # Set this to your socks host if your Eggdrop sits behind a firewall. If
@@ -837,6 +938,10 @@
 # to the old NO_IRC define.
 loadmodule server
 
+# Control certificate verification for irc servers. For a description of the
+# possible values, look at the SSL SETTINGS section above.
+#set ssl-verify-server 0
+
 # What is your network?
 #   0 = EFnet
 #   1 = IRCnet
@@ -877,6 +982,8 @@
 #
 # The format is:
 #   server[:port[:password]]
+# Prefix the port with a plus sign to attempt a SSL connection:
+#   server:+port[:password]
 # If you need to specify a numeric server IPv6 address, use following format:
 #   ip,[port[:password]]
 #
@@ -887,6 +994,7 @@
   you.need.to.change.this:6667
   another.example.com:7000:password
   2001:db8:618:5c0:263::,6669:password
+  ssl.example.net:+6697
 }
 
 # Number of seconds to wait between transmitting queued lines to the server.
Index: eggdrop1.8/help/cmds1.help
diff -u eggdrop1.8/help/cmds1.help:1.2 eggdrop1.8/help/cmds1.help:1.3
--- eggdrop1.8/help/cmds1.help:1.2	Thu Aug  5 12:12:04 2010
+++ eggdrop1.8/help/cmds1.help	Tue Oct 19 06:13:32 2010
@@ -1,10 +1,11 @@
 %{help=+bot}%{+t}
-###  %b+bot%b <handle> [address[:bot port[/user port]]] [host]
-###  %b+bot%b <handle> [IPv6 address[,bot port[/user port]]] [host]
+###  %b+bot%b <handle> [address[:[+]bot port[/[+]user port]]] [host]
+###  %b+bot%b <handle> [IPv6 address[,[+]bot port[/[+]user port]]] [host]
    Creates a user record for a new bot with the handle given. If no hostmask
    is specified, the bot will try to automatically add a host from the channel.
    The bot's address will be used in linking. If the bot has a separate port
-   for bots and users they should be separated with a slash (/).
+   for bots and users they should be separated with a slash (/). Prefixing
+   the port with a plus sign marks the bot for secure (SSL) linking.
 
 See also: -bot
 %{help=+host}%{+t|m}
@@ -151,11 +152,12 @@
 
 See also: bots, botinfo, vbottree
 %{help=chaddr}%{+t}
-###  %bchaddr%b <bot> <address[:bot port[/user port]]>
-###  %bchaddr%b <bot> <IPv6 address[,bot port[/user port]]>
+###  %bchaddr%b <bot> <address[:[+]bot port[/[+]user port]]>
+###  %bchaddr%b <bot> <IPv6 address[,[+]bot port[/[+]user port]]>
    Changes the address for a bot. This is the address your bot will try to
    connect to when linking. If the bot has a separate port for bots and users,
-   they should be separated  by a slash (/).
+   they should be separated  by a slash (/). Prefixing the port with a plus
+   sign marks the bot for secure (SSL) linking.
 
 See also: link, +bot
 %{help=chat}%{-}
Index: eggdrop1.8/help/core.help
diff -u eggdrop1.8/help/core.help:1.2 eggdrop1.8/help/core.help:1.3
--- eggdrop1.8/help/core.help:1.2	Thu Aug  5 12:12:04 2010
+++ eggdrop1.8/help/core.help	Tue Oct 19 06:13:32 2010
@@ -145,15 +145,19 @@
 userfile
 motd
 paranoid-telnet-flood
-vhost
+vhost4
+vhost6
+prefer-ipv6
+listen-addr
 telnet-banner
 admin
+userfile-perm
 use-telnet-banner
 temp-path
 notify-newusers
 owner
-my-hostname
 nat-ip
+cidr-support
 dcc-sanitycheck
 network
 whois-fields
@@ -188,14 +192,21 @@
 max-socks
 max-logs
 protect-telnet
-ident-timeout
+switch-logfiles-at
 share-unlinks
 allow-dk-cmds
-userfile-perm
-listen-addr
-switch-logfiles-at
-vhost6
-prefer-ipv6
+ident-timeout
+ssl-privatekey
+ssl-certificate
+ssl-privatekey
+ssl-certificate
+ssl-verify-depth
+ssl-capath
+ssl-cafile
+ssl-cert-auth
+ssl-verify-clients
+ssl-verify-bots
+ssl-verify-dcc
 %{end}
    Use %b'.help set <variable>'%b for more info on each variable.
 %{help=all}%{-}
Index: eggdrop1.8/help/set/cmds1.help
diff -u eggdrop1.8/help/set/cmds1.help:1.2 eggdrop1.8/help/set/cmds1.help:1.3
--- eggdrop1.8/help/set/cmds1.help:1.2	Thu Aug  5 12:12:04 2010
+++ eggdrop1.8/help/set/cmds1.help	Tue Oct 19 06:13:32 2010
@@ -28,9 +28,6 @@
 %{help=set owner}%{+n}
 ###  %bset owner%b <nickname-list>
    This is a list of owners of the bot.
-%{help=set my-hostname}%{+n}
-###  %bset my-hostname%b <hostname>
-   Set this if Eggdrop has trouble detecting its hostname.
 %{help=set vhost4}%{+n}
 ###  %bset vhost4%b <ipv4-address|hostname>
    If you're using virtual hosting (your machine has more than 1 IP),
@@ -289,3 +286,78 @@
    This specifies what permissions the user, channel, and notes
    files should be set to. The octal values are the same as for
    the chmod system command.
+%{help=set ssl-certificate}%{+n}
+###  %bset ssl-certificate%b <filename>
+   Specify the filename where your SSL certificate is located. If
+   you don't set this, eggdrop will not be able to act as a server
+   in SSL connections, as with most ciphers a certificate and a
+   private key are required on the server side. Must be in PEM
+   format.
+%{help=set ssl-privatekey}%{+n}
+###  %bset ssl-privatekey%b <filename>
+   File containing your private RSA key used for SSL connections.
+%{help=set ssl-verify-depth}%{+n}
+###  %bset ssl-verify-depth%b <depth>
+   Sets the maximum depth for the certificate chain verification
+   that will be allowed for ssl. When certificate verification is
+   enabled, any chain exceeding this depth will fail verification.
+%{help=set ssl-capath}%{+n}
+###  %bset ssl-capath%b <directory>
+   Specify the location where CA certificates for verification
+   purposes are located. These certificates are trusted. If you
+   don't set this or ssl-cafile, certificate verification will not
+   work.
+
+See also: ssl-cafile
+%{help=set ssl-cafile}%{+n}
+###  %bset ssl-cafile%b <filename>
+   Specify a file which contains CA certificates for verification
+   purposes. These certificates are trusted. If you don't set this
+   or ssl-capath, certificate verification will not work.
+
+See also: set ssl-capath
+%{help=set ssl-ciphers}%{+n}
+###  %bset ssl-ciphers%b <cipher list>
+   Specify the list of ciphers (in order of preference) allowed for
+   use with ssl. The cipher list is one or more cipher strings
+   separated by colons, commas or spaces. Unavailable ciphers are
+   silently ignored unless no useable cipher could be found. For the
+   list of possible cipher strings and their meanings, please refer
+   to the ciphers(1) manual.
+   If you set this, the value replaces any ciphers OpenSSL might use
+   by  default. To include the default ciphers, you can put DEFAULT
+   as a cipher string in the list.
+%{help=set ssl-cert-auth}%{+n}
+###  %bset ssl-cert-auth%b <0/1/2>
+   Enable certificate authorization. Set to 1 to allow users and bots
+   to identify automatically by their certificate fingerprints. Setting
+   it to 2 to will force fingerprint logins. With a value of 2, users
+   without a fingerprint set or with a certificate UID not matching
+   their handle won't be allowed to login on SSL enabled telnet ports.
+   Fingerprints must be set in advance with the .fprint and .chfinger
+   commands.
+   NOTE: this setting has no effect on plain-text ports.
+%{help=set ssl-verify-dcc}%{+n}
+###  %bset ssl-verify-dcc%b <#>
+   Control certificate verification for DCC chats (/dcc chat botnick)
+
+See also: set ssl-verify-clients
+%{help=set ssl-verify-bots}%{+n}
+###  %bset ssl-verify-bots%b <#>
+   Control certificate verification for linking to hubs
+
+See also: set ssl-verify-clients
+%{help=set ssl-verify-clients}%{+n}
+###  %bset ssl-verify-clients%b <#>
+   Control cerfificate verification for SSL listening ports. This includes
+   leaf bots connecting to us, users telneting in and /ctcp bot chat.
+   You can set this by adding together the numbers for all exceptions you
+   want to enable. By default certificate verification is disabled and all
+   certificates are assumed to be valid.
+   There are the following exceptions with their corresponding numbers:
+     1  enable certificate verification
+     2  allow self-signed certificates
+     4  don't check peer common or alt names
+     8  allow expired certificates
+     16 allow certificates which are not valid yet
+     32 allow revoked certificates
Index: eggdrop1.8/src/Makefile.in
diff -u eggdrop1.8/src/Makefile.in:1.1.1.1 eggdrop1.8/src/Makefile.in:1.2
--- eggdrop1.8/src/Makefile.in:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/Makefile.in	Tue Oct 19 06:13:32 2010
@@ -1,5 +1,5 @@
 # Makefile for src/
-# $Id: Makefile.in,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+# $Id: Makefile.in,v 1.2 2010/10/19 12:13:32 pseudo Exp $
 
 SHELL = @SHELL@
 top_srcdir = @top_srcdir@
@@ -15,13 +15,13 @@
 CC = @CC@
 LD = @CC@
 STRIP = @STRIP@
-CFLAGS = @CFLAGS@ -I.. -I$(top_srcdir) @DEFS@ $(CFLGS)
+CFLAGS = @CFLAGS@ -I.. -I$(top_srcdir) @SSL_INCLUDES@ @DEFS@ $(CFLGS)
 CPPFLAGS = @CPPFLAGS@
 
 eggdrop_objs = bg.o botcmd.o botmsg.o botnet.o chanprog.o cmds.o dcc.o \
 dccutil.o dns.o flags.o language.o match.o main.o mem.o misc.o misc_file.o \
 modules.o net.o rfc1459.o tcl.o tcldcc.o tclhash.o tclmisc.o tcluser.o \
-userent.o userrec.o users.o
+tls.o userent.o userrec.o users.o
 
 MAKE_GENERIC = $(MAKE) 'MAKE=$(MAKE)' 'CC=$(CC)' 'LD=$(LD)' \
 'STRIP=$(STRIP)' 'CFLGS=$(CFLGS)'
@@ -201,6 +201,10 @@
   compat/compat.h compat/inet_aton.h ../src/main.h compat/snprintf.h \
   compat/memset.h compat/memcpy.h compat/strcasecmp.h compat/strftime.h \
   tandem.h modules.h mod/modvals.h
+tls.o: tls.c main.h ../config.h ../lush.h lang.h eggdrop.h flags.h \
+  proto.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h users.h \
+  compat/compat.h compat/inet_aton.h ../src/main.h compat/snprintf.h \
+  compat/memset.h compat/memcpy.h compat/strcasecmp.h compat/strftime.h
 userent.o: userent.c main.h ../config.h ../lush.h lang.h eggdrop.h \
   flags.h proto.h misc_file.h cmdt.h tclegg.h tclhash.h chan.h users.h \
   compat/compat.h compat/inet_aton.h ../src/main.h compat/snprintf.h \
Index: eggdrop1.8/src/botcmd.c
diff -u eggdrop1.8/src/botcmd.c:1.1.1.1 eggdrop1.8/src/botcmd.c:1.2
--- eggdrop1.8/src/botcmd.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/botcmd.c	Tue Oct 19 06:13:32 2010
@@ -3,7 +3,7 @@
  *   commands that comes across the botnet
  *   userfile transfer and update commands from sharebots
  *
- * $Id: botcmd.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: botcmd.c,v 1.2 2010/10/19 12:13:32 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -32,6 +32,11 @@
 
 extern char botnetnick[], ver[], admin[], network[], motdfile[];
 extern int dcc_total, remote_boots, noshare;
+#ifdef TLS
+extern int tls_vfybots;
+extern int tls_vfyclients;
+extern SSL_CTX *ssl_ctx;
+#endif
 extern struct dcc_t *dcc;
 extern struct chanset_t *chanset;
 extern struct userrec *userlist;
@@ -1446,6 +1451,38 @@
   }
 }
 
+#ifdef TLS
+/* Negotiate an encrypted session over the existing link
+ * starttls
+ */
+static void bot_starttls(int idx, char *par)
+{
+  /* We're already using ssl, ignore the request */
+  if (dcc[idx].ssl)
+    return;
+
+  if (dcc[idx].status & STAT_STARTTLS) {
+    /* we requested ssl, now we got the reply */
+    dcc[idx].status &= ~STAT_STARTTLS;
+    ssl_handshake(dcc[idx].sock, TLS_CONNECT, tls_vfybots, LOG_BOTS,
+                  dcc[idx].host, NULL);
+  } else {
+    /* the peer requests ssl, tell it to go on */
+    /*
+      if (!SSL_CTX_check_private_key(ssl_ctx)) {
+      putlog(LOG_BOTS, "*", "%s", ERR_error_string(ERR_get_error()));
+      return;
+    }
+    */
+    dprintf(idx, "starttls\n");
+    putlog(LOG_BOTS, "*", "Got STARTTLS from %s. Replying...", dcc[idx].nick);
+    ssl_handshake(dcc[idx].sock, TLS_LISTEN, tls_vfybots, LOG_BOTS,
+                  dcc[idx].host, NULL);
+  }
+  dcc[idx].ssl = 1;
+}
+#endif
+
 /* BOT COMMANDS
  *
  * function call should be:
@@ -1531,6 +1568,9 @@
   {"reject",     (IntFunc) bot_reject},
 #endif
   {"s",          (IntFunc) bot_share},
+#ifdef TLS
+  {"starttls",   (IntFunc) bot_starttls},
+#endif
   {"t",          (IntFunc) bot_trace},
   {"tb",         (IntFunc) bot_thisbot},
   {"td",         (IntFunc) bot_traced},
Index: eggdrop1.8/src/botnet.c
diff -u eggdrop1.8/src/botnet.c:1.2 eggdrop1.8/src/botnet.c:1.3
--- eggdrop1.8/src/botnet.c:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/botnet.c	Tue Oct 19 06:13:33 2010
@@ -7,7 +7,7 @@
  *   linking, unlinking, and relaying to another bot
  *   pinging the bots periodically and checking leaf status
  *
- * $Id: botnet.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: botnet.c,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -44,7 +44,9 @@
 int parties = 0;                   /* Number of people on the botnet */
 char botnetnick[HANDLEN + 1] = ""; /* Botnet nickname */
 int share_unlinks = 0;             /* Allow remote unlinks of my sharebots? */
-
+#ifdef TLS
+int tls_vfybots = 0;               /* Verify SSL certificates from bots? */
+#endif
 
 int expmem_botnet()
 {
@@ -1031,6 +1033,9 @@
       i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
       dcc[i].timeval = now;
       dcc[i].port = bi->telnet_port;
+#ifdef TLS
+      dcc[i].ssl = bi->ssl;
+#endif
       dcc[i].user = u;
       strcpy(dcc[i].nick, nick);
       strcpy(dcc[i].host, bi->address);
@@ -1078,6 +1083,11 @@
   if (dcc[i].sock < 0 ||
       open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0)
     failed_link(i);
+#ifdef TLS
+  else if (dcc[i].ssl && ssl_handshake(dcc[i].sock, TLS_CONNECT,
+           tls_vfybots, LOG_BOTS, dcc[i].host, NULL))
+    failed_link(i);
+#endif
 }
 
 static void failed_tandem_relay(int idx)
@@ -1117,6 +1127,11 @@
   if (dcc[idx].sock < 0 ||
       open_telnet_raw(dcc[idx].sock, &dcc[idx].sockname) < 0)
     failed_tandem_relay(idx);
+#ifdef TLS
+  else if (dcc[idx].ssl && ssl_handshake(dcc[idx].sock, TLS_CONNECT,
+           tls_vfybots, LOG_BOTS, dcc[idx].host, NULL))
+    failed_tandem_relay(idx);
+#endif
 }
 
 
@@ -1162,6 +1177,9 @@
   }
 
   dcc[i].port = bi->relay_port;
+#ifdef TLS
+  dcc[i].ssl = bi->ssl;
+#endif
   dcc[i].addr = 0L;
   strcpy(dcc[i].nick, nick);
   dcc[i].user = u;
@@ -1248,6 +1266,11 @@
     dcc[i].sockname.addr.s4.sin_port = htons(dcc[i].port);
   if (open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0)
     failed_tandem_relay(i);
+#ifdef TLS
+  else if (dcc[i].ssl && ssl_handshake(dcc[i].sock, TLS_CONNECT,
+           tls_vfybots, LOG_BOTS, dcc[i].host, NULL))
+    failed_tandem_relay(i);
+#endif
 }
 
 /* Input from user before connect is ready
Index: eggdrop1.8/src/chanprog.c
diff -u eggdrop1.8/src/chanprog.c:1.3 eggdrop1.8/src/chanprog.c:1.4
--- eggdrop1.8/src/chanprog.c:1.3	Sun Oct 10 15:24:43 2010
+++ eggdrop1.8/src/chanprog.c	Tue Oct 19 06:13:33 2010
@@ -7,7 +7,7 @@
  *   telling the current programmed settings
  *   initializing a lot of stuff and loading the tcl scripts
  *
- * $Id: chanprog.c,v 1.3 2010/10/10 21:24:43 pseudo Exp $
+ * $Id: chanprog.c,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -52,6 +52,9 @@
 extern int backgrd, term_z, con_chan, cache_hit, cache_miss, firewallport,
            default_flags, max_logs, conmask, protect_readonly, make_userfile,
            noshare, ignore_time, max_socks;
+#ifdef TLS
+extern SSL_CTX *ssl_ctx;
+#endif
 
 tcl_timer_t *timer = NULL;         /* Minutely timer               */
 tcl_timer_t *utimer = NULL;        /* Secondly timer               */
@@ -365,6 +368,17 @@
 
   if (tcl_threaded())
     dprintf(idx, "Tcl is threaded.\n");
+#ifdef TLS
+  dprintf(idx, "TLS support is enabled.\n");
+  dprintf(idx, "TLS library: %s\n", SSLeay_version(SSLEAY_VERSION));
+#else
+  dprintf(idx, "TLS support is not available.\n");
+#endif
+#ifdef IPV6
+  dprintf(idx, "IPv6 support is enabled.\n");
+#else
+  dprintf(idx, "IPv6 support is not available.\n");
+#endif
   dprintf(idx, "Socket table: %d/%d\n", threaddata()->MAXSOCKS, max_socks);
 }
 
Index: eggdrop1.8/src/cmds.c
diff -u eggdrop1.8/src/cmds.c:1.2 eggdrop1.8/src/cmds.c:1.3
--- eggdrop1.8/src/cmds.c:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/cmds.c	Tue Oct 19 06:13:33 2010
@@ -3,7 +3,7 @@
  *   commands from a user via dcc
  *   (split in 2, this portion contains no-irc commands)
  *
- * $Id: cmds.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: cmds.c,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -805,11 +805,19 @@
     strncpy(bi->address, addr, q - addr);
     bi->address[q - addr] = 0;
     p = q + 1;
+#ifdef TLS
+    if (*p == '+')
+      bi->ssl = 1;
+#endif
     bi->telnet_port = atoi(p);
     q = strchr(p, '/');
     if (!q) {
       bi->relay_port = bi->telnet_port;
     } else  {
+#ifdef TLS
+      if (q[1] == '+')
+        bi->ssl = 1;
+#endif
       bi->relay_port = atoi(q + 1);
     }
   }
@@ -819,7 +827,7 @@
     dprintf(idx, "Added bot '%s' with address '%s' and %s%s%s.\n", handle,
             addr, host[0] ? "hostmask '" : "no hostmask", host[0] ? host : "",
             host[0] ? "'" : "");
-  } else{
+  } else {
     dprintf(idx, "Added bot '%s' with no address and %s%s%s.\n", handle,
             host[0] ? "hostmask '" : "no hostmask", host[0] ? host : "",
             host[0] ? "'" : "");
@@ -953,6 +961,73 @@
   }
 }
 
+#ifdef TLS
+static void cmd_fprint(struct userrec *u, int idx, char *par)
+{
+  char *new;
+
+  if (!par[0]) {
+    dprintf(idx, "Usage: fprint <newfingerprint|+>\n");
+    return;
+  }
+  new = newsplit(&par);
+  if (!strcmp(new, "+")) {
+    if (!dcc[idx].ssl) {
+      dprintf(idx, "You aren't connected with SSL. "
+              "Please set your fingerprint manually.\n");
+      return;
+    } else if (!(new = ssl_getfp(dcc[idx].sock))) {
+      dprintf(idx, "Can't get your current fingerprint. "
+              "Set up you client to send a certificate!\n");
+      return;
+    }
+  }
+  if (set_user(&USERENTRY_FPRINT, u, new)) {
+    putlog(LOG_CMDS, "*", "#%s# fprint...", dcc[idx].nick);
+    dprintf(idx, "Changed fingerprint to '%s'.\n", new);
+  } else
+    dprintf(idx, "Invalid fingerprint. Must be a hexadecimal string.\n");
+}
+
+static void cmd_chfinger(struct userrec *u, int idx, char *par)
+{
+  char *handle, *new;
+  int atr = u ? u->flags : 0;
+
+  if (!par[0])
+    dprintf(idx, "Usage: chfinger <handle> [fingerprint]\n");
+  else {
+    handle = newsplit(&par);
+    u = get_user_by_handle(userlist, handle);
+    if (!u)
+      dprintf(idx, "No such user.\n");
+    else if ((atr & USER_BOTMAST) && !(atr & USER_MASTER) &&
+             !(u->flags & USER_BOT))
+      dprintf(idx, "You can't change fingerprints for non-bots.\n");
+    else if ((bot_flags(u) & BOT_SHARE) && !(atr & USER_OWNER))
+      dprintf(idx, "You can't change a share bot's fingerprint.\n");
+    else if ((u->flags & USER_OWNER) && !(atr & USER_OWNER) &&
+             egg_strcasecmp(handle, dcc[idx].nick))
+      dprintf(idx, "You can't change a bot owner's fingerprint.\n");
+    else if (isowner(handle) && egg_strcasecmp(dcc[idx].nick, handle))
+      dprintf(idx, "You can't change a permanent bot owner's fingerprint.\n");
+    else if (!par[0]) {
+      putlog(LOG_CMDS, "*", "#%s# chfinger %s [nothing]", dcc[idx].nick, handle);
+      set_user(&USERENTRY_FPRINT, u, NULL);
+      dprintf(idx, "Removed fingerprint.\n");
+    } else {
+      new = newsplit(&par);
+      if (set_user(&USERENTRY_FPRINT, u, new)) {
+        putlog(LOG_CMDS, "*", "#%s# chfinger %s %s", dcc[idx].nick,
+               handle, new);
+        dprintf(idx, "Changed fingerprint.\n");
+      } else 
+        dprintf(idx, "Invalid fingerprint. Must be a hexadecimal string.\n");
+    }
+  }
+}
+#endif
+
 static void cmd_chaddr(struct userrec *u, int idx, char *par)
 {
   int telnet_port = 3333, relay_port = 3333;
@@ -992,6 +1067,9 @@
   }
 
   bi = user_malloc(sizeof(struct bot_addr));
+#ifdef TLS
+  bi->ssl = 0;
+#endif
 
 #ifdef IPV6
   if ((q = strchr(addr, ','))) {
@@ -1011,11 +1089,19 @@
     bi->address = user_malloc(q - addr + 1);
     strncpyz(bi->address, addr, q - addr + 1);
     p = q + 1;
+#ifdef TLS
+    if (*p == '+')
+      bi->ssl = 1;
+#endif
     bi->telnet_port = atoi(p);
     q = strchr(p, '/');
     if (!q) {
       bi->relay_port = bi->telnet_port;
     } else {
+#ifdef TLS
+    if (q[1] == '+')
+      bi->ssl = 1;
+#endif
       bi->relay_port = atoi(q + 1);
     }
   }
@@ -2804,6 +2890,9 @@
   {"chaddr",    "t",    (IntFunc) cmd_chaddr,     NULL},
   {"chat",      "",     (IntFunc) cmd_chat,       NULL},
   {"chattr",    "m|m",  (IntFunc) cmd_chattr,     NULL},
+#ifdef TLS
+  {"chfinger",  "t",    (IntFunc) cmd_chfinger,   NULL},
+#endif
   {"chhandle",  "t",    (IntFunc) cmd_chhandle,   NULL},
   {"chnick",    "t",    (IntFunc) cmd_chhandle,   NULL},
   {"chpass",    "t",    (IntFunc) cmd_chpass,     NULL},
@@ -2813,6 +2902,9 @@
   {"debug",     "m",    (IntFunc) cmd_debug,      NULL},
   {"die",       "n",    (IntFunc) cmd_die,        NULL},
   {"echo",      "",     (IntFunc) cmd_echo,       NULL},
+#ifdef TLS
+  {"fprint",    "",     (IntFunc) cmd_fprint,     NULL},
+#endif
   {"fixcodes",  "",     (IntFunc) cmd_fixcodes,   NULL},
   {"help",      "",     (IntFunc) cmd_help,       NULL},
   {"ignores",   "m",    (IntFunc) cmd_ignores,    NULL},
Index: eggdrop1.8/src/compat/Makefile.in
diff -u eggdrop1.8/src/compat/Makefile.in:1.2 eggdrop1.8/src/compat/Makefile.in:1.3
--- eggdrop1.8/src/compat/Makefile.in:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/compat/Makefile.in	Tue Oct 19 06:13:33 2010
@@ -1,5 +1,5 @@
 # Makefile for src/compat/
-# $Id: Makefile.in,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+# $Id: Makefile.in,v 1.3 2010/10/19 12:13:33 pseudo Exp $
 
 SHELL = @SHELL@
 top_srcdir = @top_srcdir@
@@ -15,7 +15,7 @@
 CC = @CC@
 LD = @CC@
 STRIP = @STRIP@
-CFLAGS = @CFLAGS@ -I../.. -I$(top_srcdir) -I$(top_srcdir)/src @DEFS@ $(CFLGS)
+CFLAGS = @CFLAGS@ -I../.. -I$(top_srcdir) -I$(top_srcdir)/src @SSL_INCLUDES@ @DEFS@ $(CFLGS)
 CPPFLAGS = @CPPFLAGS@
 
 OBJS = gethostbyname2.o in6.o inet_aton.o inet_ntop.o inet_pton.o snprintf.o \
Index: eggdrop1.8/src/dcc.c
diff -u eggdrop1.8/src/dcc.c:1.3 eggdrop1.8/src/dcc.c:1.4
--- eggdrop1.8/src/dcc.c:1.3	Tue Aug 31 12:21:47 2010
+++ eggdrop1.8/src/dcc.c	Tue Oct 19 06:13:33 2010
@@ -4,7 +4,7 @@
  *   disconnect on a dcc socket
  *   ...and that's it!  (but it's a LOT)
  *
- * $Id: dcc.c,v 1.3 2010/08/31 18:21:47 pseudo Exp $
+ * $Id: dcc.c,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -43,26 +43,30 @@
            make_userfile, default_flags, raw_log, ignore_time,
            par_telnet_flood;
 
-struct dcc_t *dcc = NULL;       /* DCC list                                */
-int dcc_total = 0;              /* Total dcc's                             */
-char tempdir[121] = "";         /* Temporary directory
-                                 * (default: current directory)            */
+struct dcc_t *dcc = NULL;       /* DCC list                                   */
+#ifdef TLS
+int tls_vfyclients = 0;		/* Certificate validation mode for clients    */
+int tls_vfydcc = 0;             /* Verify DCC chat/send user certificates     */
+int tls_auth = 0;               /* Allow certificate authentication           */
+#endif
+int dcc_total = 0;              /* Total dcc's                                */
 int require_p = 0;              /* Require 'p' access to get on the
-                                 * party line?                             */
+                                 * party line?                                */
 int allow_new_telnets = 0;      /* Allow people to introduce themselves
-                                 * via telnet                              */
-int stealth_telnets = 0;        /* Be paranoid? <cybah>                    */
-int use_telnet_banner = 0;      /* Display telnet banner?                  */
-char network[41] = "unknown-net";       /* Name of the IRC network you're on  */
-int password_timeout = 180;     /* Time to wait for a password from a user */
-int bot_timeout = 60;           /* Bot timeout value                       */
-int identtimeout = 5;           /* Timeout value for ident lookups         */
-int dupwait_timeout = 5;        /* Timeout for rejecting duplicate entries */
-int protect_telnet = 1;         /* Even bother with ident lookups :)       */
+                                 * via telnet                                 */
+int stealth_telnets = 0;        /* Be paranoid? <cybah>                       */
+int use_telnet_banner = 0;      /* Display telnet banner?                     */
+int password_timeout = 180;     /* Time to wait for a password from a user    */
+int bot_timeout = 60;           /* Bot timeout value                          */
+int identtimeout = 5;           /* Timeout value for ident lookups            */
+int dupwait_timeout = 5;        /* Timeout for rejecting duplicate entries    */
+int protect_telnet = 1;         /* Even bother with ident lookups :)          */
 int flood_telnet_thr = 5;       /* Number of telnet connections to be
-                                 * considered a flood                      */
-int flood_telnet_time = 60;     /* In how many seconds?                    */
-char bannerfile[121] = "text/banner";   /* File displayed on telnet login */
+                                 * considered a flood                         */
+int flood_telnet_time = 60;     /* In how many seconds?                       */
+char tempdir[121] = "";         /* Temporary directory (default: current dir) */
+char network[41] = "unknown-net";      /* Name of the IRC network you're on   */
+char bannerfile[121] = "text/banner";  /* File displayed on telnet login      */
 
 static void dcc_telnet_hostresolved(int);
 static void dcc_telnet_got_ident(int, char *);
@@ -245,6 +249,17 @@
   egg_snprintf(x, sizeof x, "v %d", dcc[idx].u.bot->numver);
   bot_share(idx, x);
   dprintf(idx, "el\n");
+#ifdef TLS
+  /* Ask the peer to switch to ssl communication. We'll continue
+   * using plain text, until it replies with stls itself. Bots which don't
+   * support it will simply ignore the request and everything goes on as usual.
+   */
+  if (dcc[idx].status & STAT_STARTTLS) {
+    dprintf(idx, "starttls\n");
+    putlog(LOG_BOTS, "*", "Sent STARTTLS to %s...", dcc[idx].nick);
+  }
+#endif
+
 }
 
 void failed_link(int idx)
@@ -311,6 +326,11 @@
       }
     }
   }
+  /* Indicate that we'd like to switch to tls later */
+#ifdef TLS
+  if (!dcc[idx].ssl)
+    dcc[idx].status |= STAT_STARTTLS;
+#endif
   dcc[idx].type = &DCC_BOT_NEW;
   dcc[idx].u.bot->numver = 0;
 
@@ -436,7 +456,7 @@
   int f;
 
   if (raw_log) {
-    if (code[0] == 's')
+    if (!strcmp(code, "s"))
       putlog(LOG_BOTSHARE, "*", "{%s} %s", dcc[idx].nick, code + 2);
     else
       putlog(LOG_BOTNET, "*", "[%s] %s", dcc[idx].nick, code);
@@ -597,7 +617,14 @@
     }
   }
 
+#ifdef TLS
+  /* Skip checking the password if the user is already identified by
+   * fingerprint.
+   */
+  if (dcc[idx].status & STAT_FPRINT || u_pass_match(dcc[idx].user, buf)) {
+#else
   if (u_pass_match(dcc[idx].user, buf)) {
+#endif
     if (atr & USER_BOT) {
       nfree(dcc[idx].u.chat);
       dcc[idx].type = &DCC_BOT_NEW;
@@ -1158,6 +1185,15 @@
   dcc[i].u.dns->ip = &dcc[i].sockname;
   dcc[i].sock = sock;
   dcc[i].port = port;
+#ifdef TLS
+  if (dcc[idx].ssl && ssl_handshake(sock, TLS_LISTEN, tls_vfyclients,
+      LOG_MISC, NULL, NULL)) {
+    killsock(sock);
+    lostdcc(i);
+    return;
+  }
+  dcc[i].ssl = dcc[idx].ssl;
+#endif
   dcc[i].timeval = now;
   strcpy(dcc[i].nick, "*");
   dcc[i].u.dns->dns_success = dcc_telnet_hostresolved;
@@ -1381,6 +1417,21 @@
   }
   dcc[idx].user = get_user_by_handle(userlist, buf);
   get_user_flagrec(dcc[idx].user, &fr, NULL);
+#ifdef TLS
+  if (dcc[idx].ssl && (tls_auth == 2)) {
+    char *uid = ssl_getuid(dcc[idx].sock);
+
+    if (!uid || strcasecmp(uid, buf)) {
+      if (glob_bot(fr))
+        dprintf(idx, "error Certificate UID doesn't match handle\n");
+      else
+        dprintf(idx, "Your certificate UID doesn't match your handle.\n");
+      killsock(dcc[idx].sock);
+      lostdcc(idx);
+      return;
+    }
+  }
+#endif
   /* Make sure users-only/bots-only connects are honored */
   if ((dcc[idx].status & STAT_BOTONLY) && !glob_bot(fr)) {
     dprintf(idx, "This telnet port is for bots only.\n");
@@ -1443,12 +1494,74 @@
   dcc_telnet_pass(idx, atr);
 }
 
+#ifdef TLS
+int dcc_fingerprint(idx)
+{
+  char *cf, *uf;
+  struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
+  
+  get_user_flagrec(dcc[idx].user, &fr, NULL);
+  /* Check if fingerprint authentication is allowed or required. */
+  if (dcc[idx].ssl && tls_auth) {
+    /* Get the fingerprint of the current certificate */
+    cf = ssl_getfp(dcc[idx].sock);
+    /* Get the fingerprint of the user, if set */
+    uf = get_user(&USERENTRY_FPRINT, dcc[idx].user);
+    if (cf && uf && !strcasecmp(cf, uf)) {
+      if (!glob_bot(fr))
+        dprintf(idx, "Used your fingerprint for automatic authentication.\n");
+      dcc[idx].status |= STAT_FPRINT;
+      dcc_chat_pass(idx, "+", 1);
+    /* Required? */
+    } else if (tls_auth == 2) {
+      if (glob_bot(fr))
+        dprintf(idx, "error fingerprint required\n");
+      else
+        dprintf(idx, "Certificate authentication required. "
+                "You need to set your fingerprint.\n");
+      killsock(dcc[idx].sock);
+      lostdcc(idx);
+    }
+    return 0;
+  }
+  return 1;
+}
+#endif
+
 static void dcc_telnet_pass(int idx, int atr)
 {
   int ok = 0;
   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
 
   get_user_flagrec(dcc[idx].user, &fr, NULL);
+#ifdef TLS
+  /* Check if fingerprint authentication is allowed or required. */
+  if (dcc[idx].ssl && tls_auth) {
+    char *cf, *uf;
+    
+    /* Get the fingerprint of the current certificate */
+    cf = ssl_getfp(dcc[idx].sock);
+    /* Get the fingerprint of the user, if set */
+    uf = get_user(&USERENTRY_FPRINT, dcc[idx].user);
+    if (cf && uf && !strcasecmp(cf, uf)) {
+      if (!glob_bot(fr))
+        dprintf(idx, "Used your fingerprint for automatic authentication.\n");
+      dcc[idx].status |= STAT_FPRINT;
+      dcc_chat_pass(idx, "+", 1);
+      return;
+    /* Required? */
+    } else if (tls_auth == 2) {
+      if (glob_bot(fr))
+        dprintf(idx, "error fingerprint required\n");
+      else
+        dprintf(idx, "Certificate authentication required. "
+                "You need to set your fingerprint.\n");
+      killsock(dcc[idx].sock);
+      lostdcc(idx);
+      return;
+    }
+  }
+#endif
   /* No password set? */
   if (u_pass_match(dcc[idx].user, "-")) {
     if (glob_bot(fr)) {
@@ -2090,6 +2203,7 @@
     lostdcc(i);
     return;
   }
+
   /* Script? */
   if (!strcmp(dcc[idx].nick, "(script)")) {
     dcc[i].type = &DCC_SOCKET;
Index: eggdrop1.8/src/dccutil.c
diff -u eggdrop1.8/src/dccutil.c:1.2 eggdrop1.8/src/dccutil.c:1.3
--- eggdrop1.8/src/dccutil.c:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/dccutil.c	Tue Oct 19 06:13:33 2010
@@ -6,7 +6,7 @@
  *   memory management for dcc structures
  *   timeout checking for dcc connections
  *
- * $Id: dccutil.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: dccutil.c,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -404,13 +404,13 @@
   if (j > 40)
     j = 40;
     
-  egg_snprintf(format, sizeof format, "%%-3s %%-%u.%us %%-5s %%-%u.%us %%s\n",
+  egg_snprintf(format, sizeof format, "%%-3s %%-%u.%us %%-6s %%-%u.%us %%s\n",
                j, j, nicklen, nicklen);
-  dprintf(zidx, format, "IDX", "ADDR", "PORT", "NICK", "TYPE  INFO");
+  dprintf(zidx, format, "IDX", "ADDR", "+ PORT", "NICK", "TYPE  INFO");
   dprintf(zidx, format, "---",
-          "------------------------------------------------------", "-----",
+          "------------------------------------------------------", "------",
           "--------------------------------", "----- ---------");
-  egg_snprintf(format, sizeof format, "%%-3d %%-%u.%us %%5d %%-%u.%us %%s\n",
+  egg_snprintf(format, sizeof format, "%%-3d %%-%u.%us %%c%%5d %%-%u.%us %%s\n",
                j, j, nicklen, nicklen);
 
   /* Show server */
@@ -421,8 +421,12 @@
       sprintf(other, "?:%lX  !! ERROR !!", (long) dcc[i].type);
       break;
     }
-      dprintf(zidx, format, dcc[i].sock, iptostr(&dcc[i].sockname.addr.sa), dcc[i].port,
-              dcc[i].nick, other);
+      dprintf(zidx, format, dcc[i].sock, iptostr(&dcc[i].sockname.addr.sa),
+#ifdef TLS
+              dcc[i].ssl ? '+' : ' ', dcc[i].port, dcc[i].nick, other);
+#else
+              ' ', dcc[i].port, dcc[i].nick, other);
+#endif
   }
 }
 
Index: eggdrop1.8/src/eggdrop.h
diff -u eggdrop1.8/src/eggdrop.h:1.5 eggdrop1.8/src/eggdrop.h:1.6
--- eggdrop1.8/src/eggdrop.h:1.5	Thu Oct 14 03:49:47 2010
+++ eggdrop1.8/src/eggdrop.h	Tue Oct 19 06:13:33 2010
@@ -4,7 +4,7 @@
  *
  *   IF YOU ALTER THIS FILE, YOU NEED TO RECOMPILE THE BOT.
  *
- * $Id: eggdrop.h,v 1.5 2010/10/14 09:49:47 pseudo Exp $
+ * $Id: eggdrop.h,v 1.6 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -274,6 +274,10 @@
 typedef int socklen_t;
 #endif
 
+#ifdef TLS
+#  include <openssl/ssl.h>
+#endif
+
 /*
  *    Handy aliases for memory tracking and core dumps
  */
@@ -389,8 +393,11 @@
 struct dcc_t {
   long sock;                    /* This should be a long to keep 64-bit machines sane. */
   IP addr;                      /* IP address in host network byte order. */
-  sockname_t sockname;          /* IPv4/IPv6 sockaddr placeholder */ 
+  sockname_t sockname;          /* IPv4/IPv6 sockaddr placeholder */
   unsigned int port;
+#ifdef TLS
+  int ssl;
+#endif
   struct userrec *user;
   char nick[NICKLEN];
   char host[UHOSTLEN];
@@ -536,8 +543,8 @@
 
 /* For dcc chat & files. */
 #define STAT_ECHO    0x00001    /* echo commands back?                  */
-#define STAT_DENY    0x00002    /* bad username (ignore password & deny
-                                 * access)                              */
+#define STAT_FPRINT  0x00002    /* fingerprint auth (ignore password &
+                                 * allow access)                        */
 #define STAT_CHAT    0x00004    /* in file-system but may return        */
 #define STAT_TELNET  0x00008    /* connected via telnet                 */
 #define STAT_PARTY   0x00010    /* only on party line via 'p' flag      */
@@ -566,6 +573,9 @@
 #define STAT_LINKING 0x00100    /* the bot is currently going through
                                  * the linking stage                     */
 #define STAT_AGGRESSIVE 0x00200 /* aggressively sharing with this bot    */
+#ifdef TLS
+#define STAT_STARTTLS   0x00400 /* have we sent a starttls request?      */
+#endif
 
 /* Flags for listening sockets */
 #define LSTN_PUBLIC  0x000001   /* No access restrictions               */
@@ -690,6 +700,30 @@
 #define HELP_TEXT       2
 #define HELP_IRC        16
 
+#ifdef TLS
+/* TLS generic flags */
+#  define TLS_LISTEN            0x80000000
+#  define TLS_CONNECT           0x40000000
+#  define TLS_DEPTH0            0x20000000
+
+/* TLS verification flags */
+#  define TLS_VERIFYPEER        0x00000001
+#  define TLS_VERIFYCN         	0x00000002
+#  define TLS_VERIFYISSUER      0x00000004
+#  define TLS_VERIFYFROM        0x00000008
+#  define TLS_VERIFYTO          0x00000010
+#  define TLS_VERIFYREV         0x00000020
+
+/* Context information to attach to SSL sockets */
+typedef struct {
+  int flags;			/* listen/connect, generic ssl flags      */
+  int verify;			/* certificate validation mode            */
+  int loglevel;			/* log level to output TLS information to */
+  char host[256];		/* host or IP for certificate validation  */
+  IntFunc cb;
+} ssl_appdata;
+#endif /* TLS */
+
 /* These are used by the net module to keep track of sockets and what's
  * queued on them
  */
@@ -708,6 +742,9 @@
 
 typedef struct sock_list {
   int sock;
+#ifdef TLS
+  SSL *ssl;
+#endif
   short flags;
   union {
     struct sock_handler sock;
Index: eggdrop1.8/src/main.c
diff -u eggdrop1.8/src/main.c:1.3 eggdrop1.8/src/main.c:1.4
--- eggdrop1.8/src/main.c:1.3	Sun Oct 10 15:24:43 2010
+++ eggdrop1.8/src/main.c	Tue Oct 19 06:13:33 2010
@@ -5,7 +5,7 @@
  *   command line arguments
  *   context and assert debugging
  *
- * $Id: main.c,v 1.3 2010/10/10 21:24:43 pseudo Exp $
+ * $Id: main.c,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -164,6 +164,9 @@
 int cx_ptr = 0;
 #endif
 
+#ifdef TLS
+int ssl_cleanup();
+#endif
 
 void fatal(const char *s, int recoverable)
 {
@@ -174,6 +177,9 @@
   for (i = 0; i < dcc_total; i++)
     if (dcc[i].sock >= 0)
       killsock(dcc[i].sock);
+#ifdef TLS
+  ssl_cleanup();
+#endif
   unlink(pid_file);
   if (!recoverable) {
     bg_send_quit(BG_ABORT);
@@ -193,6 +199,10 @@
 int expmem_language();
 int expmem_tcldcc();
 int expmem_tclmisc();
+int expmem_dns();
+#ifdef TLS
+int expmem_tls();
+#endif
 
 /* For mem.c : calculate memory we SHOULD be using
  */
@@ -203,7 +213,10 @@
   tot = expmem_chanprog() + expmem_users() + expmem_misc() + expmem_dccutil() +
         expmem_botnet() + expmem_tcl() + expmem_tclhash() + expmem_net() +
         expmem_modules(0) + expmem_language() + expmem_tcldcc() +
-        expmem_tclmisc();
+        expmem_tclmisc() + expmem_dns();
+#ifdef TLS 
+  tot += expmem_tls();
+#endif
   return tot;
 }
 
@@ -695,6 +708,9 @@
 int init_modules();
 int init_tcl(int, char **);
 int init_language(int);
+#ifdef TLS
+int ssl_init();
+#endif
 
 static void patch(const char *str)
 {
@@ -904,6 +920,10 @@
       }
 
       rehash();
+#ifdef TLS
+      ssl_cleanup();
+      ssl_init();
+#endif
       restart_chons();
       call_hook(HOOK_LOADED);
     }
@@ -1063,6 +1083,9 @@
     i++;
   putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.",
          botnetnick, i, count_users(userlist));
+#ifdef TLS
+  ssl_init();
+#endif
   cache_miss = 0;
   cache_hit = 0;
   if (!pid_file[0])
Index: eggdrop1.8/src/md5/Makefile.in
diff -u eggdrop1.8/src/md5/Makefile.in:1.1.1.1 eggdrop1.8/src/md5/Makefile.in:1.2
--- eggdrop1.8/src/md5/Makefile.in:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/md5/Makefile.in	Tue Oct 19 06:13:33 2010
@@ -1,5 +1,5 @@
 # Makefile for src/md5/
-# $Id: Makefile.in,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+# $Id: Makefile.in,v 1.2 2010/10/19 12:13:33 pseudo Exp $
 
 SHELL = @SHELL@
 top_srcdir = @top_srcdir@
@@ -15,7 +15,7 @@
 CC = @CC@
 LD = @CC@
 STRIP = @STRIP@
-CFLAGS = @CFLAGS@ -I. -I../.. -I$(top_srcdir) -I$(top_srcdir)/src @DEFS@ $(CFLGS)
+CFLAGS = @CFLAGS@ -I. -I../.. -I$(top_srcdir) -I$(top_srcdir)/src @SSL_INCLUDES@ @DEFS@ $(CFLGS)
 CPPFLAGS = @CPPFLAGS@
 
 OBJS = md5c.o
Index: eggdrop1.8/src/md5/md5.h
diff -u eggdrop1.8/src/md5/md5.h:1.1.1.1 eggdrop1.8/src/md5/md5.h:1.2
--- eggdrop1.8/src/md5/md5.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/md5/md5.h	Tue Oct 19 06:13:33 2010
@@ -9,6 +9,10 @@
 #ifndef _MD5_H
 #define _MD5_H
 
+#ifdef HAVE_OPENSSL_MD5
+#  include <openssl/md5.h>
+#else
+
 /* Any 32-bit or wider integer data type will do */
 typedef unsigned long MD5_u32plus;
 
@@ -23,4 +27,5 @@
 extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
 extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
 
-#endif
+#endif /* HAVE_OPENSSL_MD5 */
+#endif /* _MD5_H */
Index: eggdrop1.8/src/md5/md5c.c
diff -u eggdrop1.8/src/md5/md5c.c:1.1.1.1 eggdrop1.8/src/md5/md5c.c:1.2
--- eggdrop1.8/src/md5/md5c.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/md5/md5c.c	Tue Oct 19 06:13:33 2010
@@ -20,6 +20,7 @@
 #include "md5.h"
 #include "compat/compat.h"
 
+#ifndef HAVE_OPENSSL_MD5
 /*
  * The basic MD5 functions.
  *
@@ -269,3 +270,4 @@
 
 	egg_memset(ctx, 0, sizeof(ctx));
 }
+#endif /* HAVE_OPENSSL_MD5 */
Index: eggdrop1.8/src/mem.c
diff -u eggdrop1.8/src/mem.c:1.1.1.1 eggdrop1.8/src/mem.c:1.2
--- eggdrop1.8/src/mem.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mem.c	Tue Oct 19 06:13:33 2010
@@ -3,7 +3,7 @@
  *   memory allocation and deallocation
  *   keeping track of what memory is being used by whom
  *
- * $Id: mem.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: mem.c,v 1.2 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -66,7 +66,9 @@
 int expmem_language();
 int expmem_tcldcc();
 int expmem_dns();
-
+#ifdef TLS
+int expmem_tls();
+#endif
 
 /* Initialize the memory structure
  */
@@ -117,7 +119,11 @@
 void debug_mem_to_dcc(int idx)
 {
 #ifdef DEBUG_MEM
-#  define MAX_MEM 13
+#  ifdef TLS
+#    define MAX_MEM 14
+#  else
+#    define MAX_MEM 13
+#  endif
   unsigned long exp[MAX_MEM], use[MAX_MEM], l;
   int i, j;
   char fn[20], sofar[81];
@@ -137,6 +143,9 @@
   exp[10] = expmem_modules(1);
   exp[11] = expmem_tcldcc();
   exp[12] = expmem_dns();
+#ifdef TLS
+  exp[13] = expmem_tls();
+#endif
 
   for (me = module_list; me; me = me->next)
     me->mem_work = 0;
@@ -176,6 +185,10 @@
       use[11] += l;
     else if (!strcmp(fn, "dns.c"))
       use[12] += l;
+#ifdef TLS
+    else if (!strcmp(fn, "tls.c"))
+      use[13] += l;
+#endif
     else if (p) {
       for (me = module_list; me; me = me->next)
         if (!strcmp(fn, me->name))
@@ -225,6 +238,11 @@
     case 12:
       strcpy(fn, "dns.c");
       break;
+#ifdef TLS
+    case 13:
+      strcpy(fn, "tls.c");
+      break;
+#endif
     }
 
     if (use[i] == exp[i])
Index: eggdrop1.8/src/mod/Makefile.in
diff -u eggdrop1.8/src/mod/Makefile.in:1.2 eggdrop1.8/src/mod/Makefile.in:1.3
--- eggdrop1.8/src/mod/Makefile.in:1.2	Sun Oct 10 15:24:43 2010
+++ eggdrop1.8/src/mod/Makefile.in	Tue Oct 19 06:13:33 2010
@@ -1,5 +1,5 @@
 # Makefile for src/mod/
-# $Id: Makefile.in,v 1.2 2010/10/10 21:24:43 pseudo Exp $
+# $Id: Makefile.in,v 1.3 2010/10/19 12:13:33 pseudo Exp $
 
 SHELL = @SHELL@
 top_srcdir = @top_srcdir@
@@ -16,10 +16,10 @@
 CC = @CC@
 LD = @CC@
 STRIP = @STRIP@
-CFLAGS = @CFLAGS@ -I../.. -I$(top_srcdir) @DEFS@ $(CFLGS)
+CFLAGS = @CFLAGS@ -I../.. -I$(top_srcdir) @SSL_INCLUDES@ @DEFS@ $(CFLGS)
 CPPFLAGS = @CPPFLAGS@
 MOD_CFLAGS = @CFLAGS@ -I. -I../../.. -I$(MOD_UPDIR)$(top_srcdir) \
-  -I$(MOD_UPDIR)$(top_srcdir)/src/mod @DEFS@ $(CFLGS)
+  -I$(MOD_UPDIR)$(top_srcdir)/src/mod @SSL_INCLUDES@ @DEFS@ $(CFLGS)
 MOD_CPPFLAGS = @CPPFLAGS@
 XLIBS = @XLIBS@
 MOD_EXT = @MOD_EXT@
Index: eggdrop1.8/src/mod/ctcp.mod/ctcp.c
diff -u eggdrop1.8/src/mod/ctcp.mod/ctcp.c:1.3 eggdrop1.8/src/mod/ctcp.mod/ctcp.c:1.4
--- eggdrop1.8/src/mod/ctcp.mod/ctcp.c:1.3	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/mod/ctcp.mod/ctcp.c	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * ctcp.c -- part of ctcp.mod
  *   all the ctcp handling (except DCC, it's special ;)
  *
- * $Id: ctcp.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: ctcp.c,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -146,6 +146,9 @@
   struct userrec *u = get_user_by_handle(userlist, handle);
   int atr = u ? u->flags : 0, i;
   char s[INET6_ADDRSTRLEN];
+#ifdef TLS
+  int ssl = 0;
+#endif
 
   if ((atr & (USER_PARTY | USER_XFER)) || ((atr & USER_OP) && !require_p)) {
 
@@ -155,20 +158,37 @@
       return 1;
     }
 
+#ifdef TLS
+    if (!egg_strcasecmp(keyword, "SCHAT"))
+      ssl = 1;
+#endif
     for (i = 0; i < dcc_total; i++) {
       if ((dcc[i].type->flags & DCT_LISTEN) &&
+#ifdef TLS
+          (ssl == dcc[i].ssl) &&
+#endif
           (!strcmp(dcc[i].nick, "(telnet)") ||
            !strcmp(dcc[i].nick, "(users)")) &&
           getdccaddr(&dcc[i].sockname, s, sizeof s)) {
         /* Do me a favour and don't change this back to a CTCP reply,
          * CTCP replies are NOTICE's this has to be a PRIVMSG
          * -poptix 5/1/1997 */
+#ifdef TLS
+	  dprintf(DP_SERVER, "PRIVMSG %s :\001DCC %sCHAT chat %s %u\001\n",
+		  nick, (ssl ? "S" : ""), s, dcc[i].port);
+#else
           dprintf(DP_SERVER, "PRIVMSG %s :\001DCC CHAT chat %s %u\001\n",
                   nick, s, dcc[i].port);
+#endif
         return 1;
       }
     }
+#ifdef TLS
+    simple_sprintf(ctcp_reply, "%s\001ERROR no %stelnet port\001", ctcp_reply,
+	 	   (ssl ? "SSL enabled " : ""));
+#else
     simple_sprintf(ctcp_reply, "%s\001ERROR no telnet port\001", ctcp_reply);
+#endif
   }
   return 1;
 }
@@ -183,6 +203,9 @@
   {"CLIENTINFO", "",   ctcp_CLIENTINFO, NULL},
   {"TIME",       "",   ctcp_TIME,       NULL},
   {"CHAT",       "",   ctcp_CHAT,       NULL},
+#ifdef TLS
+  {"SCHAT",      "",   ctcp_CHAT,       NULL},
+#endif
   {NULL,         NULL, NULL,            NULL}
 };
 
Index: eggdrop1.8/src/mod/filesys.mod/filedb3.c
diff -u eggdrop1.8/src/mod/filesys.mod/filedb3.c:1.2 eggdrop1.8/src/mod/filesys.mod/filedb3.c:1.3
--- eggdrop1.8/src/mod/filesys.mod/filedb3.c:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/mod/filesys.mod/filedb3.c	Tue Oct 19 06:13:33 2010
@@ -4,7 +4,7 @@
  *
  * Rewritten by Fabian Knittel <fknittel at gmx.de>
  *
- * $Id: filedb3.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: filedb3.c,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
Index: eggdrop1.8/src/mod/filesys.mod/filesys.c
diff -u eggdrop1.8/src/mod/filesys.mod/filesys.c:1.3 eggdrop1.8/src/mod/filesys.mod/filesys.c:1.4
--- eggdrop1.8/src/mod/filesys.mod/filesys.c:1.3	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/mod/filesys.mod/filesys.c	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * filesys.c -- part of filesys.mod
  *   main file of the filesys eggdrop module
  *
- * $Id: filesys.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: filesys.c,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -633,7 +633,11 @@
 /* Received a ctcp-dcc.
  */
 static void filesys_dcc_send(char *nick, char *from, struct userrec *u,
+#ifdef TLS
+                             char *text, int ssl)
+#else
                              char *text)
+#endif
 {
   char *param, *ip, *prt, *buf = NULL, *msg;
   int atr = u ? u->flags : 0, i, j = 0;
@@ -701,6 +705,9 @@
       (void) setsockname(&dcc[i].sockname, ip, dcc[i].port, 0);
       dcc[i].u.dns->ip = &dcc[i].sockname;
       dcc[i].sock = -1;
+#ifdef TLS
+      dcc[i].ssl = ssl;
+#endif
       dcc[i].user = u;
       strcpy(dcc[i].nick, nick);
       strcpy(dcc[i].host, from);
@@ -825,6 +832,11 @@
       if (dcc[i].sock < 0 ||
       open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0)
         dcc[i].type->eof(i);
+#ifdef TLS
+      else if (dcc[i].ssl && ssl_handshake(dcc[i].sock, TLS_CONNECT, tls_vfydcc,
+                                           LOG_FILES, dcc[i].host, NULL))
+        dcc[i].type->eof(i);
+#endif
     }
   }
 }
@@ -842,9 +854,19 @@
   if (egg_strcasecmp(object, botname))
     return 0;
   if (!egg_strncasecmp(text, "SEND ", 5)) {
+#ifdef TLS
+    filesys_dcc_send(nick, from, u, text + 5, 0);
+#else
     filesys_dcc_send(nick, from, u, text + 5);
+#endif
     return 1;
   }
+#ifdef TLS
+  if (!egg_strncasecmp(text, "SSEND ", 5)) {
+    filesys_dcc_send(nick, from, u, text + 5, 1);
+    return 1;
+  }
+#endif
   if (egg_strncasecmp(text, "CHAT ", 5) || !u)
     return 0;
   strcpy(buf, text + 5);
Index: eggdrop1.8/src/mod/irc.mod/help/msg/irc.help
diff -u eggdrop1.8/src/mod/irc.mod/help/msg/irc.help:1.1.1.1 eggdrop1.8/src/mod/irc.mod/help/msg/irc.help:1.2
--- eggdrop1.8/src/mod/irc.mod/help/msg/irc.help:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/irc.mod/help/msg/irc.help	Tue Oct 19 06:13:33 2010
@@ -33,8 +33,8 @@
 %b/MSG%b %B %bINVITE%b <password> <channel>
 This will invite you to a channel (if the bot is on the specified channel).
 %{help=jump}%{+m}
-%b/MSG%b %B %bJUMP%b <password> [server [port [server password]]]
-This will make the bot jump to a new server. You can optionally specify a server to jump to, in the form of 'new.server.com' or 'new.server.com 6667', etc.
+%b/MSG%b %B %bJUMP%b <password> [server [[+]port [server password]]]
+This will make the bot jump to a new server. You can optionally specify a server to jump to, in the form of 'new.server.com' or 'new.server.com 6667', etc. Prefix the port with '+' for SSL.
 %{help=memory}%{+m}
 %b/MSG%b %B %bMEMORY%b <password>
 This displays the bot's memory usage information.
Index: eggdrop1.8/src/mod/irc.mod/msgcmds.c
diff -u eggdrop1.8/src/mod/irc.mod/msgcmds.c:1.1.1.1 eggdrop1.8/src/mod/irc.mod/msgcmds.c:1.2
--- eggdrop1.8/src/mod/irc.mod/msgcmds.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/irc.mod/msgcmds.c	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * msgcmds.c -- part of irc.mod
  *   all commands entered via /MSG
  *
- * $Id: msgcmds.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: msgcmds.c,v 1.2 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1075,6 +1075,9 @@
 static int msg_jump(char *nick, char *host, struct userrec *u, char *par)
 {
   char *s;
+#ifdef TLS
+  char *sport;
+#endif
   int port;
 
   if (match_my_nick(nick))
@@ -1090,11 +1093,26 @@
   if (u_pass_match(u, s)) {
     if (par[0]) {
       s = newsplit(&par);
+#ifdef TLS
+      sport = newsplit(&par);
+      if (*sport == '+')
+        use_ssl = 1;
+      else
+        use_ssl = 0;
+      port = atoi(sport);
+      if (!port) {
+        port = default_port;
+        use_ssl = 0;
+      }
+      putlog(LOG_CMDS, "*", "(%s!%s) !%s! JUMP %s %s%d %s", nick, host,
+             u->handle, s, use_ssl ? "+" : "", port, par);
+#else
       port = atoi(newsplit(&par));
       if (!port)
         port = default_port;
       putlog(LOG_CMDS, "*", "(%s!%s) !%s! JUMP %s %d %s", nick, host,
              u->handle, s, port, par);
+#endif
       strcpy(newserver, s);
       newserverport = port;
       strcpy(newserverpass, par);
Index: eggdrop1.8/src/mod/module.h
diff -u eggdrop1.8/src/mod/module.h:1.2 eggdrop1.8/src/mod/module.h:1.3
--- eggdrop1.8/src/mod/module.h:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/mod/module.h	Tue Oct 19 06:13:33 2010
@@ -1,7 +1,7 @@
 /*
  * module.h
  *
- * $Id: module.h,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: module.h,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -195,6 +195,9 @@
 #define answer ((int (*) (int, sockname_t *, unsigned short *, int))global[76])
 #define getvhost ((void (*) (sockname_t *, int))global[77])
 /* was neterror() */
+#ifdef TLS
+#  define ssl_handshake ((int (*)(int,int,int,int,char *,IntFunc))global[78])
+#endif
 #define tputs ((void (*) (int, char *,unsigned int))global[79])
 /* 80 - 83 */
 #define new_dcc ((int (*) (struct dcc_table *, int))global[80])
@@ -225,22 +228,33 @@
 #define max_dcc (*(int *)global[100])
 #define require_p (*(int *)global[101])
 #define ignore_time (*(int *)(global[102]))
-/* was use_console_r <Wcc[02/02/03]> */
+#ifdef TLS
+#  define dcc_fingerprint ((int (*) (int))global[103])
+#endif
 /* 104 - 107 */
 #define reserved_port_min (*(int *)(global[104]))
 #define reserved_port_max (*(int *)(global[105]))
 #define raw_log (*(int *)(global[106]))
 #define noshare (*(int *)(global[107]))
 /* 108 - 111 */
+#ifdef TLS
+#  define tls_vfybots (*(int *)(global[108]))
+#else
 /* 108: gban_total -- UNUSED (Eule) */
+#endif
 #define make_userfile (*(int*)global[109])
 #define default_flags (*(int*)global[110])
 #define dcc_total (*(int*)global[111])
 /* 112 - 115 */
 #define tempdir ((char *)(global[112]))
 #define natip ((char *)(global[113]))
+#ifdef TLS
+#  define tls_vfyclients (*(int *)(global[114]))
+#  define tls_vfydcc (*(int *)(global[115]))
+#else
 /* was natip -- UNUSED */
 /* was hostname -- UNUSED */
+#endif
 #define origbotname ((char *)(global[115]))
 /* 116 - 119 */
 #define botuser ((char *)(global[116]))
Index: eggdrop1.8/src/mod/server.mod/cmdsserv.c
diff -u eggdrop1.8/src/mod/server.mod/cmdsserv.c:1.1.1.1 eggdrop1.8/src/mod/server.mod/cmdsserv.c:1.2
--- eggdrop1.8/src/mod/server.mod/cmdsserv.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/server.mod/cmdsserv.c	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * cmdsserv.c -- part of server.mod
  *   handles commands from a user via dcc that cause server interaction
  *
- * $Id: cmdsserv.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: cmdsserv.c,v 1.2 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -37,12 +37,22 @@
     i = 0;
     for (; x; x = x->next) {
       if ((i == curserv) && realservername)
+#ifdef TLS
+        egg_snprintf(s, sizeof s, "  %s:%s%d (%s) <- I am here", x->name,
+                     x->ssl ? "+" : "", x->port ? x->port : default_port,
+                     realservername);
+      else
+        egg_snprintf(s, sizeof s, "  %s:%s%d %s", x->name, x->ssl ? "+" : "",
+                     x->port ? x->port : default_port,
+                     (i == curserv) ? "<- I am here" : "");
+#else
         egg_snprintf(s, sizeof s, "  %s:%d (%s) <- I am here", x->name,
                      x->port ? x->port : default_port, realservername);
       else
         egg_snprintf(s, sizeof s, "  %s:%d %s", x->name,
                      x->port ? x->port : default_port,
                      (i == curserv) ? "<- I am here" : "");
+#endif
       dprintf(idx, "%s\n", s);
       i++;
     }
@@ -67,15 +77,33 @@
 static void cmd_jump(struct userrec *u, int idx, char *par)
 {
   char *other;
+#ifdef TLS
+  char *sport;
+#endif
   int port;
 
   if (par[0]) {
     other = newsplit(&par);
+#ifdef TLS
+    sport = newsplit(&par);
+    if (*sport == '+')
+      use_ssl = 1;
+    else
+      use_ssl = 0;
+    port = atoi(sport);
+    if (!port) {
+      port = default_port;
+      use_ssl = 0;
+    }
+    putlog(LOG_CMDS, "*", "#%s# jump %s %s%d %s", dcc[idx].nick, other,
+           use_ssl ? "+" : "", port, par);
+#else
     port = atoi(newsplit(&par));
     if (!port)
       port = default_port;
     putlog(LOG_CMDS, "*", "#%s# jump %s %d %s", dcc[idx].nick, other,
            port, par);
+#endif
     strncpyz(newserver, other, sizeof newserver);
     newserverport = port;
     strncpyz(newserverpass, par, sizeof newserverpass);
Index: eggdrop1.8/src/mod/server.mod/help/server.help
diff -u eggdrop1.8/src/mod/server.mod/help/server.help:1.1.1.1 eggdrop1.8/src/mod/server.mod/help/server.help:1.2
--- eggdrop1.8/src/mod/server.mod/help/server.help:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/server.mod/help/server.help	Tue Oct 19 06:13:33 2010
@@ -12,11 +12,13 @@
    See http://www.ietf.org/rfc/rfc1459.txt for more information on the
    IRC protocol.
 %{help=jump}%{+m}
-###  %bjump%b [server [port [pass]]]
+###  %bjump%b [server [[+]port [pass]]]
    Makes the bot jump to another server. If you don't specify a server, it
    will jump to the next server in the server list (see %b'.help servers'%b).
    If you specify a server, it will jump to that server (the default port is
    6667, unless you specified a different default port in your config file).
+   If you prefix the port with a plus sign (e.g. +6697), SSL connection will
+   be attempted.
    If the server is not in the server list already, it will be added to it.
    Jumping servers ALWAYS makes the bot lose ops! Be careful!
 
Index: eggdrop1.8/src/mod/server.mod/help/set/server.help
diff -u eggdrop1.8/src/mod/server.mod/help/set/server.help:1.1.1.1 eggdrop1.8/src/mod/server.mod/help/set/server.help:1.2
--- eggdrop1.8/src/mod/server.mod/help/set/server.help:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/server.mod/help/set/server.help	Tue Oct 19 06:13:33 2010
@@ -170,6 +170,12 @@
 ###  %bset net-type%b
    Define the network the bot uses. 0 = EFnet, 1 = IRCnet, 2 = UnderNet,
    3 = DALnet, 4 = EFnet +e/+I/max-bans 20 Hybrid, 5 = Others.
+%{help=set ssl-verify-server}%{+n}
+###  %bset ssl-verify-server%b
+   Control certificate verification for servers
+   Define the network the bot uses. 0 = EFnet, 1 = IRCnet, 2 = UnderNet,
+
+See also: set ssl-verify-clients
 %{help=server settings}%{+n}
 ###  Settings for the %bserver module%b
    This is a list of the Tcl variables the can be used to setup
@@ -183,4 +189,4 @@
      %bserverror-quit%b       %banswer-ctcp%b    %baltnick%b
      %btrigger-on-ignore%b    %bdefault-port%b   %brealname%b
      %bserver-cycle-wait%b    %bcheck-stoned%b   %bflood-msg%b
-     %bquiet-reject%b         %bkeep-nick%b
+     %bssl-verify-server%b    %bquiet-reject%b   %bkeep-nick%b
Index: eggdrop1.8/src/mod/server.mod/server.c
diff -u eggdrop1.8/src/mod/server.mod/server.c:1.3 eggdrop1.8/src/mod/server.mod/server.c:1.4
--- eggdrop1.8/src/mod/server.mod/server.c:1.3	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/mod/server.mod/server.c	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * server.c -- part of server.mod
  *   basic irc server support
  *
- * $Id: server.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: server.c,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -98,6 +98,10 @@
 static int optimize_kicks;
 static int msgrate;             /* Number of seconds between sending
                                  * queued lines to server. */
+#ifdef TLS
+static int use_ssl;		/* Use SSL for the next server connection? */
+static int tls_vfyserver;       /* Certificate validation mode for servrs  */
+#endif
 
 static p_tcl_bind_list H_wall, H_raw, H_notc, H_msgm, H_msg, H_flud, H_ctcr,
                        H_ctcp, H_out;
@@ -958,9 +962,9 @@
 
   for (z = serverlist; z && z->next; z = z->next);
   while (ss) {
-    p = strchr(ss, ',');
+/*    p = strchr(ss, ',');
     if (p)
-      *p++ = 0;
+      *p++ = 0; */
     x = nmalloc(sizeof(struct server_list));
 
     x->next = 0;
@@ -986,6 +990,9 @@
       x->pass = 0;
       x->name = nmalloc(strlen(ss) + 1);
       strcpy(x->name, ss);
+#ifdef TLS
+      x->ssl = 0;
+#endif
     } else {
       *q++ = 0;
       x->name = nmalloc(q - ss);
@@ -999,6 +1006,12 @@
         x->pass = nmalloc(strlen(q) + 1);
         strcpy(x->pass, q);
       }
+#ifdef TLS
+      if (*ss == '+')
+        x->ssl = 1;
+      else
+        x->ssl = 0;
+#endif
       x->port = atoi(ss);
     }
     ss = p;
@@ -1040,10 +1053,16 @@
       if (x->port == *port) {
         if (!egg_strcasecmp(x->name, serv)) {
           *ptr = i;
+#ifdef TLS
+            x->ssl = use_ssl;
+#endif
           return;
         } else if (x->realname && !egg_strcasecmp(x->realname, serv)) {
           *ptr = i;
           strncpyz(serv, x->realname, sizeof serv);
+#ifdef TLS
+          use_ssl = x->ssl;
+#endif
           return;
         }
       }
@@ -1062,6 +1081,9 @@
       strcpy(x->pass, pass);
     } else
       x->pass = NULL;
+#ifdef TLS
+    x->ssl = use_ssl;
+#endif
     egg_list_append((struct list_type **) (&serverlist),
                     (struct list_type *) x);
     *ptr = i;
@@ -1083,6 +1105,9 @@
     x = serverlist;
     *ptr = 0;
   }                             /* Start over at the beginning */
+#ifdef TLS
+  use_ssl = x->ssl;
+#endif
   strcpy(serv, x->name);
   *port = x->port ? x->port : default_port;
   if (x->pass)
@@ -1233,7 +1258,12 @@
   if (server_online) {
     int servidx = findanyidx(serv);
 
+#ifdef TLS
+    simple_sprintf(s, "%s:%s%u", dcc[servidx].host, dcc[servidx].ssl ? "+" : "",
+                   dcc[servidx].port);
+#else
     simple_sprintf(s, "%s:%u", dcc[servidx].host, dcc[servidx].port);
+#endif
   } else
     s[0] = 0;
   Tcl_SetVar2(interp, name1, name2, s, TCL_GLOBAL_ONLY);
@@ -1395,6 +1425,9 @@
   {"stack-limit",       &stack_limit,               0},
   {"exclusive-binds",   &exclusive_binds,           0},
   {"msg-rate",          &msgrate,                   0},
+#ifdef TLS
+  {"ssl-verify-server", &tls_vfyserver,             0},
+#endif
   {NULL,                NULL,                       0}
 };
 
@@ -1420,9 +1453,16 @@
     /* Create server list */
     Tcl_DStringInit(&ds);
     for (q = serverlist; q; q = q->next) {
+#ifdef TLS
+      egg_snprintf(x, sizeof x, "%s:%s%d%s%s %s", q->name,
+                   q->ssl ? "+" : "", q->port ? q->port : default_port,
+                   q->pass ? ":" : "", q->pass ? q->pass : "",
+                   q->realname ? q->realname : "");
+#else
       egg_snprintf(x, sizeof x, "%s:%d%s%s %s", q->name,
                    q->port ? q->port : default_port, q->pass ? ":" : "",
                    q->pass ? q->pass : "", q->realname ? q->realname : "");
+#endif
       Tcl_DStringAppendElement(&ds, x);
     }
     slist = Tcl_DStringValue(&ds);
@@ -1480,6 +1520,9 @@
 {
   char *action, *param, *ip, *prt, buf[512], *msg = buf;
   int i;
+#ifdef TLS
+  int ssl = 0;
+#endif
   struct userrec *u = get_user_by_handle(userlist, handle);
   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
 
@@ -1488,8 +1531,18 @@
   param = newsplit(&msg);
   ip = newsplit(&msg);
   prt = newsplit(&msg);
+#ifdef TLS
+  if (egg_strcasecmp(action, "CHAT") || egg_strcasecmp(object, botname) || !u)
+  {
+    if (!egg_strcasecmp(action, "SCHAT"))
+      ssl = 1;
+    else
+      return 0;
+  }
+#else
   if (egg_strcasecmp(action, "CHAT") || egg_strcasecmp(object, botname) || !u)
     return 0;
+#endif
   get_user_flagrec(u, &fr, 0);
   if (dcc_total == max_dcc && increase_socks_max()) {
     if (!quiet_reject)
@@ -1519,6 +1572,9 @@
       putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", nick, ip);
       return 1;
     }
+#ifdef TLS
+    dcc[i].ssl = ssl;
+#endif
     dcc[i].port = atoi(prt);
     (void) setsockname(&dcc[i].sockname, ip, dcc[i].port, 0);
     dcc[i].u.dns->ip = &dcc[i].sockname;
@@ -1536,6 +1592,18 @@
   return 1;
 }
 
+#ifdef TLS
+int dcc_chat_sslcb(int sock)
+{
+  int idx;
+
+  idx = findanyidx(sock);
+  if ((idx >= 0) && dcc_fingerprint(idx))
+    dprintf(idx, "%s\n", DCC_ENTERPASS);
+  return 0;
+}
+#endif
+
 static void dcc_chat_hostresolved(int i)
 {
   char buf[512];
@@ -1547,14 +1615,22 @@
     lostdcc(i);
     return;
   }
+  buf[0] = 0;
   dcc[i].sock = getsock(dcc[i].sockname.family, 0);
-  if (dcc[i].sock < 0 || open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0) {
+  if (dcc[i].sock < 0 || open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0)
+    snprintf(buf, sizeof buf, strerror(errno));
+#ifdef TLS
+  else if (dcc[i].ssl && ssl_handshake(dcc[i].sock, TLS_CONNECT, tls_vfydcc,
+                                       LOG_MISC, dcc[i].host, &dcc_chat_sslcb))
+    snprintf(buf, sizeof buf, "TLS negotiation error");
+#endif
+  if (buf[0]) {
     if (!quiet_reject)
       dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[i].nick,
-              DCC_CONNECTFAILED1, strerror(errno));
+              DCC_CONNECTFAILED1, buf);
     putlog(LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED2,
            dcc[i].nick, dcc[i].host);
-    putlog(LOG_MISC, "*", "    (%s)", strerror(errno));
+    putlog(LOG_MISC, "*", "    (%s)", buf);
     killsock(dcc[i].sock);
     lostdcc(i);
   } else {
@@ -1568,7 +1644,15 @@
     /* Ok, we're satisfied with them now: attempt the connect */
     putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", dcc[i].nick,
            dcc[i].host);
-    dprintf(i, "%s\n", DCC_ENTERPASS);
+#ifdef TLS
+    if (dcc[i].ssl)
+    /* Queue something up to make sure the handshake moves on */
+      dprintf(i, "TLS handshake in progress...\n");
+    else
+    /* For SSL connections, the handshake callback will determine
+       if we should request a password */
+#endif
+      dprintf(i, "%s\n", DCC_ENTERPASS);
   }
   return;
 }
@@ -1712,8 +1796,14 @@
 
   if ((trying_server || server_online) &&
       ((servidx = findanyidx(serv)) != -1)) {
-    dprintf(idx, "    Server %s:%d %s\n", dcc[servidx].host, dcc[servidx].port,
-            trying_server ? "(trying)" : s);
+#ifdef TLS
+    dprintf(idx, "    Server [%s]:%s%d %s\n", dcc[servidx].host,
+            dcc[servidx].ssl ? "+" : "", dcc[servidx].port, trying_server ?
+            "(trying)" : s);
+#else
+    dprintf(idx, "    Server [%s]:%d %s\n", dcc[servidx].host,
+            dcc[servidx].port, trying_server ? "(trying)" : s);
+#endif
   } else
     dprintf(idx, "    %s\n", IRC_NOSERVER);
 
@@ -1820,7 +1910,11 @@
   /* 4 - 7 */
   (Function) NULL,              /* char * (points to botname later on)  */
   (Function) botuserhost,       /* char *                               */
+#ifdef TLS
+  (Function) & use_ssl,		/* int					*/
+#else
   (Function) NULL,              /* Was quiet_reject <Wcc[01/21/03]>.    */
+#endif
   (Function) & serv,            /* int                                  */
   /* 8 - 11 */
   (Function) & flud_thr,        /* int                                  */
@@ -1928,6 +2022,9 @@
   stack_limit = 4;
   realservername = 0;
   msgrate = 2;
+#ifdef TLS
+  tls_vfyserver = 0;
+#endif
 
   server_table[4] = (Function) botname;
   module_register(MODULE_NAME, server_table, 1, 4);
Index: eggdrop1.8/src/mod/server.mod/server.h
diff -u eggdrop1.8/src/mod/server.mod/server.h:1.1.1.1 eggdrop1.8/src/mod/server.mod/server.h:1.2
--- eggdrop1.8/src/mod/server.mod/server.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/server.mod/server.h	Tue Oct 19 06:13:33 2010
@@ -1,7 +1,7 @@
 /*
  * server.h -- part of server.mod
  *
- * $Id: server.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: server.h,v 1.2 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -32,7 +32,11 @@
 /* 4 - 7 */
 /* Empty */
 #define botuserhost ((char *)(server_funcs[5]))
+#ifdef TLS
+#define use_ssl (*(int *)(server_funcs[6]))
+#else
 /* Was quiet_reject (moved to core) <Wcc[01/21/03]>. */
+#endif
 #define serv (*(int *)(server_funcs[7]))
 /* 8 - 11 */
 #define flud_thr (*(int*)(server_funcs[8]))
@@ -96,6 +100,9 @@
 
   char *name;
   int port;
+#ifdef TLS
+  int ssl;
+#endif
   char *pass;
   char *realname;
 };
Index: eggdrop1.8/src/mod/server.mod/servmsg.c
diff -u eggdrop1.8/src/mod/server.mod/servmsg.c:1.2 eggdrop1.8/src/mod/server.mod/servmsg.c:1.3
--- eggdrop1.8/src/mod/server.mod/servmsg.c:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/mod/server.mod/servmsg.c	Tue Oct 19 06:13:33 2010
@@ -1,7 +1,7 @@
 /*
  * servmsg.c -- part of server.mod
  *
- * $Id: servmsg.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: servmsg.c,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1294,13 +1294,14 @@
       do_tcl("connect-server", connectserver);
     check_tcl_event("connect-server");
     next_server(&curserv, botserver, &botserverport, pass);
-#ifdef IPV6
-    if (strchr(botserver, ':'))
-      putlog(LOG_SERV, "*", "%s [%s]:%d", IRC_SERVERTRY, botserver,
-             botserverport);
-    else
+#ifdef TLS
+    putlog(LOG_SERV, "*", "%s [%s]:%s%d", IRC_SERVERTRY, botserver,
+           use_ssl ? "+" : "", botserverport);
+    dcc[servidx].ssl = use_ssl;
+#else
+    putlog(LOG_SERV, "*", "%s [%s]:%d", IRC_SERVERTRY, botserver,
+           botserverport);
 #endif
-    putlog(LOG_SERV, "*", "%s %s:%d", IRC_SERVERTRY, botserver, botserverport);
     dcc[servidx].port = botserverport;
     strcpy(dcc[servidx].nick, "(server)");
     strncpyz(dcc[servidx].host, botserver, UHOSTLEN);
@@ -1357,9 +1358,17 @@
   dcc[servidx].sock = getsock(dcc[servidx].sockname.family, 0);
   setsnport(dcc[servidx].sockname, dcc[servidx].port);
   serv = open_telnet_raw(dcc[servidx].sock, &dcc[servidx].sockname);
+#ifdef TLS
+  if (serv < 0 || (dcc[servidx].ssl &&
+      ssl_handshake(serv, TLS_CONNECT, tls_vfyserver, LOG_SERV,
+                    dcc[servidx].host, NULL))) {
+    putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host,
+           serv ? "TLS negotiation failure" : strerror(errno));
+#else
   if (serv < 0) {
     putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host,
            strerror(errno));
+#endif
     lostdcc(servidx);
     if (oldserv == curserv && !never_give_up)
       fatal("NO SERVERS WILL ACCEPT MY CONNECTION.", 0);
Index: eggdrop1.8/src/mod/server.mod/tclserv.c
diff -u eggdrop1.8/src/mod/server.mod/tclserv.c:1.1.1.1 eggdrop1.8/src/mod/server.mod/tclserv.c:1.2
--- eggdrop1.8/src/mod/server.mod/tclserv.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/server.mod/tclserv.c	Tue Oct 19 06:13:33 2010
@@ -1,7 +1,7 @@
 /*
  * tclserv.c -- part of server.mod
  *
- * $Id: tclserv.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: tclserv.c,v 1.2 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -175,7 +175,17 @@
   if (argc >= 2) {
     strncpyz(newserver, argv[1], sizeof newserver);
     if (argc >= 3)
+#ifdef TLS
+    {
+      if (*argv[2] == '+')
+        use_ssl = 1;
+      else
+        use_ssl = 0;
       newserverport = atoi(argv[2]);
+    }
+#else
+      newserverport = atoi(argv[2]);
+#endif
     else
       newserverport = default_port;
     if (argc == 4)
Index: eggdrop1.8/src/mod/share.mod/share.c
diff -u eggdrop1.8/src/mod/share.mod/share.c:1.3 eggdrop1.8/src/mod/share.mod/share.c:1.4
--- eggdrop1.8/src/mod/share.mod/share.c:1.3	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/mod/share.mod/share.c	Tue Oct 19 06:13:33 2010
@@ -1,7 +1,7 @@
 /*
  * share.c -- part of share.mod
  *
- * $Id: share.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: share.c,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1142,7 +1142,13 @@
     (void) setsockname(&dcc[i].sockname, ip, dcc[i].port, 0);
     /* Don't buffer this -> mark binary. */
     sock = getsock(dcc[i].sockname.family, SOCK_BINARY);
+#ifdef TLS
+    if (sock < 0 || (open_telnet_raw(sock, &dcc[i].sockname) < 0) ||
+        (*port == '+' && ssl_handshake(sock, TLS_CONNECT, tls_vfybots,
+        LOG_MISC, ip, NULL))) {
+#else
     if (sock < 0 || open_telnet_raw(sock, &dcc[i].sockname) < 0) {
+#endif
       lostdcc(i);
       killsock(sock);
       putlog(LOG_BOTS, "*", "Asynchronous connection failed!");
@@ -1156,6 +1162,10 @@
       dcc[i].u.xfer->length = atoi(par);
       dcc[i].u.xfer->f = f;
       dcc[i].sock = sock;
+#ifdef TLS
+      if (*port == '+')
+        dcc[i].ssl = 1;
+#endif
       strcpy(dcc[i].host, dcc[idx].nick);
 
       dcc[idx].status |= STAT_GETTING;
@@ -1932,8 +1942,13 @@
     i = dcc_total - 1;
     strcpy(dcc[i].host, dcc[idx].nick); /* Store bot's nick */
     getdccaddr(&dcc[i].sockname, s, sizeof s);
-    dprintf(idx, "s us %s %d %lu\n", s,
-            dcc[i].port, dcc[i].u.xfer->length);
+#ifdef TLS
+    if (dcc[idx].ssl) {
+      dcc[i].ssl = 1;
+      dprintf(idx, "s us %s +%d %lu\n", s, dcc[i].port, dcc[i].u.xfer->length);
+    } else
+#endif
+    dprintf(idx, "s us %s %d %lu\n", s, dcc[i].port, dcc[i].u.xfer->length);
     /* Start up a tbuf to queue outgoing changes for this bot until the
      * userlist is done transferring.
      */
Index: eggdrop1.8/src/modules.c
diff -u eggdrop1.8/src/modules.c:1.2 eggdrop1.8/src/modules.c:1.3
--- eggdrop1.8/src/modules.c:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/modules.c	Tue Oct 19 06:13:33 2010
@@ -4,7 +4,7 @@
  *
  * by Darrin Smith (beldin at light.iinet.net.au)
  *
- * $Id: modules.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: modules.c,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -86,7 +86,7 @@
 
 extern char tempdir[], botnetnick[], botname[], origbotname[], botuser[],
             admin[], userfile[], ver[], notify_new[], helpdir[], version[],
-            quit_msg[], log_ts[];
+                        quit_msg[], log_ts[];
 
 extern int parties, noshare, dcc_total, egg_numver, userfile_perm, do_restart,
            ignore_time, must_be_owner, raw_log, max_dcc, make_userfile,
@@ -98,6 +98,10 @@
 extern int pref_af;
 #endif
 
+#ifdef TLS
+extern int tls_vfyclients, tls_vfydcc, tls_vfybots;
+#endif
+
 extern party_t *party;
 extern time_t now, online_since;
 extern tand_t *tandbot;
@@ -297,7 +301,11 @@
   /* 76 - 79 */
   (Function) answer,
   (Function) getvhost,
-  (Function) 0,                   /* was neterror() -- UNUSED            */
+#ifdef TLS
+  (Function) ssl_handshake,
+#else
+  (Function) 0,
+#endif
   (Function) tputs,
   /* 80 - 83 */
   (Function) new_dcc,
@@ -328,21 +336,34 @@
   (Function) & max_dcc,           /* int                                 */
   (Function) & require_p,         /* int                                 */
   (Function) & ignore_time,       /* int                                 */
+#ifdef TLS
+  (Function) dcc_fingerprint,
+#else
   (Function) 0,                   /* was use_console_r <Wcc[02/02/03]>   */
+#endif
   /* 104 - 107 */
   (Function) & reserved_port_min,
   (Function) & reserved_port_max,
   (Function) & raw_log,           /* int                                 */
   (Function) & noshare,           /* int                                 */
   /* 108 - 111 */
+#ifdef TLS
+  (Function) & tls_vfybots,       /* int                                 */
+#else
   (Function) 0,                   /* gban_total -- UNUSED! (Eule)        */
+#endif
   (Function) & make_userfile,     /* int                                 */
   (Function) & default_flags,     /* int                                 */
   (Function) & dcc_total,         /* int                                 */
   /* 112 - 115 */
   (Function) tempdir,             /* char *                              */
+#ifdef TLS
+  (Function) & tls_vfyclients,    /* int                                 */
+  (Function) & tls_vfydcc,        /* int                                 */
+#else
   (Function) 0,                   /* was natip -- use getmyip() instead  */
   (Function) 0,                   /* was myip -- use getvhost() instead  */
+#endif
   (Function) origbotname,         /* char *                              */
   /* 116 - 119 */
   (Function) botuser,             /* char *                              */
Index: eggdrop1.8/src/net.c
diff -u eggdrop1.8/src/net.c:1.4 eggdrop1.8/src/net.c:1.5
--- eggdrop1.8/src/net.c:1.4	Tue Sep 14 13:45:29 2010
+++ eggdrop1.8/src/net.c	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * net.c -- handles:
  *   all raw network i/o
  *
- * $Id: net.c,v 1.4 2010/09/14 19:45:29 pseudo Exp $
+ * $Id: net.c,v 1.5 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * This is hereby released into the public domain.
@@ -44,6 +44,10 @@
 #endif
 #include <setjmp.h>
 
+#ifdef TLS
+#  include <openssl/err.h>
+#endif
+
 #ifndef HAVE_GETDTABLESIZE
 #  ifdef FD_SETSIZE
 #    define getdtablesize() FD_SETSIZE
@@ -271,6 +275,9 @@
       td->socklist[i].handler.sock.outbuflen = 0;
       td->socklist[i].flags = options;
       td->socklist[i].sock = sock;
+#ifdef TLS
+      td->socklist[i].ssl = 0;
+#endif
       return i;
     }
   }
@@ -369,6 +376,14 @@
   for (i = 0; i < td->MAXSOCKS; i++) {
     if ((td->socklist[i].sock == sock) && !(td->socklist[i].flags & SOCK_UNUSED)) {
       if (!(td->socklist[i].flags & SOCK_TCL)) { /* nothing to free for tclsocks */
+#ifdef TLS
+        if (td->socklist[i].ssl) {
+          SSL_shutdown(td->socklist[i].ssl);
+          nfree(SSL_get_app_data(td->socklist[i].ssl));
+          SSL_free(td->socklist[i].ssl);
+          td->socklist[i].ssl = NULL;
+        }
+#endif
         close(td->socklist[i].sock);
         if (td->socklist[i].handler.sock.inbuf != NULL) {
           nfree(td->socklist[i].handler.sock.inbuf);
@@ -716,6 +731,9 @@
     for (i = 0; i < slistmax; i++) {
       if (!tclonly && ((!(slist[i].flags & (SOCK_UNUSED | SOCK_TCL))) &&
           ((FD_ISSET(slist[i].sock, &fdr)) ||
+#ifdef TLS
+          (slist[i].ssl && SSL_pending(slist[i].ssl)) ||
+#endif
           ((slist[i].sock == STDOUT) && (!backgrd) &&
           (FD_ISSET(STDIN, &fdr)))))) {
         if (slist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) {
@@ -725,7 +743,12 @@
           if (slist[i].flags & SOCK_PROXYWAIT) /* drummer */
             /* Hang around to get the return code from proxy */
             grab = 10;
+#ifdef TLS
+          else if (!(slist[i].flags & SOCK_STRONGCONN) &&
+            (!(slist[i].ssl) || !SSL_in_init(slist[i].ssl))) {
+#else
           else if (!(slist[i].flags & SOCK_STRONGCONN)) {
+#endif
             debug1("net: connect! sock %d", slist[i].sock);
             s[0] = 0;
             *len = 0;
@@ -740,7 +763,24 @@
         if ((slist[i].sock == STDOUT) && !backgrd)
           x = read(STDIN, s, grab);
         else
-          x = read(slist[i].sock, s, grab);
+#ifdef TLS
+	{
+          if (slist[i].ssl) {
+            x = SSL_read(slist[i].ssl, s, grab);
+            if (x < 0) {
+	      int err = SSL_get_error(slist[i].ssl, x);
+	      if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
+	        errno = EAGAIN;
+              else
+                debug1("SSL error: %s", ERR_error_string(ERR_get_error(), 0));
+              x = -1;
+            }
+          } else
+            x = read(slist[i].sock, s, grab);
+	}
+#else
+	  x = read(slist[i].sock, s, grab);
+#endif  
         if (x <= 0) {           /* eof */
           if (errno != EAGAIN) { /* EAGAIN happens when the operation would
                                   * block on a non-blocking socket, if the
@@ -1047,6 +1087,22 @@
         socklist[i].handler.sock.outbuflen += len;
         return;
       }
+#ifdef TLS
+      if (socklist[i].ssl) {
+        x = SSL_write(socklist[i].ssl, s, len);
+        if (x < 0) {
+          int err = SSL_get_error(socklist[i].ssl, x);
+          if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
+            errno = EAGAIN;
+          else if (!inhere) { /* Out there, somewhere */
+            inhere = 1;
+            debug1("SSL error: %s", ERR_error_string(ERR_get_error(), 0));
+            inhere = 0;
+          }
+          x = -1;
+        }
+      } else /* not ssl, use regular write() */
+#endif      
       /* Try. */
       x = write(z, s, len);
       if (x == -1)
@@ -1114,6 +1170,20 @@
         (socklist[i].handler.sock.outbuf != NULL) && (FD_ISSET(socklist[i].sock, &wfds))) {
       /* Trick tputs into doing the work */
       errno = 0;
+#ifdef TLS
+      if (socklist[i].ssl) {
+        x = SSL_write(socklist[i].ssl, socklist[i].handler.sock.outbuf,
+        socklist[i].handler.sock.outbuflen);
+        if (x < 0) {
+          int err = SSL_get_error(socklist[i].ssl, x);
+          if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
+            errno = EAGAIN;
+          else
+            debug1("SSL error: %s", ERR_error_string(ERR_get_error(), 0));
+          x = -1;
+        }
+      } else
+#endif   
       x = write(socklist[i].sock, socklist[i].handler.sock.outbuf, socklist[i].handler.sock.outbuflen);
       if ((x < 0) && (errno != EAGAIN)
 #ifdef EBADSLT
@@ -1183,6 +1253,10 @@
         strcat(s, " (strong)");
       if (socklist[i].flags & SOCK_NONSOCK)
         strcat(s, " (file)");
+#ifdef TLS
+      if (socklist[i].ssl)
+        strcat(s, " (TLS)");
+#endif
       if (socklist[i].flags & SOCK_TCL)
         strcat(s, " (tcl)");
       if (!(socklist[i].flags & SOCK_TCL)) {
@@ -1346,3 +1420,20 @@
   }
   return -1;
 }
+
+/* Find sock in socklist.
+ *
+ * Returns index in socklist or -1 if not found.
+ */
+int findsock(int sock)
+{
+  int i;
+  struct threaddata *td = threaddata();
+
+  for (i = 0; i < td->MAXSOCKS; i++)
+    if (td->socklist[i].sock == sock)
+      break;
+  if (i == td->MAXSOCKS)
+    return -1;
+  return i;
+}
Index: eggdrop1.8/src/patch.h
diff -u eggdrop1.8/src/patch.h:1.10 eggdrop1.8/src/patch.h:1.11
--- eggdrop1.8/src/patch.h:1.10	Thu Oct 14 03:49:47 2010
+++ eggdrop1.8/src/patch.h	Tue Oct 19 06:13:33 2010
@@ -10,7 +10,7 @@
  * statement, leave the rest of the file alone, this allows better
  * overlapping patches.
  *
- * $Id: patch.h,v 1.10 2010/10/14 09:49:47 pseudo Exp $
+ * $Id: patch.h,v 1.11 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -41,12 +41,12 @@
  *
  *
  */
-patch("1287049595");            /* current unixtime */
+patch("1287489296");            /* current unixtime */
 /*
  *
  *
  */
-patch("qnx6darwin");
+patch("tls");
 /*
  *
  *
Index: eggdrop1.8/src/proto.h
diff -u eggdrop1.8/src/proto.h:1.3 eggdrop1.8/src/proto.h:1.4
--- eggdrop1.8/src/proto.h:1.3	Sun Oct 10 12:22:47 2010
+++ eggdrop1.8/src/proto.h	Tue Oct 19 06:13:33 2010
@@ -7,7 +7,7 @@
  * because they use structures in those
  * (saves including those .h files EVERY time) - Beldin
  *
- * $Id: proto.h,v 1.3 2010/10/10 18:22:47 pseudo Exp $
+ * $Id: proto.h,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -127,6 +127,9 @@
 void strip_mirc_codes(int, char *);
 int check_ansi(char *);
 void dupwait_notify(char *);
+#ifdef TLS
+int dcc_fingerprint(int);
+#endif
 
 /* dccutil.c */
 int increase_socks_max();
@@ -288,6 +291,7 @@
 int sock_has_data(int, int);
 int sockoptions(int sock, int operation, int sock_options);
 int flush_inbuf(int idx);
+int findsock(int sock);
 
 /* tcl.c */
 struct threaddata *threaddata();
@@ -297,6 +301,14 @@
 void do_tcl(char *, char *);
 int readtclprog(char *fname);
 
+/* tls.c */
+#ifdef TLS
+int ssl_handshake(int, int, int, int, char *, IntFunc);
+char *ssl_fpconv(char *in, char *out);
+char *ssl_getuid(int sock);
+char *ssl_getfp(int sock);
+#endif
+
 /* userent.c */
 void list_type_kill(struct list_type *);
 int list_type_expmem(struct list_type *);
Index: eggdrop1.8/src/tcl.c
diff -u eggdrop1.8/src/tcl.c:1.3 eggdrop1.8/src/tcl.c:1.4
--- eggdrop1.8/src/tcl.c:1.3	Mon Aug 23 15:27:40 2010
+++ eggdrop1.8/src/tcl.c	Tue Oct 19 06:13:33 2010
@@ -4,7 +4,7 @@
  *   Tcl initialization
  *   getting and setting Tcl/eggdrop variables
  *
- * $Id: tcl.c,v 1.3 2010/08/23 21:27:40 pseudo Exp $
+ * $Id: tcl.c,v 1.4 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -67,6 +67,12 @@
 extern int pref_af;
 #endif
 
+#ifdef TLS
+extern int tls_maxdepth, tls_vfybots, tls_vfyclients, tls_vfydcc, tls_auth;
+extern char tls_capath[], tls_cafile[], tls_certfile[], tls_keyfile[],
+            tls_ciphers[];
+#endif
+
 extern struct dcc_t *dcc;
 extern tcl_timer_t *timer, *utimer;
 
@@ -489,12 +495,19 @@
   {"help-path",       helpdir,        120, STR_DIR | STR_PROTECT},
   {"temp-path",       tempdir,        120, STR_DIR | STR_PROTECT},
   {"text-path",       textdir,        120, STR_DIR | STR_PROTECT},
+#ifdef TLS
+  {"ssl-capath",      tls_capath,     120, STR_DIR | STR_PROTECT},
+  {"ssl-cafile",      tls_cafile,     120,           STR_PROTECT},
+  {"ssl-ciphers",     tls_ciphers,    120,           STR_PROTECT},
+  {"ssl-privatekey",  tls_keyfile,    120,           STR_PROTECT},
+  {"ssl-certificate", tls_certfile,   120,           STR_PROTECT},
+#endif
 #ifndef STATIC
   {"mod-path",        moddir,         120, STR_DIR | STR_PROTECT},
 #endif
   {"notify-newusers", notify_new,     120,                     0},
   {"owner",           owner,          120,           STR_PROTECT},
-  {"vhost4",          vhost,          120,                     0},
+  {"vhost",           vhost,           120,                    0},
 #ifdef IPV6
   {"vhost6",          vhost6,         120,                     0},
 #endif
@@ -516,6 +529,13 @@
 static tcl_ints def_tcl_ints[] = {
   {"ignore-time",           &ignore_time,          0},
   {"handlen",               &handlen,              2},
+#ifdef TLS
+  {"ssl-chain-depth",       &tls_maxdepth,         0},
+  {"ssl-verify-dcc",        &tls_vfydcc,           0},
+  {"ssl-verify-clients",    &tls_vfyclients,       0},
+  {"ssl-verify-bots",       &tls_vfybots,          0},
+  {"ssl-cert-auth",         &tls_auth,             0},
+#endif
   {"dcc-flood-thr",         &dcc_flood_thr,        0},
   {"hourly-updates",        &notify_users_at,      0},
   {"switch-logfiles-at",    &switch_logfiles_at,   0},
@@ -595,6 +615,9 @@
 
 extern tcl_cmds tcluser_cmds[], tcldcc_cmds[], tclmisc_cmds[],
        tclmisc_objcmds[], tcldns_cmds[];
+#ifdef TLS
+extern tcl_cmds tcltls_cmds[];
+#endif
 
 #ifdef REPLACE_NOTIFIER
 /* The tickle_*() functions replace the Tcl Notifier
@@ -839,6 +862,9 @@
   add_tcl_objcommands(tclmisc_objcmds);
 #endif
   add_tcl_commands(tcldns_cmds);
+#ifdef TLS
+  add_tcl_commands(tcltls_cmds);
+#endif
 }
 
 void do_tcl(char *whatzit, char *script)
Index: eggdrop1.8/src/tcldcc.c
diff -u eggdrop1.8/src/tcldcc.c:1.2 eggdrop1.8/src/tcldcc.c:1.3
--- eggdrop1.8/src/tcldcc.c:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/tcldcc.c	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * tcldcc.c -- handles:
  *   Tcl stubs for the dcc commands
  *
- * $Id: tcldcc.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: tcldcc.c,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -33,6 +33,10 @@
 extern struct dcc_t *dcc;
 extern char botnetnick[];
 extern int dcc_total, backgrd, parties, make_userfile, do_restart, remote_boots, max_dcc;
+#ifdef TLS
+extern int tls_vfydcc;
+extern sock_list *socklist;
+#endif
 extern party_t *party;
 extern tand_t *tandbot;
 extern time_t now;
@@ -878,9 +882,21 @@
     }
     return TCL_ERROR;
   }            
+#ifdef TLS
+  if (*argv[2] == '+' && ssl_handshake(sock, TLS_CONNECT, 0, LOG_MISC, NULL, NULL)) {
+    killsock(sock);
+    strncpyz(s, "Failed to establish a TLS session", sizeof s);
+    Tcl_AppendResult(irp, s, NULL);
+    return TCL_ERROR;
+  }
+#endif
   i = new_dcc(&DCC_SOCKET, 0);
   dcc[i].sock = sock;
   dcc[i].port = atoi(argv[2]);
+#ifdef TLS
+  if (*argv[2] == '+')
+    dcc[i].ssl = 1;
+#endif
   strcpy(dcc[i].nick, "*");
   strncpyz(dcc[i].host, argv[1], UHOSTMAX);
   egg_snprintf(s, sizeof s, "%d", sock);
@@ -965,6 +981,12 @@
     dcc[idx].sock = i;
     dcc[idx].timeval = now;
   }
+#ifdef TLS
+  if (*argv[1] == '+')
+    dcc[idx].ssl = 1;
+  else
+    dcc[idx].ssl = 0;
+#endif
   /* script? */
   if (!strcmp(argv[2], "script")) {
     strcpy(dcc[idx].nick, "(script)");
Index: eggdrop1.8/src/tclhash.c
diff -u eggdrop1.8/src/tclhash.c:1.1.1.1 eggdrop1.8/src/tclhash.c:1.2
--- eggdrop1.8/src/tclhash.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/tclhash.c	Tue Oct 19 06:13:33 2010
@@ -7,7 +7,7 @@
  *   (non-Tcl) procedure lookups for msg/dcc/file commands
  *   (Tcl) binding internal procedures to msg/dcc/file commands
  *
- * $Id: tclhash.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: tclhash.c,v 1.2 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -42,6 +42,10 @@
 p_tcl_bind_list H_chat, H_act, H_bcst, H_chon, H_chof, H_load, H_unld, H_link,
                 H_disc, H_dcc, H_chjn, H_chpt, H_bot, H_time, H_nkch, H_away,
                 H_note, H_filt, H_event, H_cron, H_log = NULL;
+#ifdef TLS
+p_tcl_bind_list H_tls = NULL;
+static int builtin_idx();
+#endif
 
 static int builtin_2char();
 static int builtin_3char();
@@ -238,6 +242,9 @@
   H_act = add_bind_table("act", HT_STACKABLE, builtin_chat);
   H_event = add_bind_table("evnt", HT_STACKABLE, builtin_char);
   H_log = add_bind_table("log", HT_STACKABLE, builtin_log);
+#ifdef TLS
+  H_tls = add_bind_table("tls", HT_STACKABLE, builtin_idx);
+#endif
   add_builtins(H_dcc, C_dcc);
   Context;
 }
@@ -687,6 +694,19 @@
   return TCL_OK;
 }
 
+#ifdef TLS
+static int builtin_idx STDVAR
+{
+  Function F = (Function) cd;
+
+  BADARGS(2, 2, " idx");
+
+  CHECKVALIDITY(builtin_idx);
+  F(atoi(argv[1]));
+  return TCL_OK;
+}
+#endif
+
 /* Trigger (execute) a Tcl proc
  *
  * Note: This is INLINE code for check_tcl_bind().
@@ -1178,6 +1198,20 @@
                  MATCH_MASK | BIND_STACKABLE);
 }
 
+#ifdef TLS
+int check_tcl_tls(int sock)
+{
+  int x;
+  char s[11];
+
+  egg_snprintf(s, sizeof s, "%d", sock);
+  Tcl_SetVar(interp, "_tls", s, 0);
+  x = check_tcl_bind(H_tls, s, 0, " $_tls", MATCH_MASK | BIND_STACKABLE |
+                     BIND_WANTRET);
+  return (x == BIND_EXEC_LOG);
+}
+#endif
+
 void tell_binds(int idx, char *par)
 {
   tcl_bind_list_t *tl, *tl_kind;
Index: eggdrop1.8/src/tclhash.h
diff -u eggdrop1.8/src/tclhash.h:1.1.1.1 eggdrop1.8/src/tclhash.h:1.2
--- eggdrop1.8/src/tclhash.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/tclhash.h	Tue Oct 19 06:13:33 2010
@@ -1,7 +1,7 @@
 /*
  * tclhash.h
  *
- * $Id: tclhash.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: tclhash.h,v 1.2 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -104,6 +104,9 @@
 void check_tcl_chatactbcst(const char *, int, const char *, tcl_bind_list_t *);
 void check_tcl_event(const char *);
 void check_tcl_log(int, char *, char *);
+#ifdef TLS
+int check_tcl_tls(int);
+#endif
 
 #define check_tcl_chat(a, b, c) check_tcl_chatactbcst(a ,b, c, H_chat)
 #define check_tcl_act(a, b, c) check_tcl_chatactbcst(a, b, c, H_act)
Index: eggdrop1.8/src/tls.c
diff -u /dev/null eggdrop1.8/src/tls.c:1.1
--- /dev/null	Tue Oct 19 06:13:44 2010
+++ eggdrop1.8/src/tls.c	Tue Oct 19 06:13:33 2010
@@ -0,0 +1,866 @@
+/*
+ * tls.c -- handles:
+ *   TLS support functions
+ *   Certificate handling
+ *   OpenSSL initialization and shutdown
+ *
+ * $Id: tls.c,v 1.1 2010/10/19 12:13:33 pseudo Exp $
+ */
+/*
+ * Written by Rumen Stoyanov <pseudo at egg6.net>
+ *
+ * Copyright (C) 2010 Eggheads Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "main.h"
+
+#ifdef TLS
+
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/x509v3.h>
+
+extern int tls_vfydcc;
+extern struct dcc_t *dcc;
+
+int tls_maxdepth = 9;         /* Max certificate chain verification depth     */
+SSL_CTX *ssl_ctx = NULL;      /* SSL context object                           */
+char *tls_randfile = NULL;    /* Random seed file for SSL                     */
+char tls_capath[121] = "";    /* Path to trusted CA certificates              */
+char tls_cafile[121] = "";    /* File containing trusted CA certificates      */
+char tls_certfile[121] = "";  /* Our own digital certificate ;)               */
+char tls_keyfile[121] = "";   /* Private key for use with eggdrop             */
+char tls_ciphers[121] = "";   /* A list of ciphers for SSL to use             */
+
+
+/* Count allocated memory for SSL. This excludes memory allocated by OpenSSL's
+ * family of malloc functions.
+ */
+int expmem_tls()
+{
+  int i, tot;
+  struct threaddata *td = threaddata();
+
+  /* currently it's only the appdata structs allocated by ssl_handshake() */
+  for (i = 0, tot = 0; i < td->MAXSOCKS; i++)
+    if (!(td->socklist[i].flags & (SOCK_UNUSED | SOCK_TCL)))
+      if (td->socklist[i].ssl && SSL_get_app_data(td->socklist[i].ssl))
+        tot += sizeof(ssl_appdata);
+  return tot;
+}
+
+/* Seeds the PRNG
+ *
+ * Only does something if the system doesn't have enough entropy.
+ * If there is no random file, one will be created either at
+ * $RANDFILE if set or at $HOME/.rnd
+ *
+ * Return value: 0 on success, !=0 on failure.
+ */
+static int ssl_seed(void)
+{
+  char stackdata[1024];
+  static char rand_file[120];
+  FILE *fh;
+
+#if OPENSSL_VERSION_NUMBER >= 0x00905100
+  if (RAND_status())
+    return 0;     /* Status OK */
+#endif
+  /* If '/dev/urandom' is present, OpenSSL will use it by default.
+   * Otherwise we'll have to generate pseudorandom data ourselves,
+   * using system time, our process ID and some unitialized static
+   * storage.
+   */
+  if ((fh = fopen("/dev/urandom", "r"))) {
+    fclose(fh);
+    return 0;
+  }
+  if (RAND_file_name(rand_file, sizeof(rand_file)))
+    tls_randfile = rand_file;
+  else
+    return 1;
+  if (!RAND_load_file(rand_file, -1)) {
+    /* generate some pseudo random data */
+    unsigned int c;
+    c = time(NULL);
+    RAND_seed(&c, sizeof(c));
+    c = getpid();
+    RAND_seed(&c, sizeof(c));
+    RAND_seed(stackdata, sizeof(stackdata));
+  }
+#if OPENSSL_VERSION_NUMBER >= 0x00905100
+  if (!RAND_status())
+    return 2;   /* pseudo random data still not ehough */
+#endif
+  return 0;
+}
+
+/* Prepares and initializes SSL stuff
+ *
+ * Creates a context object, supporting SSLv2/v3 & TLSv1 protocols;
+ * Seeds the Pseudo Random Number Generator;
+ * Optionally loads a SSL certifate and a private key.
+ * Tell OpenSSL the location of certificate authority certs
+ *
+ * Return value: 0 on successful initialization, !=0 on failure
+ */
+int ssl_init()
+{
+  /* Load SSL and crypto error strings; register SSL algorithms */
+  SSL_load_error_strings();
+  SSL_library_init();
+
+  if (ssl_seed()) {
+    putlog(LOG_MISC, "*", "TLS: unable to seed PRNG. Disabling SSL");
+    ERR_free_strings();
+    return -2;
+  }
+  /* A TLS/SSL connection established with this method will understand all
+     supported protocols (SSLv2, SSLv3, and TLSv1) */
+  if (!(ssl_ctx = SSL_CTX_new(SSLv23_method()))) {
+    debug0(ERR_error_string(ERR_get_error(), NULL));
+    putlog(LOG_MISC, "*", "TLS: unable to create context. Disabling SSL.");
+    ERR_free_strings();
+    return -1;
+  }
+  /* Load our own certificate and private key. Mandatory for acting as
+     server, because we don't support anonymous ciphers by default. */
+  if (SSL_CTX_use_certificate_chain_file(ssl_ctx, tls_certfile) != 1)
+    debug1("TLS: unable to load own certificate: %s",
+           ERR_error_string(ERR_get_error(), NULL));
+  if (SSL_CTX_use_PrivateKey_file(ssl_ctx, tls_keyfile,
+      SSL_FILETYPE_PEM) != 1)
+    debug1("TLS: unable to load private key: %s",
+           ERR_error_string(ERR_get_error(), NULL));
+  if ((tls_capath[0] || tls_cafile[0]) &&
+      !SSL_CTX_load_verify_locations(ssl_ctx, tls_cafile[0] ? tls_cafile : NULL,
+      tls_capath[0] ? tls_capath : NULL))
+    debug1("TLS: unable to set CA certificates location: %s",
+           ERR_error_string(ERR_get_error(), NULL));
+  /* Let advanced users specify the list of allowed ssl ciphers */
+  if (tls_ciphers[0])
+    if (!SSL_CTX_set_cipher_list(ssl_ctx, tls_ciphers)) {
+      /* this replaces any preset ciphers so an invalid list is fatal */
+      putlog(LOG_MISC, "*", "TLS: no valid ciphers found. Disabling SSL.");
+      ERR_free_strings();
+      SSL_CTX_free(ssl_ctx);
+      ssl_ctx = NULL;
+      return -3;
+    }
+
+  return 0;
+}
+
+/* Free the SSL CTX, clean up the mess */
+void ssl_cleanup()
+{
+  if (ssl_ctx) {
+    SSL_CTX_free(ssl_ctx);
+    ssl_ctx = NULL;
+  }
+  if (tls_randfile)
+    RAND_write_file(tls_randfile);
+  ERR_free_strings();
+}
+
+char *ssl_fpconv(char *in, char *out)
+{
+  long len;
+  char *fp;
+  unsigned char *md5;
+  
+  if (!in)
+    return NULL;
+  
+  if ((md5 = string_to_hex(in, &len))) {
+    fp = hex_to_string(md5, len);
+    if (fp) {
+      out = user_realloc(out, strlen(fp) + 1);
+      strcpy(out, fp);
+      OPENSSL_free(md5);
+      OPENSSL_free(fp);
+      return out;
+    }
+      OPENSSL_free(md5);
+  }
+  return NULL;
+}
+
+/* Get the certificate, corresponding to the connection
+ * identified by sock.
+ *
+ * Return value: pointer to a X509 certificate or NULL if we couldn't
+ * look up the certificate.
+ */
+static X509 *ssl_getcert(int sock)
+{
+  int i;
+  struct threaddata *td = threaddata();
+  
+  i = findsock(sock);
+  if (i == -1 || !td->socklist[i].ssl)
+    return NULL;
+  return SSL_get_peer_certificate(td->socklist[i].ssl);
+}
+
+/* Get the certificate fingerprint of the connection corresponding
+ * to the socket.
+ *
+ * Return value: ptr to the hexadecimal representation of the fingerprint
+ * or NULL if there's no certificate associated with the connection.
+ */
+char *ssl_getfp(int sock)
+{
+  char *p;
+  unsigned i;
+  X509 *cert;
+  static char fp[64];
+  unsigned char md[EVP_MAX_MD_SIZE];
+
+  if (!(cert = ssl_getcert(sock)))
+    return NULL;
+  if (!X509_digest(cert, EVP_sha1(), md, &i))
+    return NULL;
+  if (!(p = hex_to_string(md, i)))
+    return NULL;
+  strncpyz(fp, p, sizeof fp);
+  OPENSSL_free(p);
+  return fp;
+}
+
+/* Get the UID field from the certificate subject name.
+ * The certificate is looked up using the socket of the connection.
+ *
+ * Return value: Pointer to the uid string or NULL if not found
+ */
+char *ssl_getuid(int sock)
+{
+  int idx;
+  X509 *cert;
+  X509_NAME *subj;
+  ASN1_STRING *name;
+
+  if (!(cert = ssl_getcert(sock)))
+    return NULL;
+  /* Get the subject name */
+  if (!(subj = X509_get_subject_name(cert)))
+    return NULL;
+
+  /* Get the first UID */
+  idx = X509_NAME_get_index_by_NID(subj, NID_userId, -1);
+  if (idx == -1)
+    return NULL;
+  name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, idx));
+  /* Extract the contents, assuming null-terminated ASCII string */
+  return (char *) ASN1_STRING_data(name);
+}
+
+/* Compare the peer's host with their Common Name or dnsName found in
+ * it's certificate. Only the first domain component of cn is allowed to
+ * be a wildcard '*'. The non-wildcard characters are compared ignoring
+ * case.
+ *
+ * Return value: 1 if cn matches host, 0 otherwise.
+ */
+static int ssl_hostmatch(char *cn, char *host)
+{
+  char *p, *q, *r;
+
+  if ((r = strchr(cn + 1, '.')) && r[-1] == '*' && strchr(r, '.')) {
+    for (p = cn, q = host; *p != '*'; p++, q++)
+      if (toupper(*p) != toupper(*q))
+        return 0;
+
+    if (!(p = strchr(host, '.')) || strcasecmp(p, r))
+      return 0;
+    return 1;
+  }
+
+  /* First domain component is not a wildcard and they aren't allowed
+     elsewhere, so just compare the strings. */
+  return strcasecmp(cn, host) ? 0 : 1;
+}
+
+/* Confirm the peer identity, by checking if the certificate subject 
+ * matches the peer's DNS name or IP address. Matching is performed in
+ * accordance with RFC 2818:
+ *
+ * If the certificate has a subjectAltName extension, all names of type
+ * IPAddress or dnsName present there, will be compared to data->host,
+ * depending on it's contents.
+ * In case there's no subjectAltName extension, commonName (CN) parts
+ * of the certificate subject field will be used instead of IPAddress
+ * and dnsName entries. For IP addresses, common names must contain IPs
+ * in presentation format (1.2.3.4 or 2001:DB8:15:dead::)
+ * Finally, if no subjectAltName or common names are present, the
+ * certificate is considered to not match the peer.
+ *
+ * The structure of X509 certificates and all fields referenced above
+ * are described in RFC 5280.
+ *
+ * The certificate must be pointed by cert and the peer's host must be
+ * placed in data->host. The format is a regular DNS name or an IP in
+ * presentation format (see above).
+ * 
+ * Return value: 1 if the certificate matches the peer, 0 otherwise.
+ */
+static int ssl_verifycn(X509 *cert, ssl_appdata *data)
+{
+  char *cn;
+  int crit = 0, match = 0;
+  ASN1_OCTET_STRING *ip;
+  GENERAL_NAMES *altname; /* SubjectAltName ::= GeneralNames */
+  
+  ip = a2i_IPADDRESS(data->host); /* check if it's an IP or a hostname */
+  if ((altname = X509_get_ext_d2i(cert, NID_subject_alt_name, &crit, NULL))) {
+    GENERAL_NAME *gn;
+
+    /* Loop through the general names in altname and pick these
+       of type ip address or dns name */
+    while (!match && (gn = sk_GENERAL_NAME_pop(altname))) {
+      /* if the peer's host is an IP, we're only interested in
+         matching against iPAddress general names, otherwise
+         we'll only look for dnsName's */
+      if (ip) {
+        if (gn->type == GEN_IPADD)
+          match = !ASN1_STRING_cmp(gn->d.ip, ip);
+      } else if (gn->type == GEN_DNS) {
+        /* IA5string holds ASCII data */
+        cn = (char *) ASN1_STRING_data(gn->d.ia5);
+        match = ssl_hostmatch(cn, data->host);
+      }
+    }
+    sk_GENERAL_NAME_free(altname);
+  } else { /* no subjectAltName, try to match against the subject CNs */
+    X509_NAME *subj; /* certificate subject */
+
+    /* the following is just for information */
+    switch (crit) {
+      case 0:
+        debug0("TLS: X509 subjectAltName cannot be decoded");
+        break;
+      case -1:
+        debug0("TLS: X509 has no subjectAltName extension");
+        break;
+      case -2:
+        debug0("TLS: X509 has multiple subjectAltName extensions");
+    }
+    /* no subject name either? A completely broken certificate :) */
+    if (!(subj = X509_get_subject_name(cert))) {
+      putlog(data->loglevel, "*", "TLS: peer certificate has no subject: %s",
+             data->host);
+      match = 0;
+    } else { /* we have a subject name, look at it */
+      int pos = -1;
+      ASN1_STRING *name;
+      
+      /* Look for commonName attributes in the subject name */
+      pos = X509_NAME_get_index_by_NID(subj, NID_commonName, pos);
+      if (pos == -1) /* sorry */
+        putlog(data->loglevel, "*", "TLS: Peer has no common names and "
+              "no subjectAltName extension. Verification failed.");
+      /* Loop through all common names which may be present in the subject
+         name until we find a match. */
+      while (!match && pos != -1) {
+        name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, pos));
+        cn = (char *) ASN1_STRING_data(name);
+        if (ip)
+          match = a2i_IPADDRESS(cn) ? (ASN1_STRING_cmp(ip, a2i_IPADDRESS(cn)) ? 0 : 1) : 0;
+        else
+          match = ssl_hostmatch(cn, data->host);
+        pos = X509_NAME_get_index_by_NID(subj, NID_commonName, pos);
+      }
+    }
+  }
+
+  if (ip)
+    ASN1_OCTET_STRING_free(ip);
+  return match;
+}
+
+/* Extract a human readable version of a X509_NAME and put the result
+ * into a nmalloc'd buffer.
+ * The X509_NAME structure is used for example in certificate subject
+ * and issuer names.
+ *
+ * You need to nfree() the returned pointer.
+ */
+static char *ssl_printname(X509_NAME *name)
+{
+  int len;
+  char *data, *buf;
+  BIO *bio = BIO_new(BIO_s_mem());
+  
+  /* X509_NAME_oneline() is easier and shorter, but is deprecated and
+     the manual discourages it's usage, so let's not be lazy ;) */
+  X509_NAME_print_ex(bio, name, 0, XN_FLAG_ONELINE & ~XN_FLAG_SPC_EQ);
+  len = BIO_get_mem_data(bio, &data) + 1;
+  buf = nmalloc(len);
+  strncpyz(buf, data, len);
+  BIO_free(bio);
+  return buf;
+}
+
+/* Print the time from a ASN1_UTCTIME object in standard format i.e.
+ * Nov 21 23:59:00 1996 GMT and store it in a nmalloc'd buffer.
+ * The ASN1_UTCTIME structure is what's used for example with
+ * certificate validity dates.
+ *
+ * You need to nfree() the returned pointer.
+ */
+static char *ssl_printtime(ASN1_UTCTIME *t)
+{
+  int len;
+  char *data, *buf;
+  BIO *bio = BIO_new(BIO_s_mem());
+  
+  ASN1_UTCTIME_print(bio, t);
+  len = BIO_get_mem_data(bio, &data) + 1;
+  buf = nmalloc(len);
+  strncpyz(buf, data, len);
+  BIO_free(bio);
+  return buf;
+}
+
+/* Print the value of an ASN1_INTEGER in hexadecimal format.
+ * A typical use for this is to display certificate serial numbers.
+ * As usual, we use a memory BIO.
+ *
+ * You need to nfree() the returned pointer.
+ */
+static char *ssl_printnum(ASN1_INTEGER *i)
+{
+  int len;
+  char *data, *buf;
+  BIO *bio = BIO_new(BIO_s_mem());
+  
+  i2a_ASN1_INTEGER(bio, i);
+  len = BIO_get_mem_data(bio, &data) + 1;
+  buf = nmalloc(len);
+  strncpyz(buf, data, len);
+  BIO_free(bio);
+  return buf;
+}
+
+/* Show the user all relevant information about a certificate: subject,
+ * issuer, validity dates and fingerprints.
+ */
+static void ssl_showcert(X509 *cert, int loglev)
+{
+  char *buf, *from, *to;
+  X509_NAME *name;
+  unsigned int len;
+  unsigned char md[EVP_MAX_MD_SIZE];
+  
+  /* Subject and issuer names */
+  if ((name = X509_get_subject_name(cert))) {
+    buf = ssl_printname(name);
+    putlog(loglev, "*", "TLS: certificate subject: %s", buf);
+    nfree(buf);
+  } else
+    putlog(loglev, "*", "TLS: cannot get subject name from certificate!");
+  if ((name = X509_get_issuer_name(cert))) {
+    buf = ssl_printname(name);
+    putlog(loglev, "*", "TLS: certificate issuer: %s", buf);
+    nfree(buf);
+  } else
+    putlog(loglev, "*", "TLS: cannot get issuer name from certificate!");
+  
+  /* Fingerprints */
+  X509_digest(cert, EVP_md5(), md, &len); /* MD5 hash */
+  if (len <= sizeof(md)) {
+    buf = hex_to_string(md, len);
+    putlog(loglev, "*", "TLS: certificate MD5 Fingerprint: %s", buf);
+    OPENSSL_free(buf);
+  }
+  X509_digest(cert, EVP_sha1(), md, &len); /* SHA-1 hash */
+  if (len <= sizeof(md)) {
+    buf = hex_to_string(md, len);
+    putlog(loglev, "*", "TLS: certificate SHA1 Fingerprint: %s", buf);
+    OPENSSL_free(buf);
+  }
+
+  /* Validity time */
+  from = ssl_printtime(X509_get_notBefore(cert));
+  to = ssl_printtime(X509_get_notAfter(cert));
+  putlog(loglev, "*", "TLS: certificate valid from %s to %s", from, to);
+  nfree(from);
+  nfree(to);
+}
+
+/* Certificate validation callback
+ *
+ * Check if the certificate given is valid with respect to the
+ * ssl-verify config variable. This makes it possible to allow
+ * self-signed certificates and is also a convenient place to
+ * extract a certificate summary.
+ *
+ * Return value: 1 - validation passed, 0 - invalid cert
+ */
+int ssl_verify(int ok, X509_STORE_CTX *ctx)
+{
+  SSL *ssl;
+  X509 *cert;
+  ssl_appdata *data;
+  int err, depth;
+  
+  /* get cert, callbacks, error codes, etc. */
+  depth = X509_STORE_CTX_get_error_depth(ctx);
+  cert = X509_STORE_CTX_get_current_cert(ctx);
+  ssl = X509_STORE_CTX_get_ex_data(ctx,
+                          SSL_get_ex_data_X509_STORE_CTX_idx());
+  data = (ssl_appdata *) SSL_get_app_data(ssl);
+  err = X509_STORE_CTX_get_error(ctx);
+
+  /* OpenSSL won't explicitly generate this error; instead it will
+   * report missing certificates. Refer to SSL_CTX_set_verify(3)
+   * manual for details
+   */
+  if (depth > tls_maxdepth) {
+    ok = 0;
+    err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+
+  /* depth 0 is actually the peer certificate. We do all custom
+   * verification here and leave the rest of the certificate chain
+   * to OpenSSL's built in procedures.
+   */
+  } else if (!depth) {
+    /* OpenSSL doesn't perform subject name verification. We need to do
+     * it ourselves. We check here for validity even if it's not requested
+     * in order to be able to warn the user.
+     */
+    if (!(data->flags & TLS_DEPTH0) && !ssl_verifycn(cert, data) &&
+        (data->verify & TLS_VERIFYCN)) {
+        putlog(data->loglevel, "*", "TLS: certificate validation failed. "
+               "Certificate subject does not match peer.");
+        return 0;
+    }
+    data->flags |= TLS_DEPTH0;
+    /* Allow exceptions for certain common verification errors, if the
+     * caller requested so. A lot of servers provide completely invalid
+     * certificates unuseful for any authentication.
+     */
+    if (!ok || data->verify)
+      if (((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) &&
+          (data->verify & TLS_VERIFYISSUER)) ||
+          ((err == X509_V_ERR_CERT_REVOKED) &&
+          (data->verify & TLS_VERIFYREV)) ||
+          ((err == X509_V_ERR_CERT_NOT_YET_VALID) &&
+          (data->verify & TLS_VERIFYFROM)) ||
+          ((err == X509_V_ERR_CERT_HAS_EXPIRED) &&
+          (data->verify & TLS_VERIFYTO))) {
+        debug1("TLS: peer certificate warning: %s",
+               X509_verify_cert_error_string(err));
+        ok = 1;
+      }
+  }
+  if (ok || !data->verify)
+    return 1;
+  putlog(data->loglevel, "*",
+         "TLS: certificate validation failed at depth %d: %s",
+         depth, X509_verify_cert_error_string(err));
+  return 0;
+}
+
+/* SSL info callback, this is used to trace engine state changes
+ * and to check when the handshake is finished, so we can display
+ * some cipher and session information and process callbacks.
+ */
+void ssl_info(SSL *ssl, int where, int ret)
+{
+  int sock;
+  X509 *cert;
+  char buf[256];
+  ssl_appdata *data;
+  SSL_CIPHER *cipher;
+  int secret, processed;
+  
+  /* We're doing non-blocking IO, so we check here if the handshake has
+     finished */
+  if (where & SSL_CB_HANDSHAKE_DONE) {
+    if (!(data = (ssl_appdata *) SSL_get_app_data(ssl)))
+      return;
+    /* Callback for completed handshake. Cheaper and more convenient than
+       using H_tls */
+    sock = SSL_get_fd(ssl);    
+    if (data->cb)
+      data->cb(sock);
+    /* Call TLS binds. We allow scripts to take over or disable displaying of
+       certificate information. */
+    if (check_tcl_tls(sock))
+      return;
+
+    putlog(data->loglevel, "*", "TLS: handshake successful. Secure connection "
+           "established.");
+
+    if ((cert = SSL_get_peer_certificate(ssl))) 
+      ssl_showcert(cert, data->loglevel);
+    else
+      putlog(data->loglevel, "*", "TLS: peer did not present a certificate");
+
+    /* Display cipher information */
+    cipher = SSL_get_current_cipher(ssl);
+    processed = SSL_CIPHER_get_bits(cipher, &secret);
+    putlog(data->loglevel, "*", "TLS: cipher used: %s %s; %d bits (%d secret)",
+           SSL_CIPHER_get_name(cipher), SSL_CIPHER_get_version(cipher),
+           processed, secret);
+    /* secret are the actually secret bits. If processed and secret differ,
+       the rest of the bits are fixed, i.e. for limited export ciphers */
+
+    /* More verbose information, for debugging only */
+    SSL_CIPHER_description(cipher, buf, sizeof buf);
+    debug1("TLS: cipher details: %s", buf);
+  }
+
+  /* Display the state of the engine for debugging purposes */
+/*  debug1("TLS: state change: %s", SSL_state_string_long(ssl)); */
+}
+    
+/* Switch a socket to SSL communication
+ *
+ * Creates a SSL data structure for the connection;
+ * Sets up callbacks and initiates a SSL handshake with the peer;
+ * Reports error conditions and performs cleanup upon failure.
+ *
+ * flags: ssl flags, i.e connect or listen
+ * verify: peer certificate verification flags
+ * loglevel: is the level to output information about the connection
+ * and certificates.
+ * host: contains the dns name or ip address of the peer. Used for
+ * verification.
+ * cb: optional callback, this function will be called after the
+ * handshake completes.
+ *
+ * Return value: 0 on success, !=0 on failure.
+ */
+int ssl_handshake(int sock, int flags, int verify, int loglevel, char *host,
+                  IntFunc cb)
+{
+  int i, err, ret;
+  ssl_appdata *data;
+  struct threaddata *td = threaddata();
+
+  debug0("TLS: attempting SSL negotiation...");
+  if (!ssl_ctx && ssl_init()) {
+    debug0("TLS: Failed. OpenSSL not initialized properly.");
+    return -1;
+  }
+  /* find the socket in the list */
+  i = findsock(sock);
+  if (i == -1) {
+    debug0("TLS: socket not in socklist");
+    return -2;
+  }
+  if (td->socklist[i].ssl) {
+    debug0("TLS: handshake not required - SSL session already established");
+    return 0;
+  }
+  td->socklist[i].ssl = SSL_new(ssl_ctx);
+  if (!td->socklist[i].ssl ||
+      !SSL_set_fd(td->socklist[i].ssl, td->socklist[i].sock)) {
+    debug1("TLS: cannot initiate SSL session - %s",
+           ERR_error_string(ERR_get_error(), 0));
+    return -3;
+  }
+
+  /* Prepare a ssl appdata struct for the verify callback */
+  data = nmalloc(sizeof(ssl_appdata));
+  egg_bzero(data, sizeof(ssl_appdata));
+  data->flags = flags & (TLS_LISTEN | TLS_CONNECT);
+  data->verify = flags & ~(TLS_LISTEN | TLS_CONNECT);
+  data->loglevel = loglevel;
+  data->cb = cb;
+  strncpyz(data->host, host ? host : "", sizeof(data->host));
+  SSL_set_app_data(td->socklist[i].ssl, data);
+  SSL_set_info_callback(td->socklist[i].ssl, (void *) ssl_info);
+  /* We set this +1 to be able to report extra long chains properly.
+   * Otherwise, OpenSSL will break the verification reporting about
+   * missing certificates instead. The rest of the fix is in
+   * ssl_verify()
+   */
+  SSL_set_verify_depth(td->socklist[i].ssl, tls_maxdepth + 1);
+
+  SSL_set_mode(td->socklist[i].ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+  if (data->flags & TLS_CONNECT) {
+    SSL_set_verify(td->socklist[i].ssl, SSL_VERIFY_PEER, ssl_verify);
+    ret = SSL_connect(td->socklist[i].ssl);
+    if (!ret)
+      debug0("TLS: connect handshake failed.");
+  } else {
+    if (data->flags & TLS_VERIFYPEER)
+      SSL_set_verify(td->socklist[i].ssl, SSL_VERIFY_PEER |
+                     SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify);
+    else
+      SSL_set_verify(td->socklist[i].ssl, SSL_VERIFY_PEER, ssl_verify);
+    ret = SSL_accept(td->socklist[i].ssl);
+    if (!ret)
+      debug0("TLS: accept handshake failed");
+  }
+
+  err = SSL_get_error(td->socklist[i].ssl, ret);
+  /* Normal condition for async I/O, similar to EAGAIN */
+  if (ret > 0 || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
+    debug0("TLS: handshake in progress");
+    return 0;
+  }
+  if (ERR_peek_error())
+    debug0("TLS: handshake failed due to the following errors: ");
+  while ((err = ERR_get_error()))
+    debug1("TLS: %s", ERR_error_string(err, NULL));
+
+  /* Attempt failed, cleanup and abort */
+  SSL_shutdown(td->socklist[i].ssl);
+  SSL_free(td->socklist[i].ssl);
+  td->socklist[i].ssl = NULL;
+  nfree(data);
+  return -4;
+}
+
+/* Tcl functions */
+
+/* Is the connection secure? */
+static int tcl_istls STDVAR
+{
+  int j;
+
+  BADARGS(2, 2, " idx");
+
+  j = findidx(atoi(argv[1]));
+  if (j < 0) {
+    Tcl_AppendResult(irp, "invalid idx", NULL);
+    return TCL_ERROR;
+  }
+  if (dcc[j].ssl)
+    Tcl_AppendResult(irp, "1", NULL);
+  else
+    Tcl_AppendResult(irp, "0", NULL);
+  return TCL_OK;
+}
+
+/* Perform a SSL handshake over an existing plain text
+ * connection.
+ */
+static int tcl_starttls STDVAR
+{
+  int j;
+  struct threaddata *td = threaddata();
+
+  BADARGS(2, 2, " idx");
+
+  j = findidx(atoi(argv[1]));
+  if (j < 0 || (dcc[j].type != &DCC_SCRIPT)) {
+    Tcl_AppendResult(irp, "invalid idx", NULL);
+    return TCL_ERROR;
+  }
+  if (dcc[j].ssl) {
+    Tcl_AppendResult(irp, "already started", NULL);
+    return TCL_ERROR;
+  }
+  /* Determine if we're playing a client or a server */
+  j = findsock(dcc[j].sock);
+  if (ssl_handshake(dcc[j].sock, (td->socklist[j].flags & SOCK_CONNECT) ?
+      TLS_CONNECT : TLS_LISTEN, tls_vfydcc, LOG_MISC, NULL, NULL))
+    Tcl_AppendResult(irp, "0", NULL);
+  else
+    Tcl_AppendResult(irp, "1", NULL);
+  return TCL_OK;
+}
+
+/* Get all relevant information about an established ssl connection.
+ * This includes certificate subject and issuer, serial number,
+ * expiry date, protocol version and cipher information.
+ * All data is presented as a flat list consisting of name-value pairs.
+ */
+static int tcl_tlsstatus STDVAR
+{
+  char *p;
+  int i, j;
+  X509 *cert;
+  SSL_CIPHER *cipher;
+  struct threaddata *td = threaddata();
+  Tcl_DString ds;
+
+  BADARGS(2, 2, " idx");
+
+  /* Allow it to be used for any connection, not just scripted
+   * ones. This makes it possible for a script to display the
+   * server certificate.
+   */
+  i = findanyidx(atoi(argv[1]));
+  if (i < 0) {
+    Tcl_AppendResult(irp, "invalid idx", NULL);
+    return TCL_ERROR;
+  }
+  j = findsock(dcc[i].sock);
+  if (!j || !dcc[i].ssl || !td->socklist[j].ssl) {
+    Tcl_AppendResult(irp, "not a TLS connection", NULL);
+    return TCL_ERROR;
+  }
+  
+  Tcl_DStringInit(&ds);
+  /* Try to get a cert, clients aren't required to send a
+   * certificate, so this is optional
+   */
+  cert = SSL_get_peer_certificate(td->socklist[j].ssl);
+  /* The following information is certificate dependent */
+  if (cert) {
+    p = ssl_printname(X509_get_subject_name(cert));
+    Tcl_DStringAppendElement(&ds, "subject");
+    Tcl_DStringAppendElement(&ds, p);
+    nfree(p);
+    p = ssl_printname(X509_get_issuer_name(cert));
+    Tcl_DStringAppendElement(&ds, "issuer");
+    Tcl_DStringAppendElement(&ds, p);
+    nfree(p);
+    p = ssl_printtime(X509_get_notBefore(cert));
+    Tcl_DStringAppendElement(&ds, "notBefore");
+    Tcl_DStringAppendElement(&ds, p);
+    nfree(p);
+    p = ssl_printtime(X509_get_notAfter(cert));
+    Tcl_DStringAppendElement(&ds, "notAfter");
+    Tcl_DStringAppendElement(&ds, p);
+    nfree(p);
+    p = ssl_printnum(X509_get_serialNumber(cert));
+    Tcl_DStringAppendElement(&ds, "serial");
+    Tcl_DStringAppendElement(&ds, p);
+    nfree(p);
+  }
+  /* We should always have a cipher, but who knows? */
+  cipher = SSL_get_current_cipher(td->socklist[j].ssl);
+  if (cipher) { /* don't bother if there's none */
+    Tcl_DStringAppendElement(&ds, "protocol");
+    Tcl_DStringAppendElement(&ds, SSL_CIPHER_get_version(cipher));
+    Tcl_DStringAppendElement(&ds, "cipher");
+    Tcl_DStringAppendElement(&ds, SSL_CIPHER_get_name(cipher));
+  }
+
+  /* Done, get a Tcl list from this and return it to the caller */
+  Tcl_AppendResult(irp, Tcl_DStringValue(&ds), NULL);
+  Tcl_DStringFree(&ds);
+  return TCL_OK;
+}
+
+/* These will be added by tcl.c which is the established practice */
+tcl_cmds tcltls_cmds[] = {
+  {"istls",         tcl_istls},
+  {"starttls",   tcl_starttls},
+  {"tlsstatus", tcl_tlsstatus},
+  {NULL,                 NULL}
+};
+
+#endif /* TLS */
Index: eggdrop1.8/src/userent.c
diff -u eggdrop1.8/src/userent.c:1.2 eggdrop1.8/src/userent.c:1.3
--- eggdrop1.8/src/userent.c:1.2	Thu Aug  5 12:12:05 2010
+++ eggdrop1.8/src/userent.c	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * userent.c -- handles:
  *   user-entry handling, new style more versatile.
  *
- * $Id: userent.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
+ * $Id: userent.c,v 1.3 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -26,6 +26,7 @@
 #include "main.h"
 #include "users.h"
 
+
 extern int noshare;
 extern struct userrec *userlist;
 extern struct dcc_t *dcc;
@@ -48,6 +49,9 @@
   add_entry_type(&USERENTRY_PASS);
   add_entry_type(&USERENTRY_HOSTS);
   add_entry_type(&USERENTRY_BOTFL);
+#ifdef TLS
+  add_entry_type(&USERENTRY_FPRINT);
+#endif
 }
 
 void list_type_kill(struct list_type *t)
@@ -473,9 +477,21 @@
     strncpy(bi->address, p, q - p);
     bi->address[q - p] = 0;
     q++;
+#ifdef TLS
+    if (*q == '+')
+      bi->ssl = 1;
+#endif
     bi->telnet_port = atoi(q);
     if ((q = strchr(q, '/')))
+#ifdef TLS
+    {
+      if (q[1] == '+')
+        bi->ssl = 1;
+      bi->relay_port = atoi(q + 1);
+    }
+#else
       bi->relay_port = atoi(q + 1);
+#endif
   }
 #ifdef IPV6
   for (p = bi->address; *p; p++)
@@ -493,24 +509,22 @@
 
 static int botaddr_pack(struct userrec *u, struct user_entry *e)
 {
-  char work[1024];
+  char work[1024], *p, *q = work;
   struct bot_addr *bi;
   int l;
 
   bi = (struct bot_addr *) e->u.extra;
-#ifdef IPV6
-  char *p, *addr = user_malloc(strlen(bi->address) + 1);
-  strcpy(addr, bi->address);
-  for (p = addr; *p; p++)
+  for (p = bi->address; *p; p++)
     if (*p == ':')
-      *p = ';';
-  l = simple_sprintf(work, "%s:%u/%u", p, bi->telnet_port,
-                       bi->relay_port);
-  nfree(addr);
-#else
-  l = simple_sprintf(work, "%s:%u/%u", bi->address, bi->telnet_port,
-                     bi->relay_port);
+      *q++ = ';';
+    else
+      *q++ = *p;
+#ifdef TLS
+  if (bi->ssl)
+    l = simple_sprintf(q, ":+%u/+%u", bi->telnet_port, bi->relay_port);
+  else
 #endif
+  l = simple_sprintf(q, ":%u/%u", bi->telnet_port, bi->relay_port);
   e->u.list = user_malloc(sizeof(struct list_type));
   e->u.list->next = NULL;
   e->u.list->extra = user_malloc(l + 1);
@@ -531,27 +545,30 @@
 static int botaddr_write_userfile(FILE *f, struct userrec *u,
                                   struct user_entry *e)
 {
+  int ret = 1;
+  char *p, *q, *addr;
   register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
 
-#ifdef IPV6
-  char *p, *addr = user_malloc(strlen(bi->address) + 1);
-  strcpy(addr, bi->address);
-  for (p = addr; *p; p++)
+  p = bi->address;
+  addr = user_malloc(strlen(bi->address) + 1);
+  for (q = addr; *p; p++)
     if (*p == ':')
-      *p = ';';
+      *q++ = ';';
+    else
+      *q++ = *p;
+    *q = 0;
+#ifdef TLS
+  if (bi->ssl) {
+    if (fprintf(f, "--%s %s:+%u/+%u\n", e->type->name, addr,
+                bi->telnet_port, bi->relay_port) == EOF)
+      ret = 0;
+  } else
+#endif
   if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, addr,
-      bi->telnet_port, bi->relay_port) == EOF) {
-    nfree(addr);
-    return 0;
-  }
+      bi->telnet_port, bi->relay_port) == EOF)
+    ret = 0;
   nfree(addr);
-  return 1;
-#else
-  if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, bi->address,
-              bi->telnet_port, bi->relay_port) == EOF)
-    return 0;
-  return 1;
-#endif
+  return ret;
 }
 
 static int botaddr_set(struct userrec *u, struct user_entry *e, void *buf)
@@ -568,6 +585,12 @@
     bi = e->u.extra = buf;
   }
   if (bi && !noshare && !(u->flags & USER_UNSHARED)) {
+#ifdef TLS
+    if (bi->ssl)
+      shareout(NULL, "c BOTADDR %s %s +%d +%d\n", u->handle,
+               bi->address, bi->telnet_port, bi->relay_port);
+    else
+#endif
     shareout(NULL, "c BOTADDR %s %s %d %d\n", u->handle,
              bi->address, bi->telnet_port, bi->relay_port);
   }
@@ -580,8 +603,18 @@
   register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
   char number[20];
 
+#ifdef TLS
+  if (bi->ssl)
+    sprintf(number, " +%d", bi->telnet_port);
+  else
+#endif
   sprintf(number, " %d", bi->telnet_port);
   Tcl_AppendResult(interp, bi->address, number, NULL);
+#ifdef TLS
+  if (bi->ssl)
+    sprintf(number, " +%d", bi->relay_port);
+  else
+#endif
   sprintf(number, " %d", bi->relay_port);
   Tcl_AppendResult(interp, number, NULL);
   return TCL_OK;
@@ -604,9 +637,25 @@
     bi->address = user_malloc(strlen(argv[3]) + 1);
     strcpy(bi->address, argv[3]);
     if (argc > 4)
+#ifdef TLS
+    {
+      if (*argv[4] == '+')
+        bi->ssl = 1;
+      bi->telnet_port = atoi(argv[4]);
+    }
+#else
       bi->telnet_port = atoi(argv[4]);
+#endif
     if (argc > 5)
+#ifdef TLS
+    {
+      if (*argv[5] == '+')
+        bi->ssl = 1;
+      bi->relay_port = atoi(argv[5]);
+    }
+#else
       bi->relay_port = atoi(argv[5]);
+#endif
     if (!bi->telnet_port)
       bi->telnet_port = 3333;
     if (!bi->relay_port)
@@ -628,6 +677,12 @@
   register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
 
   dprintf(idx, "  ADDRESS: %.70s\n", bi->address);
+#ifdef TLS
+  if (bi->ssl)
+    dprintf(idx, "     users: +%d, bots: +%d\n", bi->relay_port,
+            bi->telnet_port);
+  else
+#endif
   dprintf(idx, "     users: %d, bots: %d\n", bi->relay_port, bi->telnet_port);
 }
 
@@ -642,6 +697,10 @@
   bi->address = user_malloc(strlen(arg) + 1);
   strcpy(bi->address, arg);
   arg = newsplit(&buf);
+#ifdef TLS
+  if (*arg == '+' || *buf == '+')
+    bi->ssl = 1;
+#endif
   bi->telnet_port = atoi(arg);
   bi->relay_port = atoi(buf);
   if (!bi->telnet_port)
@@ -664,6 +723,9 @@
 
       bi2->telnet_port = bi->telnet_port;
       bi2->relay_port = bi->relay_port;
+#ifdef TLS
+      bi2->ssl = bi->ssl;
+#endif
       bi2->address = user_malloc(strlen(bi->address) + 1);
       strcpy(bi2->address, bi->address);
       return set_user(&USERENTRY_BOTADDR, new, bi2);
@@ -1111,6 +1173,67 @@
   "HOSTS"
 };
 
+#ifdef TLS
+int fprint_unpack(struct userrec *u, struct user_entry *e)
+{
+  char *tmp;
+
+  tmp = ssl_fpconv(e->u.list->extra, NULL);
+  nfree(e->u.list->extra);
+  e->u.list->extra = NULL;
+  list_type_kill(e->u.list);
+  e->u.string = tmp;
+  return 1;
+}
+
+int fprint_set(struct userrec *u, struct user_entry *e, void *buf)
+{
+  char *fp = buf;
+
+  if (!fp || !fp[0] || (fp[0] == '-')) {
+    if (e->u.string) {
+      nfree(e->u.string);
+      e->u.string = NULL;
+    }
+  } else {
+    fp = ssl_fpconv(buf, e->u.string);
+    if (fp)
+      e->u.string = fp;
+    else
+      return 0;
+  }
+  if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
+    shareout(NULL, "c FPRINT %s %s\n", u->handle, e->u.string ? e->u.string : "");
+  return 1;
+}
+
+static int fprint_tcl_set(Tcl_Interp * irp, struct userrec *u,
+                        struct user_entry *e, int argc, char **argv)
+{
+  BADARGS(3, 4, " handle FPRINT ?new-fingerprint?");
+
+  fprint_set(u, e, argc == 3 ? NULL : argv[3]);
+  return TCL_OK;
+}
+
+struct user_entry_type USERENTRY_FPRINT = {
+  0,
+  def_gotshare,
+  0,
+  fprint_unpack,
+  def_pack,
+  def_write_userfile,
+  def_kill,
+  def_get,
+  fprint_set,
+  def_tcl_get,
+  fprint_tcl_set,
+  def_expmem,
+  0,
+  "FPRINT"
+};
+#endif /* TLS */
+
 int egg_list_append(struct list_type **h, struct list_type *i)
 {
   for (; *h; h = &((*h)->next));
@@ -1147,6 +1270,7 @@
 
     if (e && e->name) {
       e->type = type;
+
       e->type->unpack(u, e);
       nfree(e->name);
       e->name = NULL;
Index: eggdrop1.8/src/users.h
diff -u eggdrop1.8/src/users.h:1.1.1.1 eggdrop1.8/src/users.h:1.2
--- eggdrop1.8/src/users.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/users.h	Tue Oct 19 06:13:33 2010
@@ -2,7 +2,7 @@
  * users.h
  *   structures and definitions used by users.c and userrec.c
  *
- * $Id: users.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: users.h,v 1.2 2010/10/19 12:13:33 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -69,6 +69,9 @@
 extern struct user_entry_type USERENTRY_COMMENT, USERENTRY_LASTON,
   USERENTRY_XTRA, USERENTRY_INFO, USERENTRY_BOTADDR, USERENTRY_HOSTS,
   USERENTRY_PASS, USERENTRY_BOTFL;
+#ifdef TLS
+extern struct user_entry_type USERENTRY_FPRINT;
+#endif
 #endif
 
 
@@ -81,6 +84,9 @@
   int telnet_port;
   int relay_port;
   char *address;
+#ifdef TLS
+  int ssl;
+#endif
 };
 
 struct user_entry {
Index: eggdrop1.8/ssl.conf
diff -u /dev/null eggdrop1.8/ssl.conf:1.1
--- /dev/null	Tue Oct 19 06:13:44 2010
+++ eggdrop1.8/ssl.conf	Tue Oct 19 06:13:32 2010
@@ -0,0 +1,68 @@
+#
+# $Id: ssl.conf,v 1.1 2010/10/19 12:13:32 pseudo Exp $
+#
+# OpenSSL configuration file for use with Eggdrop
+# Don't edit it unless you know what you're doing.
+#
+
+####################################################################
+[ ca ]
+default_ca			= CA_default	# The default ca section
+
+####################################################################
+[ CA_default ]
+
+default_days			= 365		# how long to certify for
+default_crl_days		= 30		# how long before next CRL
+default_md			= sha1		# which md to use.
+
+####################################################################
+[ req ]
+default_bits			= 2048
+default_keyfile 		= eggdrop.key
+distinguished_name		= req_dn
+req_extensions			= v3_req
+serial				= 1337 		# value between 0 and 9999
+
+[ req_dn ]
+countryName			= Country Name (2 letter code)
+countryName_default		= EU
+countryName_min			= 2
+countryName_max			= 2
+
+stateOrProvinceName		= State or Province Name (full name)
+
+localityName			= Locality Name (eg, city)
+
+organizationName		= Organization Name (eg, company)
+organizationName_default	= Eggheads
+
+organizationalUnitName		= Organizational Unit Name (eg, section)
+organizationalUnitName_default	= Botnet
+
+commonName			= Common Name (typically your domain name)
+commonName_max			= 128
+
+emailAddress			= Your Email Address
+emailAddress_max		= 64
+
+userId				= Botnet Nick
+userId_max			= 32
+
+[ v3_req ]
+basicConstraints 		= CA:FALSE
+keyUsage 			= digitalSignature, keyEncipherment
+subjectAltName          	= @alt_names
+
+[ alt_names ]
+
+# You should specify here all possible botaddrs. To avoid confusion,
+# this is what you would use in .+bot or .chaddr.
+# Addresses could be hostnames or IPv4/v6 addresses.
+
+DNS.1   			=
+#DNS.2   			= this.bot.net
+#DNS.3   			= lamestbot.net
+#DNS.4   			= ...
+#IP.1 				= 99.99.0.0
+#IP.2 				= 2001:db8:618:5c0:263::
----------------------- End of diff -----------------------


More information about the Changes mailing list