diff -cr ../stunnel-4.10.orig/src/client.c src/client.c
*** ../stunnel-4.10.orig/src/client.c	2005-05-13 00:43:24.000000000 -0200
--- src/client.c	2005-05-13 01:34:36.000000000 -0200
***************
*** 94,99 ****
--- 94,114 ----
      c->opt=opt;
      c->local_rfd.fd=rfd;
      c->local_wfd.fd=wfd;
+ 
+     if(options.info_dir) {
+ 	sprintf(c->info_fname, "%s/pid.%d", options.info_dir, getpid());
+ 	c->info_file = fopen(c->info_fname, "w");
+ 	if(!c->info_file) {
+ 	    s_log(LOG_ERR, "failed to create: %s (continuing)", c->info_fname);
+ 	    c->info_fname[0] = 0;
+ 	} else {
+ 	    s_log(LOG_DEBUG, "connection detail to be written to: %s",
+ 					c->info_fname);
+ 	    fprintf(c->info_file, "# connection details\n"
+ 				"STUNNEL_PID=%d\n", getpid());
+ 	}
+     }
+ 
      return c;
  }
  
***************
*** 203,208 ****
--- 218,228 ----
          s_log(LOG_NOTICE, "%s connected from %s",
              c->opt->servname, c->accepting_address);
      }
+     if(c->info_file) {
+ 	fprintf(c->info_file, "SERVICE=\"%s\"\n", c->opt->servname);
+ 	fprintf(c->info_file, "REMOTE_HOST=\"%s\"\nREMOTE_PORT=%d\n",
+ 		c->accepting_address, ntohs(c->peer_addr.addr[0].in.sin_port));
+     }
      return 0; /* OK */
  }
  
***************
*** 237,242 ****
--- 257,289 ----
      }
  #endif
      s_log(LOG_DEBUG, "Remote FD=%d initialized", fd);
+     if(c->info_file) {
+         struct sockaddr_in addr;
+         int addrlen = sizeof(addr);
+         if(getsockname(fd, (struct sockaddr *)&addr, &addrlen)) {
+             // ignore error
+         } else {
+             char newname[STRLEN];
+     
+             /* record our end of the tunnel, and change name of file to match */
+             enter_critical_section(CRIT_NTOA); /* inet_ntoa is not mt-safe */
+                 fprintf(c->info_file, "LOCAL_HOST=\"%s\"\nLOCAL_PORT=%d\n",
+                     inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+                 sprintf(newname, "%s/conn.%s:%d",
+                     options.info_dir,
+                     inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+             leave_critical_section(CRIT_NTOA);
+     
+             /* done with file, close it now */
+             fprintf(c->info_file, "# EOF\n");
+             fclose(c->info_file);
+             c->info_file = NULL;
+     
+             /* rename so it's easy for the client to find */
+             rename(c->info_fname, newname);
+             strcpy(c->info_fname, newname);
+         }
+     }
      c->remote_fd.fd=fd;
      c->remote_fd.is_socket=1; /* Always! */
      if(set_socket_options(fd, 2)<0)
***************
*** 674,679 ****
--- 721,737 ----
                  reset(c->local_wfd.fd, "linger (local_wfd)");
         }
      }
+ 	/* Cleanup connection info file which isn't useful anymore */
+     if(options.info_dir) {
+ 	if(c->info_file) {
+ 	    fclose(c->info_file);
+ 	    c->info_file = NULL;
+ 	}
+ 	if(c->info_fname) {
+ 	    unlink(c->info_fname);		/* ignore errors */
+ 	    s_log(LOG_INFO, "removed info file: %s", c->info_fname);
+ 	}
+     }
  }
  
  static void print_cipher(CLI *c) { /* print negotiated cipher */
***************
*** 683,689 ****
  #else
      SSL_CIPHER *cipher;
      char buf[STRLEN];
!     int len;
  
      cipher=SSL_get_current_cipher(c->ssl);
      SSL_CIPHER_description(cipher, buf, STRLEN);
--- 741,748 ----
  #else
      SSL_CIPHER *cipher;
      char buf[STRLEN];
!     int len, cnt;
!     SSL_COMP *comp=NULL;
  
      cipher=SSL_get_current_cipher(c->ssl);
      SSL_CIPHER_description(cipher, buf, STRLEN);
***************
*** 691,696 ****
--- 750,809 ----
      if(len>0)
          buf[len-1]='\0';
      s_log(LOG_INFO, "Negotiated ciphers: %s", buf);
+ 
+     if(c->info_file) {
+         X509 *peer;
+     
+         fprintf(c->info_file, "CIPHER_DESC=\"%s\"\n", buf);
+         fprintf(c->info_file, "CIPHER_ALGO=\"%s\"\n",
+                                         SSL_CIPHER_get_name(cipher));
+         fprintf(c->info_file, "CIPHER_BITS=%d\n",
+                                         SSL_CIPHER_get_bits(cipher, NULL));
+         // Show compression info
+         if (c->ssl->ctx->comp_methods == NULL) {
+             // No compression methods available
+             fprintf(c->info_file, "No compression methods available\n");
+         } else {
+             int cntMethods = sk_SSL_COMP_num(c->ssl->ctx->comp_methods);
+             fprintf(c->info_file, "%d compression method(s) available:\n", cntMethods);
+             for (cnt=0; cnt<cntMethods; cnt++) {
+                 comp=sk_SSL_COMP_value(c->ssl->ctx->comp_methods, cnt);
+                 fprintf(c->info_file, "%d\t%s ", comp->id, comp->name);
+                 switch (comp->id) {
+                     case 0xe0:
+                         fprintf(c->info_file, "(zlib)\n"); break;
+                     case 0xe1:
+                         fprintf(c->info_file, "(rle)\n"); break;
+                     default:
+                         fprintf(c->info_file, "(unknown)\n"); break;
+                 }
+             }
+         }
+         if (c->ssl->s3->tmp.new_compression == NULL) {
+             fprintf(c->info_file, "SSL_COMP=NULL\n");
+         } else {
+             fprintf(c->info_file, "SSL_COMP.id=%d ",
+                                             c->ssl->s3->tmp.new_compression->id);
+             switch (comp->id) {
+                 case 0xe0:
+                     fprintf(c->info_file, "(zlib)\n"); break;
+                 case 0xe1:
+                     fprintf(c->info_file, "(rle)\n"); break;
+                 default:
+                     fprintf(c->info_file, "(unknown)\n"); break;
+             }
+         }
+         peer = SSL_get_peer_certificate(c->ssl);
+         if(peer) {
+             X509_NAME_oneline(X509_get_subject_name(peer), buf, STRLEN);
+             fprintf(c->info_file, "SSL_CLIENT_DN=\"%s\"\n", buf);
+     
+             X509_NAME_oneline(X509_get_issuer_name(peer), buf, STRLEN);
+             fprintf(c->info_file, "SSL_CLIENT_I_DN=\"%s\"\n", buf);
+     
+             X509_free(peer);
+         }
+     }
  #endif
  }
  
