Only in stunnel-3.22-sg1: .#protocol.c Only in stunnel-3.22-sg1: Makefile Only in stunnel-3.22-sg1: TAGS Only in stunnel-3.22-sg1: _usr diff -ur stunnel-3.22/client.c stunnel-3.22-sg1/client.c --- stunnel-3.22/client.c Sun Dec 23 14:41:32 2001 +++ stunnel-3.22-sg1/client.c Sun May 12 03:23:27 2002 @@ -220,7 +220,9 @@ else c->ip=0; /* Setup c->remote_fd, now */ - if(options.option&OPT_REMOTE) + if (options.option&OPT_FDS) + fd=options.use_fd; + else if(options.option&OPT_REMOTE) fd=connect_remote(c); else /* NOT in remote mode */ fd=connect_local(c); @@ -867,7 +869,9 @@ log(LOG_ERR, "Select timeout (fdprintf)"); return -1; } - written=writesocket(fd, line+ptr, towrite); + +/* written=writesocket(fd, line+ptr, towrite); */ + written = write(fd, line+ptr, towrite); if(written<0) { sockerror("writesocket (fdprintf)"); return -1; Only in stunnel-3.22-sg1: client.c~ Only in stunnel-3.22-sg1: client.o Only in stunnel-3.22-sg1: config.log Only in stunnel-3.22-sg1: config.status Only in stunnel-3.22-sg1: log.o Only in stunnel-3.22-sg1: openssl.cnf diff -ur stunnel-3.22/options.c stunnel-3.22-sg1/options.c --- stunnel-3.22/options.c Sun Dec 23 15:08:51 2001 +++ stunnel-3.22-sg1/options.c Sun May 12 05:05:09 2002 @@ -69,7 +69,7 @@ options.verify_use_only_my=0; options.debug_level=5; #ifndef USE_WIN32 - options.facility=LOG_DAEMON; + options.facility=LOG_DAEMON; #endif options.session_timeout=300; options.cipher_list=NULL; @@ -84,8 +84,9 @@ options.random_bytes=RANDOM_BYTES; options.output_file=NULL; options.local_ip=NULL; + options.chroot_dir=NULL; opterr=0; - while ((c = getopt(argc, argv, "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:O:E:R:WB:VP:S:o:I:")) != EOF) + while ((c = getopt(argc, argv, "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:O:E:R:WB:VP:S:o:I:F:/:i")) != EOF) switch (c) { case 'A': safecopy(options.cert_file,optarg); @@ -140,6 +141,16 @@ case 'f': options.option|=OPT_FOREGROUND; break; + case 'F': + options.option|=OPT_FDS; + options.use_fd=atoi(optarg); + break; + case 'i': + options.option|=OPT_SUID_FIRST; + break; + case '/': + options.chroot_dir=optarg; + break; case 'T': options.option|=OPT_TRANSPARENT; break; @@ -257,8 +268,8 @@ print_info(); } #endif - if(!(options.option&(OPT_REMOTE|OPT_PROGRAM))) { - log(LOG_ERR, "Either -r, -l (or -L) option must be used"); + if(!(options.option&(OPT_REMOTE|OPT_PROGRAM|OPT_FDS))) { + log(LOG_ERR, "Either -r, -l (or -L), or -F option must be used"); print_info(); } if((options.option&OPT_REMOTE) && (options.option&OPT_PROGRAM) Only in stunnel-3.22-sg1: options.c~ Only in stunnel-3.22-sg1: options.o diff -ur stunnel-3.22/protocol.c stunnel-3.22-sg1/protocol.c --- stunnel-3.22/protocol.c Thu Dec 20 02:52:37 2001 +++ stunnel-3.22-sg1/protocol.c Sat May 11 15:07:14 2002 @@ -131,32 +131,177 @@ return 0; } +#define PP_BUFSIZE 8192 +static int plaintext_proxy(CLI *c) +{ + fd_set rd_set, wr_set; + char rbuf[PP_BUFSIZE]; + int rbufend,rdone; + char lbuf[PP_BUFSIZE]; + int lbufend,ldone; + struct timeval tv; + int ready; + int fdmax; + int howmuch, sofar; + + fdmax = c->remote_fd; + if (c->local_wfd > fdmax) + fdmax = c->local_wfd; + if (c->local_rfd > fdmax) + fdmax = c->local_rfd; + fdmax++; + + lbufend = rbufend = 0; + rdone = ldone = 0; + + tv.tv_sec = 86400; + tv.tv_usec = 0; + while( !( (rdone || ldone) && (!rbufend && !lbufend) ) ) { + log(LOG_DEBUG,"rdone=%d, ldone=%d, rbufend=%d, lbufend=%d",rdone,ldone,rbufend,lbufend); + FD_ZERO(&rd_set); + FD_ZERO(&wr_set); + if (rbufend) + FD_SET((c->local_wfd),&wr_set); + else if (!rdone) + FD_SET(c->remote_fd,&rd_set); + + if (lbufend) + FD_SET(c->remote_fd,&wr_set); + else if (!ldone) + FD_SET(c->local_rfd,&rd_set); + + do { /* Skip "Interrupted system call" errors */ + ready=select(fdmax, &rd_set, &wr_set, NULL, &tv); + } while(ready<0 && get_last_socket_error()==EINTR); + + if(ready<0) { /* Break the connection for others */ + sockerror("select"); + c->error=1; + return 1; + } + if(!ready) { /* Timeout */ + log(LOG_DEBUG, "select timeout - connection reset"); + c->error=1; + return 1; + } + + if (lbufend > 0) { + if (FD_ISSET(c->remote_fd,&wr_set)) + { + sofar = 0; + while (sofar < lbufend) { + if ((howmuch=write(c->remote_fd,lbuf+sofar,lbufend-sofar)) < 0) { + sockerror("write"); + c->error=1; + return 1; + } + sofar += howmuch; + } + lbufend = 0; + } + } else { + if (FD_ISSET(c->local_rfd,&rd_set)) { + if ( (lbufend = read(c->local_rfd,lbuf,PP_BUFSIZE)) < 0) { + sockerror("read"); + c->error = 1; + return 1; + } + if (lbufend == 0) /* EOF */ + { + log(LOG_DEBUG,"EOF reading from local"); + ldone=1; + } + } + } + + if (rbufend > 0) { + if (FD_ISSET(c->local_wfd, &wr_set)) { + sofar = 0; + while (sofar < rbufend) { + if ( (howmuch = write(c->local_wfd, rbuf + sofar, rbufend - sofar)) < 0) { + sockerror("write"); + c->error=1; + return 1; + } + sofar += howmuch; + } + rbufend = 0; + } + } else { + if (FD_ISSET(c->remote_fd,&rd_set)) { + if ( (rbufend = read(c->remote_fd,rbuf,PP_BUFSIZE)) < 0) { + sockerror("read"); + c->error = 1; + return 1; + } + if (rbufend == 0) /* EOF */ { + log(LOG_DEBUG,"EOF reading from remote"); + rdone=1; + } + } + } + } + + log(LOG_DEBUG, "plaintext_proxy finished normally."); + return 0; +} + static int smtp_server(CLI *c) { char line[STRLEN]; + int fdscanf_ret; if(RFC2487(c->local_rfd)==0) return 0; /* Return if RFC 2487 is not used */ - if(fdscanf(c->remote_fd, "220%[^\n]", line)!=1) { + if(fdscanf(c->remote_fd, "220%[^\r\n]", line)!=1) { log(LOG_ERR, "Unknown server welcome"); return -1; } if(fdprintf(c->local_wfd, "220%s + stunnel", line)<0) return -1; - if(fdscanf(c->local_rfd, "EHLO %[^\n]", line)!=1) { - log(LOG_ERR, "Unknown client EHLO"); - return -1; + + /* See if we get an EHLO command */ + if (((fdscanf_ret=fdscanf(c->local_rfd, "%[^\r\n]", line)) != 1) || + (strlen(line) < 4) || + (line[4] && !isspace(line[4])) || + (strncasecmp(line,"ehlo",4) != 0) ) + { + if ((fdscanf_ret == 1) && line[0]) + fdprintf(c->remote_fd,"%s",line); + exit(plaintext_proxy(c)); + } + if (fdprintf(c->remote_fd,"%s",line) < 0) + return -1; + while ( (fdscanf(c->remote_fd,"%[^\r\n]", line) == 1) + && (line[3] == '-') ) { + if (fdprintf(c->local_wfd, "%s",line) < 0) + return -1; } - if(fdprintf(c->local_wfd, "250-%s Welcome", line)<0) - return -1; - if(fdprintf(c->local_wfd, "250 STARTTLS")<0) - return -1; - if(fdscanf(c->local_rfd, "STARTTLS", line)<0) { - log(LOG_ERR, "STARTTLS expected"); - return -1; + line[3] = '-'; + fdprintf(c->local_wfd,"%s",line); + fdprintf(c->local_wfd,"250 STARTTLS"); + + /* See if we get a STARTTLS command */ + if (((fdscanf_ret=fdscanf(c->local_rfd, "%[^\r\n]", line)) != 1) || + (strlen(line) < 8) || + (line[8] && !isspace(line[8])) || + (strncasecmp(line,"starttls",8) != 0) ) + { + if ((fdscanf_ret==1) && line[0]) + fdprintf(c->remote_fd,"%s",line); + exit(plaintext_proxy(c)); + } + + if (line[8]) { + fdprintf(c->local_wfd,"501 Syntax error (no parameters allowed; STARTTLS disabled) (#5.5.4)"); + exit(plaintext_proxy(c)); } - if(fdprintf(c->local_wfd, "220 Go ahead", line)<0) + + if(fdprintf(c->local_wfd, "220 Go ahead")<0) return -1; + + /* Technically, we should shut down the SMTP connection and get + * a new one, but screw it for now. */ return 0; } Only in stunnel-3.22-sg1: protocol.c~ Only in stunnel-3.22-sg1: protocol.o diff -ur stunnel-3.22/prototypes.h stunnel-3.22-sg1/prototypes.h --- stunnel-3.22/prototypes.h Sun Nov 11 14:16:01 2001 +++ stunnel-3.22-sg1/prototypes.h Sun May 12 05:00:52 2002 @@ -79,6 +79,8 @@ #define OPT_REMOTE 0x20 #define OPT_TRANSPARENT 0x40 #define OPT_PTY 0x80 +#define OPT_FDS 0x100 +#define OPT_SUID_FIRST 0x200 typedef struct { char pem[STRLEN]; /* pem (priv key/cert) filename */ @@ -111,6 +113,8 @@ int cert_defaults; char *output_file; u32 *local_ip; + int use_fd; + char *chroot_dir; } server_options; typedef enum { Only in stunnel-3.22-sg1: prototypes.h~ Only in stunnel-3.22-sg1: pty.o diff -ur stunnel-3.22/ssl.c stunnel-3.22-sg1/ssl.c --- stunnel-3.22/ssl.c Sun Dec 23 14:46:03 2001 +++ stunnel-3.22-sg1/ssl.c Sun May 12 04:00:01 2002 @@ -46,6 +46,7 @@ #include #include #include +#include #else #include #include @@ -71,7 +72,13 @@ SSL_CTX *ctx; /* global SSL context */ void context_init() { /* init SSL */ + LHASH *config = NULL; + long errline; + if (getenv("OPENSSL_CONF")) + { + CONF_load(config,getenv("OPENSSL_CONF"),&errline); + } if(!init_prng()) log(LOG_INFO, "PRNG seeded successfully"); SSLeay_add_ssl_algorithms(); Only in stunnel-3.22-sg1: ssl.c~ Only in stunnel-3.22-sg1: ssl.o Only in stunnel-3.22-sg1: sthreads.o Only in stunnel-3.22-sg1: stunnel diff -ur stunnel-3.22/stunnel.c stunnel-3.22-sg1/stunnel.c --- stunnel-3.22/stunnel.c Thu Dec 20 02:53:54 2001 +++ stunnel-3.22-sg1/stunnel.c Sun May 12 05:15:45 2002 @@ -54,6 +54,8 @@ static void create_pid(); static void delete_pid(); #endif +void do_setugid(char *user, char *group); +int is_alldigits(char *s); /* Socket functions */ static int listen_local(); @@ -119,8 +121,25 @@ if(!(options.option&OPT_FOREGROUND)) options.foreground=0; log_open(); + if (options.chroot_dir) + { + log(LOG_DEBUG,"chroot(%s)",options.chroot_dir); + if (chroot(options.chroot_dir) < 0) + { + ioerror("chroot"); + exit(1); + } + + if (chdir("/") < 0) + { + ioerror("chdir"); + exit(1); + } + } + if (options.option&OPT_SUID_FIRST) + do_setugid(options.setuid_user,options.setgid_group); log(LOG_NOTICE, "Using '%s' as tcpwrapper service name", options.servname); - + /* check if certificate exists */ if(options.option&OPT_CERT) { if(stat(options.pem, &st)) { @@ -682,4 +701,79 @@ return retval; } +void do_setugid(char *user, char *group) + { + uid_t uid; + gid_t gid; + +#ifndef USE_WIN32 + if(group) { + struct group *gr; + gid_t gr_list[1]; + + if (is_alldigits(group)) + { + gid=atoi(group); + } + else + { + gr=getgrnam(group); + if(!gr) { + log(LOG_ERR, "Failed to get GID for group %s", + options.setgid_group); + exit(1); + } + gid = gr->gr_gid; + } + + if(setgid(gid)) { + sockerror("setgid"); + exit(1); + } + gr_list[0]=gid; + if(setgroups(1, gr_list)) { + sockerror("setgroups"); + exit(1); + } + } +#endif + + if(user) { + struct passwd *pw; + + if (is_alldigits(user)) + { + uid = atoi(user); + } + else + { + pw=getpwnam(options.setuid_user); + if(!pw) { + log(LOG_ERR, "Failed to get UID for user %s", + options.setuid_user); + exit(1); + } + uid=pw->pw_uid; + } + +#ifndef USE_WIN32 + /* gotta chown that pid file, or we can't remove it. */ + if ( options.pidfile[0] && chown( options.pidfile, uid, -1) ) { + log(LOG_ERR, "Failed to chown pidfile %s", options.pidfile); + } +#endif + if(setuid(uid)) { + sockerror("setuid"); + exit(1); + } + } + } + +int is_alldigits(char *s) { + while (*s) + if (!isdigit(*s++)) + return 0; + return 1; +} + /* End of stunnel.c */ Only in stunnel-3.22-sg1: stunnel.c~ Only in stunnel-3.22-sg1: stunnel.o Only in stunnel-3.22-sg1: stunnel.pem Binary files stunnel-3.22/stunnel.rnd and stunnel-3.22-sg1/stunnel.rnd differ Only in stunnel-3.22-sg1: stunnel.so Only in stunnel-3.22-sg1: typescript