--- pathexec.h.orig	Mon Jun 12 22:39:50 2006
+++ pathexec.h	Sun May 21 13:05:57 2006
@@ -2,9 +2,11 @@
 
 #ifndef PATHEXEC_H
 #define PATHEXEC_H
+#include "stralloc.h"
 
 extern void pathexec_run(const char *,char * const *,char * const *);
 extern int pathexec_env(const char *,const char *);
+extern int pathexec_multienv(stralloc *);
 extern void pathexec(char * const *);
 
 #endif
--- pathexec_env.c.orig	Mon Jun 12 22:39:50 2006
+++ pathexec_env.c	Sun May 21 13:05:57 2006
@@ -22,6 +22,12 @@
   return stralloc_cat(&plus,&tmp);
 }
 
+int pathexec_multienv(stralloc *sa)
+{
+  if (!sa) return 1;
+  return stralloc_cat(&plus,sa);
+}
+
 void pathexec(char * const *argv)
 {
   char **e;
--- ssl.h.orig	Mon Jun 12 22:39:50 2006
+++ ssl.h	Sun May 21 13:05:57 2006
@@ -20,7 +20,7 @@
 extern int ssl_params(SSL_CTX *,const char *,int);
 extern int ssl_server_env(SSL *,stralloc *);
 extern int ssl_client_env(SSL *,stralloc *);
-extern void ssl_error_str();
+extern char *ssl_error_str(int);
 extern int ssl_error(int (*)(const char *));
 
 #define ssl_client() (ssl_context(SSLv23_client_method()))
--- sslserver.c.orig	Mon Jun 12 22:39:50 2006
+++ sslserver.c	Mon Jun 12 22:39:19 2006
@@ -4,6 +4,7 @@
 #include <sys/param.h>
 #include <netdb.h>
 #include <openssl/ssl.h>
+#include <fcntl.h>
 #include <arpa/inet.h>
 #include "ssl.h"
 #include "uint16.h"
@@ -39,10 +40,10 @@
 #include "auto_certfile.h"
 #include "auto_keyfile.h"
 #include "auto_ciphers.h"
+#include "fmt.h"
 
 int verbosity = 1;
 int flagkillopts = 1;
-int flagafter = 0;
 int flagdelay = 0;
 const char *banner = "";
 int flagremoteinfo = 1;
@@ -51,6 +52,7 @@
 int flagclientcert = 0;
 int flagsslenv = 0;
 int flagtcpenv = 0;
+int flagsslwait = 0;
 unsigned long timeout = 26;
 unsigned long ssltimeout = 26;
 unsigned int progtimeout = 3600;
@@ -72,6 +74,9 @@
 char *remotehost = 0;
 char *verifyhost = 0;
 
+unsigned long uid = 0;
+unsigned long gid = 0;
+
 char strnum[FMT_ULONG];
 char strnum2[FMT_ULONG];
 
@@ -106,6 +111,8 @@
 X509 *cert;
 char buf[SSL_NAME_LEN];
 
+#define FATAL "sslserver: fatal: "
+
 
 /* ---------------------------- child */
 
@@ -180,7 +187,96 @@
   int j;
   SSL *ssl;
   int wstat;
+  int sslctl[2];
+  char *s;
+  long tmp_long;
+  char ssl_cmd;
+  stralloc ssl_env = { 0 };
+  int bytesleft;
+  char envbuf[8192];
+  
+  if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
+  if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
+  if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: ");
+  
+  switch(fork()) {
+    case -1:
+      strerr_die2sys(111,DROP,"unable to fork: ");
+    case 0:
+      /* Child */
+      break;
+    default:
+      /* Parent */
+      
+      close(pi[0]); close(po[1]); close(sslctl[1]);
+
+      if ((s=env_get("SSL_CHROOT")))
+        if (chroot(s) == -1)
+          strerr_die2x(111,DROP,"unable to chroot");
+      
+      if ((s=env_get("SSL_GID"))) {
+        scan_ulong(s,&tmp_long);
+        gid = tmp_long;
+      }
+      if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,FATAL,"unable to set gid: ");
+
+      if ((s=env_get("SSL_UID"))) {
+        scan_ulong(s,&tmp_long);
+        uid = tmp_long;
+      }
+      if (uid) if (prot_uid(uid) == -1)
+        strerr_die2sys(111,FATAL,"unable to set uid: ");
 
+      /* Read the TLS command socket.  This will block until/unless
+       * TLS is requested.
+       */
+      if (read(sslctl[0],&ssl_cmd,1) == 1) {
+        ssl = ssl_new(ctx,t);
+        if (!ssl) strerr_die2x(111,DROP,"unable to create SSL instance");
+        if (ndelay_on(t) == -1)
+          strerr_die2sys(111,DROP,"unable to set socket options: ");
+        if (ssl_timeoutaccept(ssl,ssltimeout) == -1)
+          strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno));
+      }
+        
+      if (verbosity >= 2) {
+        strnum[fmt_ulong(strnum,getpid())] = 0;
+        strerr_warn3("sslserver: ssl ",strnum," accept ",0);
+      }
+        
+      if (flagclientcert) {
+        switch(ssl_verify(ssl,verifyhost)) {
+          case -1:
+            strerr_die2x(111,DROP,"unable to verify client certificate");
+          case -2:
+            strerr_die2x(111,DROP,"no client certificate");
+          case -3:
+            strerr_die2x(111,DROP,"client name does not match certificate");
+          default: break;
+        }
+      }
+      
+      if (ssl_cmd == 'Y') {
+        ssl_server_env(ssl, &ssl_env);
+        if(!stralloc_0(&ssl_env)) drop_nomem(); /* Add another NUL */
+        env("SSLCTL",ssl_env.s); 
+
+        for(bytesleft = ssl_env.len; bytesleft>0; bytesleft-=j)
+          if ( (j=write(sslctl[0], ssl_env.s, bytesleft)) < 0)
+            strerr_die2sys(111, FATAL, "unable to write SSL environment: ");
+      }
+
+      if (ssl_cmd == 'Y' || ssl_cmd == 'y') {
+        if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0)
+          strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno));
+        if (wait_nohang(&wstat) > 0)
+          _exit(wait_exitcode(wstat)); 
+        ssl_close(ssl);
+      }
+      _exit(0);
+  }
+
+  /* Child-only below this point */
   remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0;
 
   if (verbosity >= 2) {
@@ -278,59 +374,11 @@
 
   if (flagdeny) _exit(100);
 
-  if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
-  if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: ");
-
-  ssl = ssl_new(ctx,t);
-  if (!ssl) strerr_die2x(111,DROP,"unable to create SSL instance");
-  if (ndelay_on(t) == -1)
-    strerr_die2sys(111,DROP,"unable to set socket options: ");
-  if (ssl_timeoutaccept(ssl,ssltimeout) == -1) {
-    strerr_warn2(DROP,"unable to SSL accept:",&strerr_sys);
-    ssl_error(error_warn);
-    ssl_close(ssl);
-    _exit(111);
-  }
-
-  if (verbosity >= 2) {
-    strnum[fmt_ulong(strnum,getpid())] = 0;
-    strerr_warn3("sslserver: ssl ",strnum," accept ",0);
-  }
-
-  if (flagclientcert) {
-    switch(ssl_verify(ssl,verifyhost)) {
-      case -1:
-	strerr_die2x(111,DROP,"unable to verify client certificate");
-      case -2:
-	strerr_die2x(111,DROP,"no client certificate");
-      case -3:
-	strerr_die2x(111,DROP,"client name does not match certificate");
-      default: break;
-    }
-  }
+  if (gid) if (prot_gid(gid) == -1)
+    strerr_die2sys(111,FATAL,"unable to set gid: ");
+  if (uid) if (prot_uid(uid) == -1)
+    strerr_die2sys(111,FATAL,"unable to set uid: ");
 
-  switch(j = fork()) {
-    case -1:
-      strerr_die2sys(111,DROP,"unable to fork: ");
-    case 0:
-      break;
-    default:
-      sig_ignore(sig_pipe);
-      sig_uncatch(sig_child);
-      sig_unblock(sig_child);
-      close(pi[0]); close(po[1]);
-      if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) {
-	strerr_warn2(DROP,"unable to speak SSL:",&strerr_sys);
-	ssl_error(error_warn);
-	ssl_close(ssl);
-	wait_pid(&wstat,j);
-	_exit(111);
-      }
-      ssl_close(ssl);
-      if (wait_pid(&wstat,j) > 0)
-	_exit(wait_exitcode(wstat));
-      _exit(0);
-  }
   close(pi[1]); close(po[0]);
 
   sig_uncatch(sig_child);
