Просмотр исходного кода

* Initial commit for ssl server support
* Added myipstr(int 4/6)
* Increased cmd_dccstat to 40 for host field
* Various other improvements and fixes


svn: 154

Bryan Drewery 22 лет назад
Родитель
Сommit
1c4a192291
15 измененных файлов с 349 добавлено и 55 удалено
  1. 5 1
      Makefile.in
  2. 1 0
      misc/maketype
  3. 12 0
      src/botnet.c
  4. 2 0
      src/chanprog.c
  5. 4 0
      src/dcc.c
  6. 6 6
      src/dccutil.c
  7. 20 4
      src/eggdrop.h
  8. 9 5
      src/main.c
  9. 0 9
      src/main.h
  10. 1 1
      src/misc.c
  11. 4 3
      src/mod/module.h
  12. 20 6
      src/mod/server.mod/servmsg.c
  13. 5 3
      src/modules.c
  14. 254 16
      src/net.c
  15. 6 1
      src/proto.h

+ 5 - 1
Makefile.in

@@ -142,7 +142,11 @@ clean-modconfig:
 reconfig: clean-modconfig config
 
 packconf:
-	@cp -f pack/settings.c src/settings.c
+	@rm -f src/settings.c
+	@echo "/* DO NOT EDIT THIS FILE DIRECTLY, EDIT pack/settings.c */" > src/settings.c
+	@echo " " >> src/settings.c
+	@cat pack/settings.c >> src/settings.c
+#	@cp -f pack/settings.c src/settings.c
 
 utils:  packconf
 	@cd src && $(MAKE_UTILS) ../stringfix

+ 1 - 0
misc/maketype

@@ -5,6 +5,7 @@ if test ! -f stamp.$1
 then
   flist="`find src -name \*.c`"
   cfiles="`grep -l \"def [H|L][U|E][B|A]\" $flist`"
+  echo "[*] Cleaning up files for $1 build"
   for s in $cfiles 
   do
     bleh="`echo $s | cut -d / -f 2`";

+ 12 - 0
src/botnet.c

@@ -1061,6 +1061,18 @@ static void botlink_resolve_success(int i)
 #endif /* USE_IPV6 */
 		      dcc[i].port) < 0)
     failed_link(i);
+  else { /* let's attempt to initiate SSL before ANYTHING else... */
+#ifdef HAVE_SSL
+/*    if (!ssl_link(dcc[i].sock, CONNECT_SSL)) {
+      debug2("back from ssl_link(%d, %d) for botlink (failed)", dcc[i].sock, CONNECT_SSL);
+      dcc[i].ssl = 0;
+      putlog(LOG_BOTS, "*", "SSL link for '%s' failed", dcc[i].nick); 
+    } else */
+      dcc[i].ssl = 1;
+#else
+      dcc[i].ssl = 0;
+#endif /* HAVE_SSL */
+  }
 }
 
 static void failed_tandem_relay(int idx)

+ 2 - 0
src/chanprog.c

@@ -547,6 +547,8 @@ void chanprog()
 
   /* cache our ip on load instead of every 30 seconds -zip */
   cache_my_ip();
+  sdprintf("ip4: %s", myipstr(4));
+  sdprintf("ip6: %s", myipstr(6));
   conmask = 0;
   /* Turn off read-only variables (make them write-able) for rehash */
   protect_readonly = 0;

+ 4 - 0
src/dcc.c

@@ -363,6 +363,7 @@ static void cont_link(int idx, char *buf, int ii)
         }
       }
     }
+//.    ssl_link(dcc[idx].sock, CONNECT_SSL);
     dcc[idx].type = &DCC_BOT_NEW;
     dcc[idx].u.bot->numver = 0;
     dprintf(idx, "%s\n", botnetnick);
@@ -1234,6 +1235,7 @@ static void dcc_telnet(int idx, char *buf, int i)
   sock = answer(dcc[idx].sock, s, &ip, &port, 0);
   while ((sock == -1) && (errno == EAGAIN))
     sock = answer(sock, s, &ip, &port, 0);
