Changes of Revision 2
[-] | Changed | stunnel.spec |
x 1
2 Summary: An SSL-encrypting socket wrapper 3 Name: stunnel 4 Version: 4.56 5 -Release: 2%{?dist} 6 +Release: 1IX 7 License: GPLv2 8 Group: Applications/Internet 9 URL: http://www.stunnel.org/ 10
11 Source4: stunnel-sfinger.conf 12 Source5: pop3-redirect.xinetd 13 Source6: stunnel-pop3s-client.conf 14 +Source7: stunnel.init 15 Patch0: stunnel-4-authpriv.patch 16 Patch1: stunnel-4-sample.patch 17 +Patch2: stunnel-4.53-xforwarded-for.diff 18 + 19 Buildroot: %{_tmppath}/stunnel-root 20 # util-linux is needed for rename 21 BuildRequires: openssl-devel, pkgconfig, tcp_wrappers-devel, util-linux 22 + 23 # for /usr/bin/pod2man 24 %if 0%{?fedora} > 18 || 0%{?rhel} >= 7 25 BuildRequires: perl-podlators 26
27 %setup -q 28 %patch0 -p1 -b .authpriv 29 %patch1 -p1 -b .sample 30 +%patch2 -p1 -b .xforwarded 31 32 iconv -f iso-8859-1 -t utf-8 < doc/stunnel.fr.8 > doc/stunnel.fr.8_ 33 mv doc/stunnel.fr.8_ doc/stunnel.fr.8 34
35 %install 36 rm -rf $RPM_BUILD_ROOT 37 mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/stunnel 38 +%{__install} -p -D -m 0755 %{SOURCE7} %{buildroot}%{_initrddir}/%{name} 39 touch $RPM_BUILD_ROOT%{_sysconfdir}/stunnel/stunnel.pem 40 make install DESTDIR=$RPM_BUILD_ROOT 41 +mv tools/stunnel.init %{buildroot}%{_initrddir}/stunnel 42 # Move the translated man pages to the right subdirectories, and strip off the 43 # language suffixes. 44 for lang in fr pl ; do 45
46 %doc AUTHORS BUGS ChangeLog COPY* CREDITS PORTS README TODO 47 %doc tools/stunnel.conf-sample 48 %doc srpm-docs/* 49 +%{_initrddir}/%{name} 50 %lang(en) %doc doc/en/* 51 %lang(po) %doc doc/pl/* 52 %{_bindir}/stunnel 53
54 %exclude %{_sysconfdir}/stunnel/* 55 56 %changelog 57 +* Tue Nov 12 2013 Juergen Gotteswinter <jg@internetx.de> - 4.56-99 58 +- added working init script 59 +- added x-forwarded-for patch 60 + 61 * Mon Aug 5 2013 Avesh Agarwal <avagarwa@redhat.com> - 4.56-2 62 - Ftp mirrors for NA does not work, so changing source code 63 URLs to the correct ones. 64 |
||
[+] | Added | stunnel-4.53-xforwarded-for.diff ^ |
@@ -0,0 +1,250 @@ +diff --git a/doc/stunnel.8 b/doc/stunnel.8 +index 589d968..f56f5c0 100644 +--- a/doc/stunnel.8 ++++ b/doc/stunnel.8 +@@ -693,6 +693,10 @@ This options has been renamed to \fInone\fR. + .RE + .RS 4 + .RE ++.IP "\fBxforwardedfor\fR = yes | no" 4 ++.IX Item "xforwardedfor = yes | no" ++append an 'X-Forwarded-For:' HTTP request header providing the ++client's IP address to the server. + .IP "\fBverify\fR = level" 4 + .IX Item "verify = level" + verify peer certificate +diff --git a/src/client.c b/src/client.c +index 4003d13..56ba370 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -48,6 +48,8 @@ + #define SHUT_RDWR 2 + #endif + ++#define IPLEN 40 ++ + static void client_try(CLI *); + static void client_run(CLI *); + static void init_local(CLI *); +@@ -75,6 +77,12 @@ CLI *alloc_client_session(SERVICE_OPTIONS *opt, int rfd, int wfd) { + c=str_alloc(sizeof(CLI)); + str_detach(c); + c->opt=opt; ++ /* some options need space to add some information */ ++ if (c->opt->option.xforwardedfor) ++ c->buffsize = BUFFSIZE - BUFF_RESERVED; ++ else ++ c->buffsize = BUFFSIZE; ++ c->crlf_seen=0; + c->local_rfd.fd=rfd; + c->local_wfd.fd=wfd; + return c; +@@ -496,6 +504,28 @@ static void win_new_chain(CLI *c) { + } + #endif + ++/* Moves all data from the buffer <buffer> between positions <start> and <stop> ++ * to insert <string> of length <len>. <start> and <stop> are updated to their ++ * new respective values, and the number of characters inserted is returned. ++ * If <len> is too long, nothing is done and -1 is returned. ++ * Note that neither <string> nor <buffer> can be NULL. ++ */ ++static int buffer_insert_with_len(char *buffer, int *start, int *stop, int limit, char *string, int len) { ++ if (len > limit - *stop) ++ return -1; ++ if (*start > *stop) ++ return -1; ++ memmove(buffer + *start + len, buffer + *start, *stop - *start); ++ memcpy(buffer + *start, string, len); ++ *start += len; ++ *stop += len; ++ return len; ++} ++ ++static int buffer_insert(char *buffer, int *start, int *stop, int limit, char *string) { ++ return buffer_insert_with_len(buffer, start, stop, limit, string, strlen(string)); ++} ++ + /****************************** transfer data */ + static void transfer(CLI *c) { + int watchdog=0; /* a counter to detect an infinite loop */ +@@ -514,7 +544,7 @@ static void transfer(CLI *c) { + do { /* main loop of client data transfer */ + /****************************** initialize *_wants_* */ + read_wants_read=!(SSL_get_shutdown(c->ssl)&SSL_RECEIVED_SHUTDOWN) +- && c->ssl_ptr<BUFFSIZE && !read_wants_write; ++ && c->ssl_ptr<c->buffsize && !read_wants_write; + write_wants_write=!(SSL_get_shutdown(c->ssl)&SSL_SENT_SHUTDOWN) + && c->sock_ptr && !write_wants_read; + +@@ -523,7 +553,7 @@ static void transfer(CLI *c) { + /* for plain socket open data strem = open file descriptor */ + /* make sure to add each open socket to receive exceptions! */ + if(sock_open_rd) +- s_poll_add(c->fds, c->sock_rfd->fd, c->sock_ptr<BUFFSIZE, 0); ++ s_poll_add(c->fds, c->sock_rfd->fd, c->sock_ptr<c->buffsize, 0); + if(sock_open_wr) + s_poll_add(c->fds, c->sock_wfd->fd, 0, c->ssl_ptr); + /* for SSL assume that sockets are open if there any pending requests */ +@@ -645,7 +675,7 @@ static void transfer(CLI *c) { + /****************************** read from socket */ + if(sock_open_rd && sock_can_rd) { + num=readsocket(c->sock_rfd->fd, +- c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr); ++ c->sock_buff+c->sock_ptr, c->buffsize-c->sock_ptr); + switch(num) { + case -1: + if(parse_socket_error(c, "readsocket")) +@@ -682,7 +712,7 @@ static void transfer(CLI *c) { + /****************************** update *_wants_* based on new *_ptr */ + /* this update is also required for SSL_pending() to be used */ + read_wants_read=!(SSL_get_shutdown(c->ssl)&SSL_RECEIVED_SHUTDOWN) +- && c->ssl_ptr<BUFFSIZE && !read_wants_write; ++ && c->ssl_ptr<c->buffsize && !read_wants_write; + write_wants_write=!(SSL_get_shutdown(c->ssl)&SSL_SENT_SHUTDOWN) + && c->sock_ptr && !write_wants_read; + +@@ -692,12 +722,72 @@ static void transfer(CLI *c) { + * writesocket() above made some room in c->ssl_buff */ + (read_wants_write && ssl_can_wr)) { + read_wants_write=0; +- num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr); ++ num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, c->buffsize-c->ssl_ptr); + switch(err=SSL_get_error(c->ssl, num)) { + case SSL_ERROR_NONE: + if(num==0) + s_log(LOG_DEBUG, "SSL_read returned 0"); +- c->ssl_ptr+=num; ++ if (c->buffsize != BUFFSIZE && c->opt->option.xforwardedfor) { /* some work left to do */ ++ int last = c->ssl_ptr; ++ c->ssl_ptr += num; ++ ++ /* Look for end of HTTP headers between last and ssl_ptr. ++ * To achieve this reliably, we have to count the number of ++ * successive [CR]LF and to memorize it in case it's spread ++ * over multiple segments. --WT. ++ */ ++ while (last < c->ssl_ptr) { ++ if (c->ssl_buff[last] == '\n') { ++ if (++c->crlf_seen == 2) ++ break; ++ } else if (last < c->ssl_ptr - 1 && ++ c->ssl_buff[last] == '\r' && ++ c->ssl_buff[last+1] == '\n') { ++ if (++c->crlf_seen == 2) ++ break; ++ last++; ++ } else if (c->ssl_buff[last] != '\r') ++ /* don't refuse '\r' because we may get a '\n' on next read */ ++ c->crlf_seen = 0; ++ last++; ++ } ++ if (c->crlf_seen >= 2) { ++ /* We have all the HTTP headers now. We don't need to ++ * reserve any space anymore. <ssl_ptr> points to the ++ * first byte of unread data, and <last> points to the ++ * exact location where we want to insert our headers, ++ * which is right before the empty line. ++ */ ++ c->buffsize = BUFFSIZE; ++ ++ if (c->opt->option.xforwardedfor) { ++ /* X-Forwarded-For: xxxx \r\n\0 */ ++ char xforw[17 + IPLEN + 3]; ++ ++ /* We will insert our X-Forwarded-For: header here. ++ * We need to write the IP address, but if we use ++ * sprintf, it will pad with the terminating 0. ++ * So we will pass via a temporary buffer allocated ++ * on the stack. ++ */ ++ memcpy(xforw, "X-Forwarded-For: ", 17); ++ if (getnameinfo(&c->peer_addr.sa, ++ c->peer_addr_len, ++ xforw + 17, IPLEN, NULL, 0, ++ NI_NUMERICHOST) == 0) { ++ strcat(xforw + 17, "\r\n"); ++ buffer_insert(c->ssl_buff, &last, &c->ssl_ptr, ++ c->buffsize, xforw); ++ } ++ /* last still points to the \r\n and ssl_ptr to the ++ * end of the buffer, so we may add as many headers ++ * as wee need to. ++ */ ++ } ++ } ++ } ++ else ++ c->ssl_ptr+=num; + watchdog=0; /* reset watchdog */ + break; + case SSL_ERROR_WANT_WRITE: +diff --git a/src/common.h b/src/common.h +index 4f85e2f..f9f1335 100644 +--- a/src/common.h ++++ b/src/common.h +@@ -52,6 +52,9 @@ + /* I/O buffer size - 18432 is the maximum size of SSL record payload */ + #define BUFFSIZE 18432 + ++/* maximum space reserved for header insertion in BUFFSIZE */ ++#define BUFF_RESERVED 1024 ++ + /* how many bytes of random input to read from files for PRNG */ + /* OpenSSL likes at least 128 bits, so 64 bytes seems plenty. */ + #define RANDOM_BYTES 64 +diff --git a/src/options.c b/src/options.c +index 9b672da..e18aa93 100644 +--- a/src/options.c ++++ b/src/options.c | ||
[+] | Added | stunnel.init ^ |
@@ -0,0 +1,85 @@ +#!/bin/bash +# +# stunnel SSL encryption wrapper +# +# chkconfig: 345 80 30 +# description: Postfix is a Mail Transport Agent, which is the program \ +# that moves mail from one machine to another. +# processname: stunnel +# pidfile: /var/run/stunnel/stunnel.pid +# config: /etc/stunnel/stunnel.con +# description: secure tunnel daemon +# + +### BEGIN INIT INFO +# Provides: stunnel +# Required-Start: $local_fs $network +# Required-Stop: $local_fs $network +# Default-Start: 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop stunnel +# Description: Stunnel is SSL encryption wrapper, and is commonly used to +# add SSL functionality to other daemons without any changes +# in their programs' code. +### END INIT INFO + +# Source function library. +. /etc/rc.d/init.d/functions + +RETVAL=0 +prog="stunnel" +exec=/usr/bin/$prog +lockfile=/var/lock/subsys/$prog +pidfile=/var/run/stunnel/stunnel.pid +CONFIG="/etc/stunnel/stunnel.conf" + +# Source stunnel configuration. +if [ -f /etc/sysconfig/stunnel ] ; then + . /etc/sysconfig/stunnel +fi + + +start() { + [ -x "$exec" ] || exit 5 + echo -n $"Starting secure tunnel: " + daemon $exec $CONFIG + RETVAL=$? + [ "$RETVAL" -eq 0 ] && touch "$lockfile" + echo + return $RETVAL +} + +stop() { + echo -n $"Stopping secure tunnel: " + killproc -p $pidfile $prog + RETVAL=$? + [ "$RETVAL" -eq 0 ] && rm -f "$lockfile" + echo + return $RETVAL +} + +restart() { + stop + start +} + +# See how we were called. +case "$1" in + start|stop|restart) + $1 + ;; + reload|force-reload) + restart + ;; + condrestart|try-restart) + [ ! -f "$lockfile" ] || restart + ;; + status) + status $prog + ;; + *) + echo $"Usage: $0 {start|stop|restart|try-restart|condrestart|reload|force-reload|status}" + exit 2 +esac + +exit $? |