***************
*** 953,958 ****
--- 1066,1075 ----
          s_ntop(c->connecting_address, &addr);
          s_log(LOG_DEBUG, "%s connecting %s",
              c->opt->servname, c->connecting_address);
+         if(c->info_file) {
+             fprintf(c->info_file, "TUNNEL_HOST=\"%s\"\nTUNNEL_PORT=%d\n",
+                         c->connecting_address, ntohs(addr.in.sin_port));
+         }
          if(!connect(s, &addr.sa, addr_len(addr)))
              return s; /* no error -> success (should not be possible) */
          error=get_last_socket_error();
Only in src: client.c.orig
Only in src: client.c~
diff -cr ../stunnel-4.10.orig/src/options.c src/options.c
*** ../stunnel-4.10.orig/src/options.c	2005-05-13 00:43:24.000000000 -0200
--- src/options.c	2005-05-13 00:44:16.000000000 -0200
***************
*** 664,669 ****
--- 664,693 ----
          break;
      }
  
+     /* infodir */
+     switch(cmd) {
+     case CMD_INIT:
+         options.info_dir=NULL;
+         break;
+     case CMD_EXEC:
+         if(strcasecmp(opt, "infodir"))
+             break;
+         if(arg[0]) { /* not empty */
+ 	    if(strlen(arg) > STRLEN - 20) return "infodir pathname too long";
+             options.info_dir=stralloc(arg);
+         } else {
+             options.info_dir=NULL;
+ 	}
+         return NULL; /* OK */
+     case CMD_DEFAULT:
+         break;
+     case CMD_HELP:
+         log_raw("%-15s = writable directory to store connection info into",
+             "infodir");
+         break;
+     }
+ 
+ 
      if(cmd==CMD_EXEC)
          return option_not_found;
      return NULL; /* OK */
diff -cr ../stunnel-4.10.orig/src/prototypes.h src/prototypes.h
*** ../stunnel-4.10.orig/src/prototypes.h	2005-05-13 00:43:24.000000000 -0200
--- src/prototypes.h	2005-05-13 00:47:03.000000000 -0200
***************
*** 113,118 ****
--- 113,119 ----
      int verify_level;
      int verify_use_only_my;
      long ssl_options;
+     char *info_dir;                         /* directory for connection info */
  
          /* some global data for stunnel.c */
  #ifndef USE_WIN32
***************
*** 264,269 ****
--- 265,272 ----
      FD *ssl_rfd, *ssl_wfd; /* Read and write SSL descriptors */
      int sock_bytes, ssl_bytes; /* Bytes written to socket and ssl */
      s_poll_set fds; /* File descriptors */
+     FILE *info_file; /* text file with connection information */
+     char info_fname[STRLEN]; /* file name (full path) for info_file */
  } CLI;
  
  extern int max_clients;
***************
*** 305,311 ****
  /**************************************** Prototypes for sthreads.c */
  
  typedef enum {
!     CRIT_KEYGEN, CRIT_INET, CRIT_CLIENTS, CRIT_WIN_LOG, CRIT_SESSION,
      CRIT_SECTIONS
  } SECTION_CODE;
  
--- 308,314 ----
  /**************************************** Prototypes for sthreads.c */
  
  typedef enum {
!     CRIT_KEYGEN, CRIT_INET, CRIT_CLIENTS, CRIT_WIN_LOG, CRIT_SESSION, CRIT_NTOA,
      CRIT_SECTIONS
  } SECTION_CODE;
  
