--- FILES 14 Jun 2002 08:47:30 -0000 1.1.1.1 +++ FILES 5 Apr 2004 15:34:57 -0000 1.2 @@ -216,3 +216,19 @@ warn-auto.sh warn-shsgr x86cpuid.c +addcr.1 +argv0.1 +date@.1 +delcr.1 +finger@.1 +fixcrio.1 +http@.1 +mconnect.1 +recordio.1 +tcpcat.1 +tcpclient.1 +tcprules.1 +tcprulescheck.1 +tcpserver.1 +who@.1 +tcp-environ.5 --- Makefile 14 Jun 2002 08:47:30 -0000 1.1.1.1 +++ Makefile 5 Apr 2004 15:34:57 -0000 1.3 @@ -1,5 +1,13 @@ # Don't edit Makefile! Use conf-* for configuration. +DEFINES=-DWITH_SSL +#add -DWITH_SSL to enable ssl support + +# LIBS for additional libraries and INCS for additional includes +LIBS=-lcrypto -lssl +#INCS=-I/usr/local/include +OPENSSLBIN=openssl + SHELL=/bin/sh default: it @@ -745,7 +753,7 @@ load tcpserver.o rules.o remoteinfo.o timeoutconn.o cdb.a dns.a \ time.a unix.a byte.a socket.lib ./load tcpserver rules.o remoteinfo.o timeoutconn.o cdb.a \ - dns.a time.a unix.a byte.a `cat socket.lib` + dns.a time.a unix.a byte.a $(LIBS) `cat socket.lib` tcpserver.o: \ compile tcpserver.c uint16.h str.h byte.h fmt.h scan.h ip4.h fd.h \ @@ -754,7 +762,7 @@ socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h \ stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h \ taia.h - ./compile tcpserver.c + ./compile $(DEFINES) $(INCS) tcpserver.c time.a: \ makelib iopause.o tai_pack.o taia_add.o taia_approx.o taia_frac.o \ @@ -835,3 +843,21 @@ | sed s}HOME}"`head -1 conf-home`"}g \ > who@ chmod 755 who@ + +clean: + rm -f `cat TARGETS` + +cert: + ${OPENSSLBIN} req -new -x509 -nodes \ + -out cert.pem -days 366 \ + -keyout cert.pem + +cert-req: + ${OPENSSLBIN} req -new -nodes \ + -out req.pem \ + -keyout cert.pem + @echo + @echo "Send req.pem to your CA to obtain signed_req.pem, and do:" + @echo "cat signed_req.pem >> `head -1 conf-qmail`/control/cert.pem" + + --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ addcr.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,22 @@ +.TH addcr 1 +.SH NAME +addcr \- add a CR before each LF +.SH SYNOPSIS +.B addcr +.SH DESCRIPTION +.B addcr +inserts CR at the end of each line of input. +It does not insert CR at the end of a partial final line. +.SH COMPATIBILITY +Some vendors ship +.B unix2dos +or +.B bsd2dos +tools similar to +.BR addcr . +Those tools often blow up on long lines and nulls. +.B addcr +has no trouble with long lines and nulls. +.SH "SEE ALSO" +delcr(1), +fixcrio(1) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ argv0.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,47 @@ +.TH argv0 1 +.SH NAME +argv0 \- run a program with a specified 0th argument +.SH SYNOPSIS +.B argv0 +.I realname +.I zero +[ +.I arg ... +] +.SH DESCRIPTION +.B argv0 +runs +the program stored as +.I realname +on disk, +with the given +arguments. +It sets the 0th argument of +the program to +.IR zero . + +For example, + +.EX + argv0 /bin/csh -bin/csh +.EE + +runs +.B /bin/csh +with a 0th argument of +.BR -bin/csh . +.B csh +will think it is a login shell +and behave accordingly. + +.B argv0 +can be used to run some +.B inetd +wrappers under +.BR tcpserver . +.SH "SEE ALSO" +csh(1), +tcpserver(1), +execve(2), +execvp(3), +inetd(8) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ date@.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,32 @@ +.TH date@ 1 +.SH NAME +date@ \- print the date on a host +.SH SYNTAX +.B date@ +[ +.I host +] +.SH DESCRIPTION +.B date@ +connects to TCP port 13 (Daytime) on +.I host +and prints any data it receives. +It removes CR and converts unprintable characters to a visible format. + +If +.I host +is not supplied, +.B date@ +connects to the local host. + +Some computers respond to port 13 with a human-readable date. +For example, they may be running + +.EX + tcpserver 0 13 date & +.EE +.SH "SEE ALSO" +cat(1), +delcr(1), +tcpclient(1), +tcpserver(1) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ delcr.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,30 @@ +.TH delcr 1 +.SH NAME +delcr \- remove a CR before each LF +.SH SYNOPSIS +.B delcr +.SH DESCRIPTION +.B delcr +removes a CR at the end of each line of input, +if a CR is present. +It also removes a CR at the end of a partial final line. + +The pipeline + +.EX + addcr | delcr +.EE + +prints an exact copy of its input. +.SH COMPATIBILITY +Some vendors ship +.B dos2unix +or +.B dos2bsd +tools similar to +.BR delcr . +Those tools often blow up on long lines and nulls. +.B delcr +has no trouble with long lines and nulls. +.SH "SEE ALSO" +addcr(1) --- error.h 14 Jun 2002 08:47:31 -0000 1.1.1.1 +++ error.h 6 Nov 2003 09:47:05 -0000 1.2 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ finger@.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,45 @@ +.TH finger@ 1 +.SH NAME +finger@ \- get user information from a host +.SH SYNTAX +.B finger@ +[ +.I host +[ +.I user +] +] +.SH DESCRIPTION +.B finger@ +connects to TCP port 79 (Finger) on +.IR host , +sends +.I user +(with an extra CR) +to +.IR host , +and prints any data it receives. +It removes CR and converts unprintable characters to a visible format. +Some computers respond to port 79 with information about +.IR user . + +If +.I user +is not supplied, +.B finger@ +sends a blank line to +.IR host . +Some computers respond with information about +all the users who are logged in. + +If +.I host +is not supplied, +.B finger@ +connects to the local host. +.SH "SEE ALSO" +addcr(1), +cat(1), +delcr(1), +finger(1), +tcpclient(1) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ fixcrio.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,15 @@ +.TH fixcrio 1 +.SH NAME +fixcrio \- make sure that there is a CR before each LF +.SH SYNOPSIS +.B fixcrio +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B fixcrio +inserts CR at the end of each line of input where a CR is not already present. +It does not insert CR at the end of a partial final line. +.SH "SEE ALSO" +addcr(1) --- hier.c 14 Jun 2002 08:47:32 -0000 1.1.1.1 +++ hier.c 5 Apr 2004 15:34:57 -0000 1.2 @@ -2,8 +2,11 @@ void hier() { - h(auto_home,-1,-1,02755); - d(auto_home,"bin",-1,-1,02755); + h(auto_home,-1,-1,0755); + d(auto_home,"bin",-1,-1,0755); + d(auto_home,"man",-1,-1,0755); + d(auto_home,"man/man1",-1,-1,0755); + d(auto_home,"man/man5",-1,-1,0755); c(auto_home,"bin","tcpserver",-1,-1,0755); c(auto_home,"bin","tcprules",-1,-1,0755); @@ -22,4 +27,21 @@ c(auto_home,"bin","delcr",-1,-1,0755); c(auto_home,"bin","fixcrio",-1,-1,0755); c(auto_home,"bin","rblsmtpd",-1,-1,0755); + + c(auto_home,"man/man1","addcr.1",-1,-1,0644); + c(auto_home,"man/man1","argv0.1",-1,-1,0644); + c(auto_home,"man/man1","date@.1",-1,-1,0644); + c(auto_home,"man/man1","delcr.1",-1,-1,0644); + c(auto_home,"man/man1","finger@.1",-1,-1,0644); + c(auto_home,"man/man1","fixcrio.1",-1,-1,0644); + c(auto_home,"man/man1","http@.1",-1,-1,0644); + c(auto_home,"man/man1","mconnect.1",-1,-1,0644); + c(auto_home,"man/man1","recordio.1",-1,-1,0644); + c(auto_home,"man/man1","tcpcat.1",-1,-1,0644); + c(auto_home,"man/man1","tcpclient.1",-1,-1,0644); + c(auto_home,"man/man1","tcprules.1",-1,-1,0644); + c(auto_home,"man/man1","tcprulescheck.1",-1,-1,0644); + c(auto_home,"man/man1","tcpserver.1",-1,-1,0644); + c(auto_home,"man/man1","who@.1",-1,-1,0644); + c(auto_home,"man/man5","tcp-environ.5",-1,-1,0644); } --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ http@.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,52 @@ +.TH http@ 1 +.SH NAME +http@ \- get a web page from a host through HTTP +.SH SYNTAX +.B http@ +[ +.I host +[ +.I page +[ +.I port +] +] +] +.SH DESCRIPTION +.B http@ +connects to +.I port +on +.IR host , +sends +.B GET /\fIpage +(with an extra CR) +to +.IR host , +and prints any data it receives, +removing CR from the end of each line. + +If +.I port +is not supplied, +.B http@ +uses port 80 (HTTP). + +If +.I page +is not supplied, +.B http@ +sends +.B GET / +to +.IR host . + +If +.I host +is not supplied, +.B http@ +connects to the local host. +.SH "SEE ALSO" +addcr(1), +delcr(1), +tcpclient(1) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ mconnect.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,36 @@ +.TH mconnect 1 +.SH NAME +mconnect \- connect to the SMTP server on a host +.SH SYNTAX +.B mconnect +[ +.I host +[ +.I port +] +] +.SH DESCRIPTION +.B mconnect +connects to +.I port +on +.IR host . +It sends its input to +.IR host , +adding a CR to each line. +Meanwhile it prints anything it receives from +.IR host . + +If +.I port +is not supplied, +.B mconnect +uses port 25 (SMTP). + +If +.I host +is not supplied, +.B mconnect +connects to the local host. +.SH "SEE ALSO" +tcpclient(1) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ recordio.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,75 @@ +.TH recordio 1 +.SH NAME +recordio \- record the input and output of a program +.SH SYNTAX +.B recordio +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B recordio +runs +.I program +with the given arguments. +It prints lines to stderr +showing the input and output of +.IR program . + +At the beginning of each line on stderr, +.B recordio +inserts the +.I program +process ID, +along with +.B < +for input or +.B > +for output. +At the end of each line it inserts a space, a plus sign, or [EOF]; +a space indicates that there was a newline in the input or output, +and [EOF] indicates the end of input or output. + +.B recordio +prints every packet of input and output immediately. +It does not attempt to combine packets into coherent stderr lines. +For example, + +.EX + recordio sh -c 'cat /dev/fd/8 2>&1' > /dev/null +.EE + +could produce + +.EX + 5135 > cat: /dev/fd/8: Bad file descriptor +.br + 5135 > [EOF] +.EE + +or + +.EX + 5135 > cat: + +.br + 5135 > /dev/fd/8+ +.br + 5135 > : + +.br + 5135 > Bad file descriptor +.br + 5135 > [EOF] +.EE + +.B recordio +uses several lines for long packets +to guarantee that each line is printed atomically to stderr. + +.B recordio +runs as a child of +.IR program . +It exits when it sees the end of +.IR program 's +output. +.SH "SEE ALSO" +tcpserver(1) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tcp-environ.5 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,62 @@ +.TH tcp-environ 5 +.SH NAME +tcp-environ \- TCP-related environment variables +.SH DESCRIPTION +The following environment variables +describe a TCP connection. +They are set up by +.BR tcp-env , +.BR tcpclient , +and +.BR tcpserver . +Note that +.BR TCPLOCALHOST , +.BR TCPREMOTEHOST , +and +.B TCPREMOTEINFO +can contain arbitrary characters. +.TP 5 +PROTO +The string +.BR TCP . +.TP 5 +TCPLOCALHOST +The domain name of the local host, +with uppercase letters converted to lowercase. +If there is no currently available domain name +for the local IP address, +.B TCPLOCALHOST +is not set. +.TP 5 +TCPLOCALIP +The IP address of the local host, in dotted-decimal form. +.TP 5 +TCPLOCALPORT +The local TCP port number, in decimal. +.TP 5 +TCPREMOTEHOST +The domain name of the remote host, +with uppercase letters converted to lowercase. +If there is no currently available domain name +for the remote IP address, +.B TCPREMOTEHOST +is not set. +.TP 5 +TCPREMOTEINFO +A connection-specific string, perhaps a username, +supplied by the remote host +via 931/1413/IDENT/TAP. +If the remote host did not supply connection information, +.B TCPREMOTEINFO +is not set. +.TP 5 +TCPREMOTEIP +The IP address of the remote host. +.TP 5 +TCPREMOTEPORT +The remote TCP port number. +.SH "SEE ALSO" +tcpclient(1), +tcpserver(1), +tcp-env(1), +tcp(4) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tcpcat.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,20 @@ +.TH tcpcat 1 +.SH NAME +tcpcat \- print data from a TCP port +.SH SYNTAX +.B tcpcat +.I host +.I port +.SH DESCRIPTION +.B tcpcat +connects to +.I port +on +.I host +and prints any data it receives. + +.B tcpcat +can be used to transfer binary data. +It does no conversions. +.SH "SEE ALSO" +tcpclient(1) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tcpclient.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,151 @@ +.TH tcpclient 1 +.SH NAME +tcpclient \- create an outgoing TCP connection +.SH SYNOPSIS +.B tcpclient +[ +.B \-hHrRdDqQv +] +[ +.B \-i\fIlocalip +] +[ +.B \-p\fIlocalport +] +[ +.B \-T\fItimeoutconn +] +[ +.B \-l\fIlocalname +] +[ +.B \-t\fItimeoutinfo +] +.I host +.I port +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B tcpclient +attempts to connect to a TCP server. +If it is successful, it runs +.I program +with the given arguments, +with descriptor 6 reading from the network +and descriptor 7 writing to the network. + +The server's address is given by +.I host +and +.IR port . +.I host +may be 0, referring to the local machine, +or a dotted-decimal IP address, +or a host name; +if a host has several IP addresses, +.B tcpclient +tries each in turn. +.I port +may be a numeric port number +or a port name. + +.B tcpclient +sets up several environment variables, +as described in +.B tcp-environ(5). +.SH OPTIONS +.TP +.B \-i\fIlocalip +Use +.I localip +as the IP address for the local side of the connection; +quit if +.I localip +is not available. +.TP +.B \-p\fIlocalport +Use +.I localport +as the port number for the local side of the connection; +quit if +.I localport +is not available. +.TP +.B \-T\fItimeoutconn +Give up on the +connection attempt +after +.I timeoutconn +seconds. Default: 60. +This timeout applies to each IP address tried. +.TP +.B \-d +(Default.) +Delay sending data for a fraction of a second whenever the +remote host is responding slowly, +to make better use of the network. +.TP +.B \-D +Never delay sending data; +enable TCP_NODELAY. +This is appropriate for interactive connections. +.TP +.B \-q +Quiet. +Do not print any messages. +.TP +.B \-Q +(Default.) +Print error messages. +.TP +.B \-v +Verbose. +Print all available messages. +.SH "DATA-GATHERING OPTIONS" +.TP +.B \-h +(Default.) +Look up the remote host name for +.BR TCPREMOTEHOST . +.TP +.B \-H +Do not look up the remote host name; +unset +.BR TCPREMOTEHOST . +.TP +.B \-l\fIlocalname +Do not look up the local host name; +use +.I localname +for +.BR TCPLOCALHOST . +.TP +.B \-r +(Default.) +Attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-R +Do not attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-t\fItimeoutinfo +Give up on the +.B TCPREMOTEINFO +connection attempt +after +.I timeoutinfo +seconds. Default: 26. +.SH "SEE ALSO" +date@(1), +finger@(1), +http@(1), +mconnect(1), +tcpcat(1), +tcpserver(1), +who@(1), +tcp-environ(5) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tcprules.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,208 @@ +.TH tcprules 1 +.SH NAME +tcprules \- compile rules for tcpserver +.SH SYNOPSIS +.B tcprules +.I rules.cdb +.I rules.tmp +.SH OVERVIEW +.B tcpserver +optionally follows rules to decide whether a TCP connection is acceptable. +For example, a rule of + +.EX + 18.23.0.32:deny +.EE + +prohibits connections from IP address 18.23.0.32. + +.B tcprules +reads rules from its standard input +and writes them into +.I rules.cdb +in a binary format suited +for quick access by +.BR tcpserver . + +.B tcprules +can be used while +.B tcpserver +is running: +it ensures that +.I rules.cdb +is updated atomically. +It does this by first writing the rules to +.I rules.tmp +and then moving +.I rules.tmp +on top of +.IR rules.cdb . +If +.I rules.tmp +already exists, it is destroyed. +The directories containing +.I rules.cdb +and +.I rules.tmp +must be writable to +.BR tcprules ; +they must also be on the same filesystem. + +If there is a problem with the input, +.B tcprules +complains and leaves +.I rules.cdb +alone. + +The binary +.I rules.cdb +format is portable across machines. +.SH "RULE FORMAT" +A rule takes up one line. +A file containing rules +may also contain comments: lines beginning with # are ignored. + +Each rule contains an +.BR address , +a colon, +and a list of +.BR instructions , +with no extra spaces. +When +.B tcpserver +receives a connection from that address, +it follows the instructions. +.SH "ADDRESSES" +.B tcpserver +starts by looking for a rule with address +.IR TCPREMOTEINFO\fB@\fITCPREMOTEIP . +If it doesn't find one, or if +.I TCPREMOTEINFO +is not set, it tries the address +.IR TCPREMOTEIP . +If that doesn't work, it tries shorter and shorter prefixes of +.I TCPREMOTEIP +ending with a dot. +If none of them work, it tries the empty string. + +For example, here are some rules: + +.EX + joe@127.0.0.1:first +.br + 18.23.0.32:second +.br + 127.:third +.br + :fourth +.EE + +If +.I TCPREMOTEIP +is +.BR 10.119.75.38 , +.B tcpserver +will follow the +.B fourth +instructions. + +If +.I TCPREMOTEIP +is +.BR 18.23.0.32 , +.B tcpserver +will follow the +.B second +instructions. + +If +.I TCPREMOTEINFO +is +.B bill +and +.I TCPREMOTEIP +is +.BR 127.0.0.1 , +.B tcpserver +will follow the +.B third +instructions. + +If +.I TCPREMOTEINFO +is +.B joe +and +.I TCPREMOTEIP +is +.BR 127.0.0.1 , +.B tcpserver +will follow the +.B first +instructions. +.SH "ADDRESS RANGES" +.B tcprules +treats +.B 1.2.3.37-53:ins +as an abbreviation +for the rules +.BR 1.2.3.37:ins , +.BR 1.2.3.38:ins , +and so on up through +.BR 1.2.3.53:ins . +Similarly, +.BR 10.2-3.:ins +is an abbreviation for +.B 10.2.:ins +and +.BR 10.3.:ins . +.SH "INSTRUCTIONS" +The instructions in a rule must begin with either +.B allow +or +.BR deny . +.B deny +tells +.B tcpserver +to drop the connection without running anything. +For example, the rule + +.EX + :deny +.EE + +tells +.B tcpserver +to drop all connections that aren't handled by more specific rules. + +The instructions may continue with some environment variables, +in the format +.IR ,VAR="VALUE" . +.B tcpserver +adds +.I VAR=VALUE +to the current environment. +For example, + +.EX + 10.0.:allow,RELAYCLIENT="@fix.me" +.EE + +adds +.B RELAYCLIENT=@fix.me +to the environment. +The quotes here may be replaced by any repeated character: + +.EX + 10.0.:allow,RELAYCLIENT=/@fix.me/ +.EE + +Any number of variables may be listed: + +.EX + 127.0.0.1:allow,RELAYCLIENT="",TCPLOCALHOST="movie.edu" +.EE +.SH "SEE ALSO" +tcprulescheck(1), +tcpserver(1), +tcp-environ(5) --- tcprules.c 14 Jun 2002 08:47:30 -0000 1.1.1.1 +++ tcprules.c 16 Mar 2004 15:12:26 -0000 1.2 @@ -94,6 +94,7 @@ int len; int fd; int i; + int e; char ch; fn = argv[1]; @@ -144,8 +145,16 @@ while (len) switch(*x) { case ',': + e = byte_chr(x + 1,len - 1,','); i = byte_chr(x,len,'='); - if (i == len) die_bad(); + if (i > e) { + if (e < 2 || x[1] != '!') die_bad(); + if (!stralloc_catb(&data,"-",1)) nomem(); + if (!stralloc_catb(&data,x + 2,e - 1)) nomem(); + if (!stralloc_0(&data)) nomem(); + x += e + 1; len -= e + 1; + break; + } if (!stralloc_catb(&data,"+",1)) nomem(); if (!stralloc_catb(&data,x + 1,i)) nomem(); x += i + 1; len -= i + 1; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tcprulescheck.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,25 @@ +.TH tcprulescheck 1 +.SH NAME +tcprulescheck \- try out rules for tcpserver +.SH SYNTAX +.B tcprulescheck +.I rules.cdb +.I tcpremoteip +[ +.I tcpremoteinfo +] +.SH DESCRIPTION +.B tcprulescheck +says what +.B tcpserver +will do with a connection from +IP address +.IR tcpremoteip , +following the rules compiled into +.I rules.cdb +by +.BR tcprules . +.SH "SEE ALSO" +tcprules(1), +tcpserver(1), +tcp-environ(5) diff -u -p -r1.1.1.1 -r1.2 --- tcprulescheck.c 14 Jun 2002 08:47:30 -0000 1.1.1.1 +++ tcprulescheck.c 16 Mar 2004 15:12:27 -0000 1.2 @@ -22,6 +22,11 @@ buffer_puts(buffer_1,data + 1); buffer_puts(buffer_1,"\n"); break; + case '-': + buffer_puts(buffer_1,"unset environment variable "); + buffer_puts(buffer_1,data + 1); + buffer_puts(buffer_1,"\n"); + break; } ++next0; data += next0; datalen -= next0; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tcpserver.1 6 Apr 2004 11:49:45 -0000 1.2 @@ -0,0 +1,284 @@ +.TH tcpserver 1 +.SH NAME +tcpserver \- accept incoming TCP connections +.SH SYNOPSIS +.B tcpserver +[ +.B \-1UXpPhHrRoOdDqQsSv +] +[ +.B \-c\fIlimit +] +[ +.B \-x\fIrules.cdb +] +[ +.B \-B\fIbanner +] +[ +.B \-g\fIgid +] +[ +.B \-u\fIuid +] +[ +.B \-b\fIbacklog +] +[ +.B \-l\fIlocalname +] +[ +.B \-t\fItimeout +] +[ +.B \-n\fIcertfile +] +.I host +.I port +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B tcpserver +waits for connections from TCP clients. +For each connection, it runs +.I program +with the given arguments, +with descriptor 0 reading from the network +and descriptor 1 writing to the network. + +The server's address is given by +.I host +and +.IR port . +.I host +can be 0, allowing connections from any host; +or a particular IP address, +allowing connections only to that address; +or a host name, allowing connections to the first IP address +for that host. +.I port +may be a numeric port number +or a port name. +If +.I port +is 0, +.B tcpserver +will choose a free port. + +.B tcpserver +sets up several environment variables, +as described in +.B tcp-environ(5). + +.B tcpserver +exits when it receives SIGTERM. +.SH "OPTIONS" +.TP +.B \-c\fIlimit +Do not handle more than +.I limit +simultaneous connections. +If there are +.I limit +simultaneous copies of +.I program +running, defer acceptance of a new connection +until one copy finishes. +.I limit +must be a positive integer. +Default: 40. +.TP +.B \-x\fIrules.cdb +Follow the rules compiled into +.I rules.cdb +by +.BR tcprules . +These rules may specify setting environment variables +or rejecting connections from bad sources. + +.B tcpserver +does not read +.I rules.cdb +into memory; +you can rerun +.B tcprules +to change +.BR tcpserver 's +behavior on the fly. +.TP +.B \-B\fIbanner +Write +.I banner +to the network immediately after each connection is made. +.B tcpserver +writes +.I banner +before looking up +.BR TCPREMOTEHOST , +before looking up +.BR TCPREMOTEINFO , +and before checking +.IR rules.cdb . + +This feature can be used to reduce latency in protocols +where the client waits for a greeting from the server. +.TP +.B \-g\fIgid +Switch group ID to +.I gid +after preparing to receive connections. +.I gid +must be a positive integer. +.TP +.B \-u\fIuid +Switch user ID to +.I uid +after preparing to receive connections. +.I uid +must be a positive integer. +.TP +.B \-U +Same as +.B \-g\fI$GID +.BR \-u\fI$UID . +Typically +.I $GID +and +.I $UID +are set by envuidgid. +.TP +.B \-1 +After preparing to receive connections, +print the local port number to standard output. +.TP +.B \-b\fIbacklog +Allow up to +.I backlog +simultaneous SYN_RECEIVEDs. +Default: 20. +On some systems, +.I backlog +is silently limited to 5. +See +.BR listen (2) +for more details. +.TP +.B \-o +Leave IP options alone. +If the client is sending packets along an IP source route, +send packets back along the same route. +.TP +.B \-O +(Default.) +Kill IP options. +A client can still use source routing to connect and to send data, +but packets will be sent back along the default route. +.TP +.B \-d +(Default.) +Delay sending data for a fraction of a second whenever the +remote host is responding slowly, +to make better use of the network. +.TP +.B \-D +Never delay sending data; +enable TCP_NODELAY. +This is appropriate for interactive connections. +.TP +.B \-q +Quiet. +Do not print any messages. +.TP +.B \-Q +(Default.) +Print error messages. +.TP +.B \-s +Enable SSL/TLS mode. This modus needs a SSL enabled build and a certificat. +.TP +.B \-S +(Default.) +Don't enable SSL/TLS mode. +.TP +.B \-n\fIcertfile +Instead of the default ./cert.pem certificate us the specified +.IR certfile . +.TP +.B \-v +Verbose. +Print all available messages. +.TP +.B \-X +With +.BR -x\fIcdb , +allow connections even if +.I cdb +does not exist. +Normally the connection gets dropped. +.SH "DATA-GATHERING OPTIONS" +.TP +.B \-p +Paranoid. +After looking up the remote host name, +look up the IP addresses for that name, +and make sure one of them matches +.BR TCPREMOTEIP . +If none of them do, +unset +.BR TCPREMOTEHOST . +.TP +.B \-P +(Default.) +Not paranoid. +.TP +.B \-h +(Default.) +Look up the remote host name and set +.BR TCPREMOTEHOST . +.TP +.B \-H +Do not look up the remote host name. +.TP +.B \-l\fIlocalname +Do not look up the local host name; +use +.I localname +for +.BR TCPLOCALHOST . +.TP +.B \-r +(Default.) +Attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-R +Do not attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-t\fItimeout +Give up on the +.B TCPREMOTEINFO +connection attempt +after +.I timeout +seconds. Default: 26. +.SH ENVIRONMENT +.TP +.B SSL_CIPHER +Specifies the ciphers that should be used in SSL/TLS mode. +See +.I openssl(1) +for more information. +.SH "SEE ALSO" +argv0(1), +fixcr(1), +recordio(1), +tcpclient(1), +tcprules(1), +listen(2), +tcp-environ(5), +openssl(1) --- tcpserver.c 14 Jun 2002 08:47:30 -0000 1.1.1.1 +++ tcpserver.c 1 Apr 2005 15:13:15 -0000 1.8 @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "uint16.h" #include "str.h" #include "byte.h" @@ -36,6 +37,13 @@ int flagremotehost = 1; int flagparanoid = 0; unsigned long timeout = 26; +#ifdef WITH_SSL +int flagssl = 0; +struct stralloc certfile = {0}; +#define CERTFILE "./cert.pem" + +void translate(SSL*, int, int, unsigned int); +#endif static stralloc tcpremoteinfo; @@ -127,6 +135,9 @@ env(data + 1,data + 1 + split + 1); } break; + case '-': + env(data + 1, (char *)0); + break; } ++next0; data += next0; datalen -= next0; @@ -238,6 +249,7 @@ void usage(void) { +#ifndef WITH_SSL strerr_warn1("\ tcpserver: usage: tcpserver \ [ -1UXpPhHrRoOdDqQv ] \ @@ -250,6 +262,21 @@ [ -l localname ] \ [ -t timeout ] \ host port program",0); +#else + strerr_warn1("\ +tcpserver: usage: tcpserver \ +[ -1UXpPhHrRoOdDqQsSv ] \ +[ -c limit ] \ +[ -x rules.cdb ] \ +[ -B banner ] \ +[ -g gid ] \ +[ -u uid ] \ +[ -b backlog ] \ +[ -l localname ] \ +[ -t timeout ] \ +[ -n certfile ] \ +host port program",0); +#endif _exit(100); } @@ -300,7 +327,20 @@ int s; int t; +#ifdef WITH_SSL + BIO *sbio; + SSL *ssl; + SSL_CTX *ctx; + int pi2c[2], pi4c[2]; + + ctx = NULL; + + if (!stralloc_copys(&certfile, CERTFILE) || !stralloc_0(&certfile) ) + strerr_die2x(111,FATAL,"out of memory"); + while ((opt = getopt(argc,argv,"dDvqQhHrRsS1UXx:t:u:g:l:b:B:c:n:pPoO")) != opteof) +#else while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof) +#endif switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; @@ -327,6 +367,14 @@ case 'g': scan_ulong(optarg,&gid); break; case '1': flag1 = 1; break; case 'l': localhost = optarg; break; +#ifdef WITH_SSL + case 's': flagssl = 1; break; + case 'S': flagssl = 0; break; + case 'n': if (!stralloc_copys(&certfile, optarg) || + !stralloc_0(&certfile) ) + strerr_die2x(111,FATAL,"out of memory"); + break; +#endif default: usage(); } argc -= optind; @@ -334,6 +382,11 @@ if (!verbosity) buffer_2->fd = -1; + + if (limit == 0) + strerr_die2x(100,FATAL,"limit may not be set to 0"); + if (limit > 65000) + strerr_die2x(100,FATAL,"limit way to high"); hostname = *argv++; if (!hostname) usage(); @@ -366,6 +419,25 @@ strerr_die3x(111,FATAL,"no IP address for ",hostname); byte_copy(localip,4,addresses.s); +#ifdef WITH_SSL + if (flagssl == 1) { + /* setup SSL context (load key and cert into ctx) */ + SSL_library_init(); + ctx=SSL_CTX_new(SSLv23_server_method()); + if (!ctx) strerr_die2x(111,FATAL,"unable to create SSL context"); + + /* set prefered ciphers */ + if (env_get("SSL_CIPHER")) + if (SSL_CTX_set_cipher_list(ctx, env_get("SSL_CIPHER")) == 0) + strerr_die2x(111,FATAL,"unable to set cipher list"); + + if(SSL_CTX_use_RSAPrivateKey_file(ctx, certfile.s, SSL_FILETYPE_PEM) != 1) + strerr_die2x(111,FATAL,"unable to load RSA private key"); + if(SSL_CTX_use_certificate_chain_file(ctx, certfile.s) != 1) + strerr_die2x(111,FATAL,"unable to load certificate"); + } +#endif + s = socket_tcp(); if (s == -1) strerr_die2sys(111,FATAL,"unable to create socket: "); @@ -415,6 +487,39 @@ sig_unblock(sig_child); sig_uncatch(sig_term); sig_uncatch(sig_pipe); +#ifdef WITH_SSL + if (flagssl == 1) { + if (pipe(pi2c) != 0) + strerr_die2sys(111,DROP,"unable to create pipe: "); + if (pipe(pi4c) != 0) + strerr_die2sys(111,DROP,"unable to create pipe: "); + switch(fork()) { + case 0: + close(0); close(1); + close(pi2c[1]); + close(pi4c[0]); + if ((fd_move(0,pi2c[0]) == -1) || (fd_move(1,pi4c[1]) == -1)) + strerr_die2sys(111,DROP,"unable to set up descriptors: "); + /* signals are allready set in the parent */ + pathexec(argv); + strerr_die4sys(111,DROP,"unable to run ",*argv,": "); + case -1: + strerr_die2sys(111,DROP,"unable to fork: "); + default: + ssl = SSL_new(ctx); + if (!ssl) + strerr_die2x(111,DROP,"unable to set up SSL session"); + sbio = BIO_new_socket(0,BIO_NOCLOSE); + if (!sbio) + strerr_die2x(111,DROP,"unable to set up BIO socket"); + SSL_set_bio(ssl,sbio,sbio); + close(pi2c[0]); + close(pi4c[1]); + translate(ssl, pi2c[1], pi4c[0], 3600); + _exit(0); + } + } +#endif pathexec(argv); strerr_die4sys(111,DROP,"unable to run ",*argv,": "); case -1: @@ -424,3 +529,186 @@ close(t); } } + +#ifdef WITH_SSL +int ssl_timeoutio(int (*func)(), long t, int rfd, int wfd, SSL *ssl, char *buf, int len) +{ + int n; + const long end = t + time(NULL); + + do { + fd_set fds; + struct timeval tv; + + const int r = buf ? func(ssl, buf, len) : func(ssl); + if (r > 0) + return r; + + t = end - time(NULL); + if (t < 0) + break; + tv.tv_sec = t; + tv.tv_usec = 0; + + FD_ZERO(&fds); + switch (SSL_get_error(ssl, r)) + { + default: + return r; /* some other error */ + case SSL_ERROR_WANT_READ: + FD_SET(rfd, &fds); + n = select(rfd + 1, &fds, NULL, NULL, &tv); + break; + case SSL_ERROR_WANT_WRITE: + FD_SET(wfd, &fds); + n = select(wfd + 1, NULL, &fds, NULL, &tv); + break; + } + + /* n is the number of descriptors that changed status */ + } + while (n > 0); + + if (n != -1) errno = error_timeout; + return -1; +} + +int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl) +{ + int r; + + /* if connection is established, keep NDELAY */ + if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) + return -1; + r = ssl_timeoutio(SSL_accept, t, rfd, wfd, ssl, NULL, 0); + + if (r <= 0) { + ndelay_off(rfd); + ndelay_off(wfd); + } + else + SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); + + return r; +} + +int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len) +{ + if (!buf) + return 0; + if (SSL_pending(ssl)) + return SSL_read(ssl, buf, len); + return ssl_timeoutio(SSL_read, t, rfd, wfd, ssl, buf, len); +} + +int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len) +{ + if (!buf) + return 0; + return ssl_timeoutio(SSL_write, t, rfd, wfd, ssl, buf, len); +} + +static int allwrite(int fd, char *buf, int len) +{ + int w; + + while (len) { + w = write(fd,buf,len); + if (w == -1) { + if (errno == error_intr) continue; + return -1; /* note that some data may have been written */ + } + if (w == 0) ; /* luser's fault */ + buf += w; + len -= w; + } + return 0; +} + +static int allwritessl(long t, int rfd, int wfd, SSL* ssl, char *buf, int len) +{ + int w; + + while (len) { + w = ssl_timeoutwrite(t, rfd, wfd, ssl, buf, len); + if (w == -1) { + if (errno == error_intr) continue; + return -1; /* note that some data may have been written */ + } + if (w == 0) ; /* luser's fault */ + buf += w; + len -= w; + } + return 0; +} + +char tbuf[2048]; + +void translate(SSL* ssl, int clearout, int clearin, unsigned int iotimeout) +{ + struct taia now; + struct taia deadline; + iopause_fd iop[2]; + int flagexitasap; + int iopl; + int sslout, sslin; + int n, r; + + sslin = SSL_get_fd(ssl); + sslout = SSL_get_fd(ssl); + if (sslin == -1 || sslout == -1) + strerr_die2x(111,DROP,"unable to set up SSL connection"); + + flagexitasap = 0; + + if (ssl_timeoutaccept(timeout, sslin, sslout, ssl) <= 0) + strerr_die2x(111,DROP,"unable to accept SSL connection"); + + while (!flagexitasap) { + taia_now(&now); + taia_uint(&deadline,iotimeout); + taia_add(&deadline,&now,&deadline); + + /* fill iopause struct */ + iopl = 2; + iop[0].fd = sslin; + iop[0].events = IOPAUSE_READ; + iop[1].fd = clearin; + iop[1].events = IOPAUSE_READ; + + /* do iopause read */ + iopause(iop,iopl,&deadline,&now); + if (iop[0].revents) { + do { + /* data on sslin */ + n = ssl_timeoutread(iotimeout, sslin, sslout, ssl, tbuf, sizeof(tbuf)); + if ( n < 0 ) + strerr_die2sys(111,DROP,"unable to read form network: "); + if ( n == 0 ) + flagexitasap = 1; + r = allwrite(clearout, tbuf, n); + if ( r < 0 ) + strerr_die2sys(111,DROP,"unable to write to client: "); + /* + * if the data payload was longer than sizeof(tbuf) then SSL will have + * bytes processed and pending. We need to pick them up and write them + * to clearout. + */ + } while (SSL_pending(ssl)); + } + if (iop[1].revents) { + /* data on clearin */ + n = read(clearin, tbuf, sizeof(tbuf)); + if ( n < 0 ) + strerr_die2sys(111,DROP,"unable to read form client: "); + if ( n == 0 ) + flagexitasap = 1; + r = allwritessl(iotimeout, sslin, sslout, ssl, tbuf, n); + if ( r < 0 ) + strerr_die2sys(111,DROP,"unable to write to network: "); + } + if (!iop[0].revents && !iop[1].revents) + strerr_die2x(0, DROP,"timeout reached without input"); + } +} +#endif --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ who@.1 5 Apr 2004 15:34:57 -0000 1.1 @@ -0,0 +1,32 @@ +.TH who@ 1 +.SH NAME +who@ \- print list of active users on a host +.SH SYNTAX +.B who@ +[ +.I host +] +.SH DESCRIPTION +.B who@ +connects to TCP port 11 (Systat) on +.I host +and prints any data it receives. +It removes CR and converts unprintable characters to a visible format. + +If +.I host +is not supplied, +.B who@ +connects to the local host. + +Some computers respond to port 11 with a list of active users. +For example, they may be running + +.EX + tcpserver 0 11 who & +.EE +.SH "SEE ALSO" +cat(1), +delcr(1), +tcpclient(1), +tcpserver(1)