Download | Plain Text | Line Numbers
--- FILES 14 Jun 2002 08:47:30 -0000 1.1.1.1
+++ FILES 5 Apr 2004 15:34:57 -0000 1.2
@@ -216,6 +216,7 @@
warn-auto.sh
warn-shsgr
x86cpuid.c
+fixcrio.1
dns_ip6.c
dns_ipq6.c
dns_nd6.c
--- 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
@@ -755,7 +763,7 @@
load tcpserver.o rules.o remoteinfo6.o timeoutconn6.o cdb.a dns.a \
time.a unix.a byte.a socket.lib
./load tcpserver rules.o remoteinfo6.o timeoutconn6.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 \
@@ -764,7 +772,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 uint32.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 \
@@ -967,3 +975,18 @@
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
+++ 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
@@ -26,6 +26,7 @@
c(auto_home,"bin","fixcrio",-1,-1,0755);
c(auto_home,"bin","rblsmtpd",-1,-1,0755);
+ c(auto_home,"man/man1","fixcrio.1",-1,-1,0644);
c(auto_home,"man/man1","tcpclient.1",-1,-1,0644);
c(auto_home,"man/man1","tcpserver.1",-1,-1,0644);
c(auto_home,"man/man1","tcprules.1",-1,-1,0644);
}
--- 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];
@@ -154,8 +155,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;
--- 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;
--- tcpserver.1.orig 1 Jan 1970 00:00:00 -0000
+++ tcpserver.1 6 Apr 2004 11:49:45 -0000 1.2
@@ -4,7 +4,7 @@
.SH SYNOPSIS
.B tcpserver
[
-.B \-146jpPhHrRoOdDqQv
+.B \-146UXpPhHrRoOdDqQsSv
]
[
.B \-c\fIlimit
@@ -31,6 +31,9 @@
.B \-t\fItimeout
]
[
+.B \-n\fIcertfile
+]
+[
.B \-I\fIinterface
]
.I host
@@ -204,11 +207,31 @@
(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.
.SH "DATA-GATHERING OPTIONS"
.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,
@@ -256,6 +279,13 @@
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),
@@ -264,3 +294,4 @@
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 <sys/types.h>
#include <sys/param.h>
#include <netdb.h>
+#include <openssl/ssl.h>
+#include <fcntl.h>
#include "uint16.h"
#include "str.h"
#include "byte.h"
@@ -39,6 +40,13 @@
int flagparanoid = 0;
unsigned long timeout = 26;
uint32 netif = 0;
+#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;
@@ -130,6 +138,9 @@
env(data + 1,data + 1 + split + 1);
}
break;
+ case '-':
+ env(data + 1, (char *)0);
+ break;
}
++next0;
data += next0; datalen -= next0;
@@ -271,6 +282,7 @@
void usage(void)
{
+#ifndef WITH_SSL
strerr_warn1("\
tcpserver: usage: tcpserver \
[ -461UXpPhHrRoOdDqQv ] \
@@ -282,8 +294,23 @@
[ -b backlog ] \
[ -l localname ] \
[ -t timeout ] \
+host port program",0);
+#else
+ strerr_warn1("\
+tcpserver: usage: tcpserver \
+[ -461UXpPhHrRoOdDqQsSv ] \
+[ -c limit ] \
+[ -x rules.cdb ] \
+[ -B banner ] \
+[ -g gid ] \
+[ -u uid ] \
+[ -b backlog ] \
+[ -l localname ] \
+[ -t timeout ] \
+[ -n certfile ] \
[ -I interface ] \
host port program",0);
+#endif
_exit(100);
}
@@ -334,7 +361,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,"46dDvqQhHrRsS1UXx:t:u:g:l:b:B:c:n:I:pPoO")) != opteof)
+#else
while ((opt = getopt(argc,argv,"46dDvqQhHrR1UXx:t:u:g:l:b:B:c:I:pPoO")) != opteof)
+#endif
switch(opt) {
case 'b': scan_ulong(optarg,&backlog); break;
case 'c': scan_ulong(optarg,&limit); break;
@@ -364,6 +404,14 @@
case '4': noipv6 = 1; break;
case '6': forcev6 = 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;
@@ -371,6 +419,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();
@@ -412,6 +465,25 @@
noipv6=1;
}
+#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_tcp6();
if (s == -1)
strerr_die2sys(111,FATAL,"unable to create socket: ");
@@ -461,6 +533,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:
@@ -470,3 +575,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