@@ -338,13 +386,32 @@
   sig_uncatch(sig_term);
   sig_uncatch(sig_pipe);
 
-  if (flagsslenv && !ssl_server_env(ssl,0)) drop_nomem();
-  ssl_close(ssl);  
-
-  if (fd_move(0,pi[0]) == -1)
-    strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
-  if (fd_move(1,po[1]) == -1)
-    strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
+  if (fcntl(sslctl[1],F_SETFD,0) == -1)
+    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
+  strnum[fmt_ulong(strnum,sslctl[1])]=0;
+  env("SSLCTLFD",strnum);
+
+  if (fcntl(pi[0],F_SETFD,0) == -1)
+    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
+  strnum[fmt_ulong(strnum,pi[0])]=0;
+  env("SSLREADFD",strnum);
+
+  if (fcntl(po[1],F_SETFD,0) == -1)
+    strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag");
+  strnum[fmt_ulong(strnum,po[1])]=0;
+  env("SSLWRITEFD",strnum);
+
+  if (flagsslwait) {
+    if (fd_copy(0,t) == -1)
+      strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
+    if (fd_copy(1,t) == -1)
+      strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
+  } else {
+    if (fd_move(0,pi[0]) == -1)
+      strerr_die2sys(111,DROP,"unable to set up descriptor 0: ");
+    if (fd_move(1,po[1]) == -1)
+      strerr_die2sys(111,DROP,"unable to set up descriptor 1: ");
+  }
 
   if (flagkillopts)
     socket_ipoptionskill(t);