+//. ssl_link ACCEPT_SSL should go here!!!!
   if (sock < 0) {
     neterror(s);
     putlog(LOG_MISC, "*", DCC_FAILED, s);
@@ -1312,6 +1314,7 @@ static void dcc_telnet_hostresolved(int i)
     lostdcc(i);
     return;
   }
+//.  ssl_link(dcc[i].sock, ACCEPT_SSL);
 
   changeover_dcc(i, &DCC_IDENTWAIT, 0);
   dcc[i].timeval = now;
@@ -2053,6 +2056,7 @@ void dcc_telnet_got_ident(int i, char *host)
   /* This is so we dont tell someone doing a portscan anything
    * about ourselves. <cybah>
    */
+//n  ssl_link(dcc[i].sock, ACCEPT_SSL);
 #ifdef HUB
   dprintf(i, "\n");
 #else

+ 6 - 6
src/dccutil.c

@@ -415,19 +415,19 @@ void tell_dcc(int zidx)
   }
   if(nicklen < 9) nicklen = 9;
   
-  egg_snprintf(format, sizeof format, "%%-4s %%-8s %%-5s %%-%us %%-25s %%s\n", 
+  egg_snprintf(format, sizeof format, "%%-4s %%-8s %%-5s %%-%us %%-40s %%s\n", 
                           nicklen);
   dprintf(zidx, format, "SOCK", "ADDR",     "PORT",  "NICK", "HOST", "TYPE");
   dprintf(zidx, format, "----", "--------", "-----", "---------", 
-                        "-------------------------", "----");
+                        "----------------------------------------", "----");
 
