diff -cr ../src.orig/client.c ./client.c *** ../src.orig/client.c Thu Mar 13 13:13:59 2003 --- ./client.c Wed Mar 19 13:48:55 2003 *************** *** 92,97 **** --- 92,112 ---- 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) { + log(LOG_ERR, "failed to create: %s (continuing)", c->info_fname); + c->info_fname[0] = 0; + } else { + 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; } *************** *** 184,189 **** --- 199,209 ---- log(LOG_NOTICE, "%s connected from %s:%d", c->opt->servname, c->accepting_address, ntohs(c->addr.sin_port)); } + 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->addr.sin_port)); + } return 0; /* OK */ } *************** *** 220,225 **** --- 240,274 ---- } #endif 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) *************** *** 567,572 **** --- 616,632 ---- 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 */ + log(LOG_INFO, "removed info file: %s", c->info_fname); + } + } } static void print_cipher(CLI *c) { /* print negotiated cipher */ *************** *** 584,589 **** --- 644,670 ---- if(len>0) buf[len-1]='\0'; 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)); + + 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 } *************** *** 860,865 **** --- 941,950 ---- safe_ntoa(c->connecting_address, addr.sin_addr); log(LOG_DEBUG, "%s connecting %s:%d", c->opt->servname, c->connecting_address, ntohs(addr.sin_port)); + if(c->info_file) { + fprintf(c->info_file, "TUNNEL_HOST=\"%s\"\nTUNNEL_PORT=%d\n", + c->connecting_address, ntohs(addr.sin_port)); + } if(!connect(s, (struct sockaddr *)&addr, sizeof(addr))) return s; /* no error -> success */ error=get_last_socket_error(); diff -cr ../src.orig/options.c ./options.c *** ../src.orig/options.c Thu Mar 13 13:13:59 2003 --- ./options.c Thu Mar 13 14:39:30 2003 *************** *** 555,560 **** --- 555,584 ---- 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 ../src.orig/prototypes.h ./prototypes.h *** ../src.orig/prototypes.h Thu Mar 13 13:13:59 2003 --- ./prototypes.h Thu Mar 13 15:18:55 2003 *************** *** 104,109 **** --- 104,110 ---- 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 *************** *** 228,233 **** --- 229,236 ---- FD *sock_rfd, *sock_wfd; /* Read and write socket descriptors */ FD *ssl_rfd, *ssl_wfd; /* Read and write SSL descriptors */ int sock_bytes, ssl_bytes; /* Bytes written to socket and ssl */ + FILE *info_file; /* text file with connection information */ + char info_fname[STRLEN]; /* file name (full path) for info_file */ } CLI; extern int max_clients;