@@ -357,6 +424,22 @@
       strerr_die2sys(111,DROP,"unable to print banner: ");
   }
 
+  if (!flagsslwait) {
+    ssl_cmd = flagsslenv ? 'Y' : 'y';
+    if (write(sslctl[1], &ssl_cmd, 1) < 1)
+      strerr_die2sys(111,DROP,"unable to start SSL: ");
+    if (flagsslenv) {
+      while ((j=read(sslctl[1],envbuf,8192)) > 0) {
+        stralloc_catb(&ssl_env,envbuf,j);
+        if (ssl_env.len >= 2 && ssl_env.s[ssl_env.len-2]==0 && ssl_env.s[ssl_env.len-1]==0)
+          break;
+      }
+      if (j < 0)
+        strerr_die2sys(111,DROP,"unable to read SSL environment: ");
+      pathexec_multienv(&ssl_env);
+    }
+  }
+      
   pathexec(prog);
   strerr_die4sys(111,DROP,"unable to run ",*prog,": ");
 }
@@ -365,13 +448,11 @@
 
 /* ---------------------------- parent */
 
-#define FATAL "sslserver: fatal: "
-
 void usage(void)
 {
   strerr_warn1("\
 sslserver: usage: sslserver \
-[ -13UXpPhHrRoOdDqQviIeEsS ] \
+[ -13UXpPhHrRoOdDqQviIeEsSnN ] \
 [ -c limit ] \
 [ -x rules.cdb ] \
 [ -B banner ] \
@@ -392,8 +473,6 @@
 int flag1 = 0;
 int flag3 = 0;
 unsigned long backlog = 20;
-unsigned long uid = 0;
-unsigned long gid = 0;
 
 void printstatus(void)
 {
@@ -449,7 +528,7 @@
   int s;
   int t;
  
-  while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:T:u:g:l:b:B:c:pPoO3IiEeSsaAw:")) != opteof)
+  while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:T:u:g:l:b:B:c:pPoO3IiEeSsw:nN")) != opteof)
     switch(opt) {
       case 'b': scan_ulong(optarg,&backlog); break;
       case 'c': scan_ulong(optarg,&limit); break;
@@ -485,8 +564,8 @@
       case 's': flagsslenv = 1; break;
       case 'E': flagtcpenv = 0; break;
       case 'e': flagtcpenv = 1; break;
-      case 'A': flagafter = 0; break;
-      case 'a': flagafter = 1; break;
+      case 'n': flagsslwait = 1; break;
+      case 'N': flagsslwait = 0; break;
       default: usage();
     }
   argc -= optind;
@@ -523,6 +602,8 @@
 
   if (x = env_get("CCAFILE")) ccafile = x;
   if (ccafile && str_equal(ccafile,"")) ccafile = 0;
+
+  if (env_get("CCAVERIFY")) flagclientcert = 1;
   if (!flagclientcert) ccafile = 0;
 
   if (x = env_get("CADIR")) cadir = x;
@@ -566,13 +647,6 @@
     strerr_die2sys(111,FATAL,"unable to listen: ");
   ndelay_off(s);
 
-  if (!flagafter) {
-    if (gid) if (prot_gid(gid) == -1)
-      strerr_die2sys(111,FATAL,"unable to set gid: ");
-    if (uid) if (prot_uid(uid) == -1)
-      strerr_die2sys(111,FATAL,"unable to set uid: ");
-  }
-
   localportstr[fmt_ulong(localportstr,localport)] = 0;
   if (flag1) {
     buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace);
@@ -603,13 +677,6 @@
   if (!ssl_params(ctx,dhfile,rsalen))
     strerr_die2x(111,FATAL,"unable to set cipher parameters");
 
-  if (flagafter) {
-    if (gid) if (prot_gid(gid) == -1)
-      strerr_die2sys(111,FATAL,"unable to set gid: ");
-    if (uid) if (prot_uid(uid) == -1)
-      strerr_die2sys(111,FATAL,"unable to set uid: ");
-  }
-
   if (!ssl_ciphers(ctx,ciphers))
     strerr_die2x(111,FATAL,"unable to set cipher list");
 
@@ -624,8 +691,9 @@
     strerr_warn6("sslserver: param ",strnum," ",dhfile," ",strnum2,0);
   }
 
-  close(0);
-  close(1);
+  close(0); open_read("/dev/null");
+  close(1); open_append("/dev/null");
+
   printstatus();
  
   for (;;) {
@@ -650,3 +718,11 @@
     close(t);
   }
 }
+
+/* taken from 0.68 */
+char *ssl_error_str(int e)
+{
+  SSL_load_error_strings();
+  return ERR_error_string(e,0);
+}
+
--- ssl_ca.c.orig	Mon Jun 12 22:39:50 2006
+++ ssl_ca.c	Sun May 21 13:07:05 2006
@@ -6,6 +6,15 @@
   if (!SSL_CTX_load_verify_locations(ctx,certfile,certdir)) return 0;
 
   SSL_CTX_set_verify_depth(ctx,d);
+       /* HJHJ */
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+       X509_STORE *store;
+       if( (store=SSL_CTX_get_cert_store(ctx)) != NULL )
+               { X509_STORE_set_flags( store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); }
+       else
+               { return 0; }
+#endif
+       /* HJHJ */
 
   return 1;
 }
--- ssl_cca.c.orig	Mon Jun 12 22:39:50 2006
+++ ssl_cca.c	Sun May 21 13:07:40 2006
@@ -13,6 +13,7 @@
   SSL_CTX_set_client_CA_list(ctx,x);
 
   SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,0);
+  SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);
 
   return 1;
 }