-  egg_snprintf(format, sizeof format, "%%-4d %%08X %%5d %%-%us %%-25s %%s\n", 
+  egg_snprintf(format, sizeof format, "%%-4d %%08X %%5d %%-%us %%-40s %%s\n", 
                           nicklen);
   /* Show server */
   for (i = 0; i < dcc_total; i++) {
     j = strlen(dcc[i].host);
-    if (j > 25)
-      j -= 25;
+    if (j > 40)
+      j -= 40;
     else
       j = 0;
     if (dcc[i].type && dcc[i].type->display)
@@ -710,7 +710,7 @@ Context;
       else {
         idx = new_dcc(&DCC_TELNET, 0);
         dcc[idx].addr = notalloc;
-        strcpy(dcc[idx].addr6, getmyip6());
+        strcpy(dcc[idx].addr6, myipstr(6));
         dcc[idx].port = port;
         dcc[idx].sock = i6;
         dcc[idx].timeval = now;

+ 20 - 4
src/eggdrop.h

@@ -9,6 +9,18 @@
 #ifndef _EGG_EGGDROP_H
 #define _EGG_EGGDROP_H
 
+#ifdef HAVE_OPENSSL_SSL_H
+# ifndef SSL_INC
+#  include <openssl/ssl.h>
+#  include <openssl/rand.h>
+#  include <openssl/err.h>
+#  include <openssl/md5.h>
+#  define SSL_INC
+# endif /* ! SSL_INC */
+# define HAVE_SSL 1
+#endif /* HAVE_OPENSSL_SSL_H */
+
+
 /*
  * Enable IPv6 support?
  */
@@ -128,10 +140,6 @@
 #  include "error_you_need_vsprintf_to_compile_eggdrop"
 #endif
 
-#ifdef HAVE_OPENSSL_SSL_H
-#  define HAVE_SSL
-#endif /* HAVE_OPENSSL_SSL_H */
-
 /* IPv6 sanity checks. */
 #ifdef USE_IPV6
 #  ifndef HAVE_IPV6
@@ -321,6 +329,7 @@ struct dcc_t {
   char addr6[121];              /* easier.. ipv6 address in regular notation (3ffe:80c0:225::) */
 #endif /* USE_IPV6 */
   unsigned int port;
+  int ssl;			/* use ssl on this dcc? */
   struct userrec *user;
   char simulbot[NICKLEN];	/* used for hub->leaf cmd simulation, holds bot that results should be sent to */
   time_t simultime;		/* the time when the simul dcc is initiated, expires after a number of seconds */
@@ -595,6 +604,9 @@ struct dupwait_info {
 #define DET_SUICIDE 4
 #define DET_NOCHECK 5
 
+#define CONNECT_SSL 1
+#define ACCEPT_SSL 2
+
 /* Structure for internal logs */
 typedef struct {
   char *filename;
@@ -721,6 +733,10 @@ typedef struct {
 #ifdef USE_IPV6
   unsigned int af;
 #endif /* USE_IPV6 */
+#ifdef HAVE_SSL
+  SSL 		*ssl;
+#endif /* HAVE_SSL */
+
 } sock_list;
 #ifdef S_DCCPASS
 typedef struct cmd_pass {

+ 9 - 5
src/main.c

@@ -181,9 +181,14 @@ void fatal(const char *s, int recoverable)
   if (s[0])
     putlog(LOG_MISC, "*", "* %s", s);
 /*  flushlogs(); */
-  for (i = 0; i < dcc_total; i++)
+  for (i = 0; i < dcc_total; i++) {
     if (dcc[i].sock >= 0)
       killsock(dcc[i].sock);
+#ifdef HAVE_SSL
+      ssl_cleanup();
+#endif /* HAVE_SSL */
+
+  }
   if (!recoverable) {
     unlink(pid_file);
     bg_send_quit(BG_ABORT);
@@ -415,6 +420,7 @@ static void got_hup(int z)
  */
 static void got_alarm(int z)
 {
+  debug0("got alarm...");
   longjmp(alarmret, 1);
 
   /* -Never reached- */
@@ -940,10 +946,7 @@ void crontab_create(int interval) {
   if ((fd = mkstemp(tmpfile)) == -1) {
     unlink(tmpfile);
     return;
-  } else { /* FIXME: is this absolutely necesary? */
-    unlink(tmpfile);
-    close(fd);
-  }
+  } 
 
   sprintf(buf, STR("crontab -l | grep -v \"%s\" | grep -v \"^#\" | grep -v \"^\\$\"> %s"), binname, tmpfile);
   if (shell_exec(buf, NULL, NULL, NULL) && (f = fdopen(fd, "a")) != NULL) {
@@ -969,6 +972,7 @@ void crontab_create(int interval) {
     sprintf(buf, STR("crontab %s"), tmpfile);
     shell_exec(buf, NULL, NULL, NULL);
   }
+  close(fd);
   unlink(tmpfile);
 
 }

+ 0 - 9
src/main.h

@@ -76,15 +76,6 @@
 #ifdef HAVE_ZLIB_H
 #  include <zlib.h>
 #endif /* HAVE_ZLIB_H */
-#ifdef HAVE_OPENSSL_SSL_H
-# ifndef SSL_INC
-//#  include <openssl/rand.h>
-#  include <openssl/ssl.h>
-#  include <openssl/err.h>
-#  include <openssl/md5.h>
-#  define SSL_INC
-# endif /* ! SSL_INC */
-#endif /* HAVE_OPENSSL_SSL_H */
 
 #ifndef MAKING_MODS
 #  include "proto.h"

+ 1 - 1
src/misc.c

@@ -1876,7 +1876,7 @@ int shell_exec(char *cmdline, char *input, char **output, char **erroutput)
 /* Update system code
  */
 int ucnt = 0;
-static void updatelocal(void)
+void updatelocal(void)
 {
 #ifdef LEAF
   module_entry *me;

+ 4 - 3
src/mod/module.h

@@ -267,7 +267,7 @@
 #define findanyidx ((int (*)(int))global[130])
 #define findchan ((struct chanset_t *(*)(char *))global[131])
 /* 132 - 135 */
-#define cmd_die (global[132])
+/* 132 -- UNUSED */
 #define days ((void (*)(time_t,time_t,char *))global[133])
 #define daysago ((void (*)(time_t,time_t,char *))global[134])
 #define daysdur ((void (*)(time_t,time_t,char *))global[135])
@@ -539,8 +539,9 @@
 #define putbot ((void (*)(char *, char *))global[332])
 /* 333 - 335 */
 #define putallbots ((void (*)(char *))global[333])
-
-
+#define ssl_link ((int (*) (int, int))global[334])
+#define dropssl ((void (*) (int))global[335])
+#define myipstr ((char*(*)(int))global[336])
 
 /* This is for blowfish module, couldnt be bothered making a whole new .h
  * file for it ;)

+ 20 - 6
src/mod/server.mod/servmsg.c

@@ -52,10 +52,13 @@ Context;
 Context;
     p++;
 Context;
-    if (!*p)
+    if (!*p) {
+Context;
       altnick_char = 'a' + random() % 26;
-    else
+    } else {
+Context;
       altnick_char = (*p);
+    }
 Context;
     botname[l] = altnick_char;
   }
@@ -1662,6 +1665,21 @@ static void server_resolve_success(int servidx)
       fatal("NO SERVERS WILL ACCEPT MY CONNECTION.", 0);
   } else {
     dcc[servidx].sock = serv;
+#ifdef HAVE_SSL
+    if (!ssl_link(dcc[servidx].sock, CONNECT_SSL)) {
+      dcc[servidx].ssl = 0;
+      putlog(LOG_SERV, "*", "SSL for '%s' failed", dcc[servidx].host);
+    } else {
+      putlog(LOG_SERV, "*", "SSL for '%s' successful", dcc[servidx].host);
+      dcc[servidx].ssl = 1;
+    }
+#else
+      dcc[servidx].ssl = 0;
+#endif /* HAVE_SSL */
+#ifdef S_NODELAY
+    i = 1;
+    setsockopt(serv, 6, TCP_NODELAY, &i, sizeof(i));
+#endif /* S_NODELAY */
     /* Queue standard login */
     dcc[servidx].timeval = now;
     SERVER_SOCKET.timeout_val = &server_timeout;
@@ -1674,10 +1692,6 @@ static void server_resolve_success(int servidx)
     dprintf(DP_MODE, "NICK %s\n", botname);
     dprintf(DP_MODE, "USER %s . . :%s\n", botuser, botrealname);
     /* Wait for async result now */
-#ifdef S_NODELAY
-    i = 1;
-    setsockopt(serv, 6, TCP_NODELAY, &i, sizeof(i));
-#endif
   }
 }
 #endif

+ 5 - 3
src/modules.c

@@ -39,7 +39,6 @@ extern party_t *party;
 extern int parties;
 extern sock_list        *socklist;
 
-int cmd_die();
 int xtra_kill();
 int xtra_unpack();
 static int module_rename(char *name, char *newname);
@@ -315,7 +314,7 @@ Function global_table[] =
   (Function) findanyidx,
   (Function) findchan,
   /* 132 - 135 */
-  (Function) cmd_die,
+  (Function) 0,
   (Function) days,
   (Function) daysago,
   (Function) daysdur,
@@ -581,7 +580,10 @@ Function global_table[] =
   (Function) hostprotocol,
   (Function) sdprintf,
   (Function) putbot,
-  (Function) putallbots
+  (Function) putallbots,
+  (Function) ssl_link,
+  (Function) dropssl,
+  (Function) myipstr
 
 
 };

+ 254 - 16
src/net.c

@@ -44,6 +44,12 @@ extern unsigned long	 otraffic_irc_today, otraffic_bn_today,
 			 otraffic_dcc_today, otraffic_filesys_today,
 			 otraffic_trans_today, otraffic_unknown_today;
 
+
+#ifdef HAVE_SSL
+  SSL_CTX 		*ssl_c_ctx = NULL, *ssl_s_ctx = NULL;
+  char 			*tls_rand_file = NULL;
+#endif /* HAVE_SSL */
+
 union sockaddr_union cached_myip4_so;
 #ifdef USE_IPV6
 union sockaddr_union cached_myip6_so;
@@ -166,6 +172,38 @@ int get_ip(char *hostname, union sockaddr_union *so)
 #endif /* USE_IPV6 */
 }
 
+#ifdef HAVE_SSL
+int seed_PRNG(void)
+{
+  char stackdata[1024];
+  static char rand_file[300];
+  FILE *fh = 0;
+#if OPENSSL_VERSION_NUMBER >= 0x00905100
+  if (RAND_status()) return 0;
+#endif
+  if ((fh = fopen("/dev/urandom", "r"))) {
+    fclose(fh);
+    return 0;
+  }
+  if (RAND_file_name(rand_file, sizeof(rand_file)))
+    tls_rand_file = rand_file;
+  else
+    return 1;
+  if (!RAND_load_file(rand_file, 1024)) {
+    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;
+#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100 */
+  return 0;
+}
+#endif /* HAVE_SSL */
+
 /* Initialize the socklist
  */
 void init_net()
@@ -174,10 +212,39 @@ void init_net()
 
   for (i = 0; i < MAXSOCKS; i++) {
     bzero(&socklist[i], sizeof(socklist[i]));
+#ifdef HAVE_SSL
+    socklist[i].ssl=NULL;
+#endif /* HAVE_SSL */
     socklist[i].flags = SOCK_UNUSED;
   }
+#ifdef HAVE_SSL
+  SSL_load_error_strings();
+  OpenSSL_add_ssl_algorithms();
+  ssl_c_ctx = SSL_CTX_new(SSLv23_client_method());
+  ssl_s_ctx = SSL_CTX_new(SSLv23_server_method());
+  if (!ssl_c_ctx || !ssl_s_ctx)
+    fatal("SSL Inititlization failed", 0);
+  if (seed_PRNG())
+    fatal("SSL PRNG seeding failed!", 0);
+#endif /* HAVE_SSL */
 }
 
+#ifdef HAVE_SSL
+int ssl_cleanup() {
+ if (ssl_c_ctx) {
+    SSL_CTX_free(ssl_c_ctx);
+    ssl_c_ctx = NULL;
+  }
+  if (ssl_s_ctx) {
+    SSL_CTX_free(ssl_s_ctx);
+    ssl_s_ctx = NULL;
+  }
+  if (tls_rand_file) RAND_write_file(tls_rand_file);
+ return 0;
+}
+#endif /* HAVE_SSL */
+
+
 int expmem_net()
 {
   int i, tot = 0;
@@ -193,18 +260,27 @@ int expmem_net()
   return tot;
 }
 
-/* Get my ipv6 ip
+/* Get my ipv? ip
  */
-char *getmyip6()
+char *myipstr(int af_type)
 {
+
 #ifdef USE_IPV6
-  static char s[UHOSTLEN + 1];
-  egg_inet_ntop(AF_INET6, &cached_myip6_so.sin6.sin6_addr, s, 119);
-  s[120] = 0;
-  return s;
-#else
-  return "";
+  if (af_type == 6) {
+    static char s[UHOSTLEN + 1];
+    egg_inet_ntop(AF_INET6, &cached_myip6_so.sin6.sin6_addr, s, 119);
+    s[120] = 0;
+    return s;
+  } else
 #endif /* USE_IPV6 */
+    if (af_type == 4) {
+      static char s[UHOSTLEN + 1];
+      egg_inet_ntop(AF_INET, &cached_myip4_so.sin.sin_addr, s, 119);
+      s[120] = 0;
+      return s;
+    }
+
+  return "";
 }
 
 /* Get my ip number
@@ -380,6 +456,9 @@ int allocsock(int sock, int options)
       /* yay!  there is table space */
       socklist[i].inbuf = socklist[i].outbuf = NULL;
       socklist[i].inbuflen = socklist[i].outbuflen = 0;
+#ifdef HAVE_SSL
+      socklist[i].ssl = NULL;
+#endif /* HAVE_SSL */
       socklist[i].flags = options;
       socklist[i].sock = sock;
       socklist[i].encstatus = 0;
@@ -434,6 +513,27 @@ int getsock(int options)
   return sock;
 }
 
+void dropssl(register int sock)
+{
+#ifdef HAVE_SSL
+  int i;
+
+  if (sock < 0)
+    return;
+  for (i = 0; (i < MAXSOCKS); i++)
+    if (socklist[i].sock == sock) break;
+
+  if (socklist[i].ssl) {
+    SSL_set_quiet_shutdown(socklist[i].ssl, 1);
+    SSL_shutdown(socklist[i].ssl);
+    usleep(1000 * 500);
+    SSL_free(socklist[i].ssl);
+    usleep(1000 * 500);
+    socklist[i].ssl = NULL;
+  }
+#endif /* HAVE_SSL */
+}
+
 /* Done with a socket
  */
 void real_killsock(register int sock, const char *file, int line)
@@ -445,6 +545,7 @@ void real_killsock(register int sock, const char *file, int line)
     return;
   for (i = 0; i < MAXSOCKS; i++) {
     if ((socklist[i].sock == sock) && !(socklist[i].flags & SOCK_UNUSED)) {
+      dropssl(sock);
       close(socklist[i].sock);
       if (socklist[i].inbuf != NULL) {
 	nfree(socklist[i].inbuf);
@@ -622,6 +723,7 @@ int open_telnet_raw(int sock, char *server, int sport)
   /* Synchronous? :/ */
   if (firewall[0])
     return proxy_connect(sock, server, sport, proxy);
+
   return sock;
 }
 
@@ -748,6 +850,74 @@ inline int open_listen_by_af(int *port, int af_def)
 #endif /* USE_IPV6 */
 }
 
+#ifdef HAVE_SSL
+int ssl_link(register int sock, int state)
+{
+  int err = 0, i = 0, errs = 0;
+
+  debug2("ssl_link(%d, %d)", sock, state);
+  for (i = 0; (i < MAXSOCKS); i++) {		
+    if (socklist[i].sock == sock) break;
+  }
+  if (socklist[i].ssl) {
+    putlog(LOG_ERROR, "*", "Switching to SSL (%d,%d) - already active", state, sock);
+    return 0;
+  }
+  if (state == CONNECT_SSL) {
+    socklist[i].ssl = SSL_new(ssl_c_ctx);
+  } else if (state == ACCEPT_SSL) {
+    socklist[i].ssl = SSL_new(ssl_s_ctx);
+  }
+  if (!socklist[i].ssl) {
+    putlog(LOG_ERROR, "*", "Switching to SSL (%d) - SSL_new(%d) failed", sock, state);
+    return 0;
+  }
+  if (!SSL_set_fd(socklist[i].ssl, socklist[i].sock)) {
+    putlog(LOG_ERROR, "*", "SSL_set_fd(%d) (%d) failed", state, socklist[i].sock);
+    return 0;
+  }
+  if (state == CONNECT_SSL) {
+    SSL_set_connect_state(socklist[i].ssl);
+  } else if (state == ACCEPT_SSL) {
+    SSL_set_accept_state(socklist[i].ssl);
+  } else {
+    putlog(LOG_DEBUG, "*" "ssl_link(%d, 0?) NO STATE?", sock);
+    return 0;
+  }
+
+  if (state == CONNECT_SSL) {
+    err = SSL_connect(socklist[i].ssl);
+  } else if (state == ACCEPT_SSL) {
+    err = SSL_accept(socklist[i].ssl);
+  }
+  if (!setjmp(alarmret)) {
+      alarm(5); /* this is plenty of time */
+      while ((err < 1) && (errno == EAGAIN)) {
+        if (state == CONNECT_SSL) {
+          err = SSL_connect(socklist[i].ssl);
+        } else if (state == ACCEPT_SSL) {
+          err = SSL_accept(socklist[i].ssl);
+        }
+        if ((errs!=SSL_ERROR_WANT_READ)&&(errs!=SSL_ERROR_WANT_WRITE)&& (errs!=SSL_ERROR_WANT_X509_LOOKUP))
+          break; /* anything not one of these is a sufficient condition to break out... */
+      }
+      alarm(0);
+  }
+      errs = SSL_get_error(socklist[i].ssl, err);
+        putlog(LOG_DEBUG, "*", "SSL_link(%d, %d) = %d, errs: %d (%d), %s", sock, state, err, errs, errno, (char *)ERR_error_string(ERR_get_error(), NULL));
+        if (errno) putlog(LOG_DEBUG, "*", "errno %d: %s", errno, strerror(errno));
+  if (err == 1) {
+    putlog(LOG_ERROR, "*", "SSL_link(%d, %d) was successfull", sock, state);
+    return 1;
+  } else {
+    putlog(LOG_ERROR, "*", "SSL_link(%d, %d) failed", sock, state);
+    dropssl(socklist[i].sock);
+  }
+  return 0;
+}
+#endif /* HAVE_SSL */
+
+
 /* Given a network-style IP address, returns the hostname. The hostname
  * will be in the "##.##.##.##" format if there was an error.
  * 
@@ -962,10 +1132,11 @@ static int sockread(char *s, int *len)
   if (x > 0) {
     /* Something happened */
     for (i = 0; i < MAXSOCKS; i++) {
-      if ((!(socklist[i].flags & SOCK_UNUSED)) &&
-	  ((FD_ISSET(socklist[i].sock, &fd)) ||
-	  ((socklist[i].sock == STDOUT) && (!backgrd) &&
-	  (FD_ISSET(STDIN, &fd))))) {
+      if ((!(socklist[i].flags & SOCK_UNUSED)) && ((FD_ISSET(socklist[i].sock, &fd)) ||
+#ifdef HAVE_SSL
+          ((socklist[i].ssl) && (SSL_pending(socklist[i].ssl))) ||
+#endif /* HAVE_SSL */
+	  ((socklist[i].sock == STDOUT) && (!backgrd) && (FD_ISSET(STDIN, &fd))))) {
 	if (socklist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) {
 	  /* Listening socket -- don't read, just return activity */
 	  /* Same for connection attempt */
@@ -977,6 +1148,12 @@ static int sockread(char *s, int *len)
 	    debug1("net: connect! sock %d", socklist[i].sock);
 	    s[0] = 0;
 	    *len = 0;
+#ifdef HAVE_SSL
+/*            debug0("CALLING SSL_LINK() FROM SOCKREAD");
+            if (!ssl_link(socklist[i].sock))
+              debug0("SSL_LINK FAILED");
+            debug0("BACK FROM SSL_LINK()"); */
+#endif /* HAVE_SSL */
 	    return i;
 	  }
 	} else if (socklist[i].flags & SOCK_PASS) {
@@ -987,8 +1164,29 @@ static int sockread(char *s, int *len)
 	errno = 0;
 	if ((socklist[i].sock == STDOUT) && !backgrd)
 	  x = read(STDIN, s, grab);
-	else
-	  x = read(socklist[i].sock, s, grab);
+	else {
+#ifdef HAVE_SSL
+          if (socklist[i].ssl) {
+            x = SSL_read(socklist[i].ssl, s, grab);
+            if (x < 0) {
+              int err = SSL_get_error(socklist[i].ssl, x);
+              x = -1;
+              switch (err) {
+                case SSL_ERROR_WANT_READ:
+                  errno = EAGAIN;
+                  break;
+                case SSL_ERROR_WANT_WRITE:
+                  errno = EAGAIN;
+                  break;
+                case SSL_ERROR_WANT_X509_LOOKUP:
+                  errno = EAGAIN;
+                  break;
+              }
+            }
+          } else 
+#endif /* HAVE_SSL */
+            x = read(socklist[i].sock, s, grab);
+        }
 	if (x <= 0) {		/* eof */
 	  if (errno != EAGAIN) { /* EAGAIN happens when the operation would block 
 				    on a non-blocking socket, if the socket is going
@@ -1379,14 +1577,34 @@ void tputs(register int z, char *s, unsigned int len)
 	return;
       }
       /* Try. */
-#ifdef HAVE_ZLIB_H
+#ifdef HAVE_SSL
+      if (socklist[i].ssl) {
+        x = SSL_write(socklist[i].ssl, s, len);
+        if (x < 0) {
+          int err = SSL_get_error(socklist[i].ssl, x);
+          x = -1;
+          switch (err) {
+            case SSL_ERROR_WANT_READ:
+              errno = EAGAIN;
+              break;
+            case SSL_ERROR_WANT_WRITE:
+              errno = EAGAIN;
+              break;
+            case SSL_ERROR_WANT_X509_LOOKUP:
+              errno = EAGAIN;
+              break;
+          }
+        }
+      } else
+#endif /* HAVE_SSL */
+//#ifdef HAVE_ZLIB_H
 //      if (socklist[i].gz) { 		/* gzipped links */
 //        FILE *fp;
 //        fp = gzdopen(z, "wb0");
 //        x = gzwrite(fp, s, len);
 //        
 //      } else
-#endif /* HAVE_ZLIB_H */
+//#endif /* HAVE_ZLIB_H */
         x = write(z, s, len);
       if (x == (-1))
 	x = 0;
@@ -1462,6 +1680,26 @@ void dequeue_sockets()
 	(socklist[i].outbuf != NULL) && (FD_ISSET(socklist[i].sock, &wfds))) {
       /* Trick tputs into doing the work */
       errno = 0;
+#ifdef HAVE_SSL
+      if (socklist[i].ssl) {
+        x = write(socklist[i].sock, socklist[i].outbuf, socklist[i].outbuflen);
+        if (x < 0) {
+          int err = SSL_get_error(socklist[i].ssl, x);
+          x = -1;
+          switch (err) {
+            case SSL_ERROR_WANT_READ:
+              errno = EAGAIN;
+              break;
+            case SSL_ERROR_WANT_WRITE:
+              errno = EAGAIN;
+              break;
+            case SSL_ERROR_WANT_X509_LOOKUP:
+              errno = EAGAIN;
+              break;
+          }
+        }
+      } else
+#endif
       x = write(socklist[i].sock, socklist[i].outbuf, socklist[i].outbuflen);
       if ((x < 0) && (errno != EAGAIN)
 #ifdef EBADSLT

+ 6 - 1
src/proto.h

@@ -282,9 +282,13 @@ void set_cmd_pass(char *, int);
 
 
 /* net.c */
+#ifdef HAVE_SSL
+int ssl_cleanup();
+int ssl_link(int, int);
+#endif /* HAVE_SSL */
 IP my_atoul(char *);
 unsigned long iptolong(IP);
-char *getmyip6();
+char *myipstr(int);
 IP getmyip();
 void cache_my_ip();
 void neterror(char *);
@@ -298,6 +302,7 @@ int getsock(int);
 int sockprotocol(int);
 int hostprotocol(char *);
 char *hostnamefromip(unsigned long);
+void dropssl(int);
 void real_killsock(int, const char *, int);
 int answer(int, char *, unsigned long *, unsigned short *, int);
 inline int open_listen(int *);