summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Bogatov <KAction@debian.org>2018-11-15 16:13:04 +0000
committerDmitry Bogatov <KAction@debian.org>2018-11-15 16:13:04 +0000
commitcfb2fb1ef87d02e8398267927531a0067d103024 (patch)
tree2587fff9f0f2af94642f5f1f054e7100535e6a0b
parente68f4a9a5d2b38573878f54c1e175c14140813aa (diff)
parentc574ccf210d44ca814d632568c9036ab9933ddc5 (diff)
Update upstream source from tag 'upstream/1.30'
Update to upstream version '1.30' with Debian dir 61b925122c8cfa37d6d67e4db9ea90b13ed92d98
-rw-r--r--README8
-rw-r--r--contrib/redhat-rpm/mini_httpd.spec2
-rw-r--r--htpasswd.c3
-rw-r--r--mini_httpd.c166
-rwxr-xr-xscripts/mini_httpd.sh47
-rw-r--r--version.h2
6 files changed, 160 insertions, 68 deletions
diff --git a/README b/README
index 3f152b4..c12ae95 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
mini_httpd - small HTTP server
- version 1.23 of 28Dec2015
+ version 1.30 of 26Oct2018
mini_httpd is a small HTTP server. Its performance is not great, but for
low or medium traffic sites it's quite adequate. It implements all the
@@ -48,9 +48,9 @@ If you're doing SSL, uncomment those lines too. Otherwise, just do a make.
On Red Hat Linux systems you can use RPM to install mini_httpd, like so:
cd /usr/src/redhat/SOURCES
- wget http://www.acme.com/software/mini_httpd/mini_httpd-1.20.tar.gz
- rpm -ta mini_httpd-1.20.tar.gz
- rpm -i /usr/src/redhat/RPMS/i386/mini_httpd-1.20-1.i386.rpm
+ wget http://www.acme.com/software/mini_httpd/mini_httpd-1.30.tar.gz
+ rpm -ta mini_httpd-1.30.tar.gz
+ rpm -i /usr/src/redhat/RPMS/i386/mini_httpd-1.30-1.i386.rpm
Feedback is welcome - send bug reports, enhancements, checks, money
orders, etc. to the addresses below.
diff --git a/contrib/redhat-rpm/mini_httpd.spec b/contrib/redhat-rpm/mini_httpd.spec
index 2cab698..c1ad3e7 100644
--- a/contrib/redhat-rpm/mini_httpd.spec
+++ b/contrib/redhat-rpm/mini_httpd.spec
@@ -1,6 +1,6 @@
Summary: small, simple http daemon, supports SSL
Name: mini_httpd
-Version: 1.23
+Version: 1.30
Release: 1
Copyright: Freely Redistributable
Packager: Bennett Todd <bet@mordor.net>
diff --git a/htpasswd.c b/htpasswd.c
index 8ffda29..31ac769 100644
--- a/htpasswd.c
+++ b/htpasswd.c
@@ -184,7 +184,8 @@ int main(int argc, char *argv[]) {
fprintf(stderr,"Use -c option to create new one.\n");
exit(1);
}
- strcpy(user,argv[2]);
+ strncpy(user,argv[2],sizeof(user)-1);
+ user[sizeof(user)-1] = '\0';
found = 0;
while(!(my_getline(line,MAX_STRING_LEN,f))) {
diff --git a/mini_httpd.c b/mini_httpd.c
index 4051625..ed963f0 100644
--- a/mini_httpd.c
+++ b/mini_httpd.c
@@ -163,6 +163,9 @@ typedef long long int64_t;
#define METHOD_GET 1
#define METHOD_HEAD 2
#define METHOD_POST 3
+#define METHOD_PUT 4
+#define METHOD_DELETE 5
+#define METHOD_TRACE 6
/* A multi-family sockaddr. */
@@ -244,7 +247,8 @@ static void read_config( char* filename );
static void value_required( char* name, char* value );
static void no_value_required( char* name, char* value );
static int initialize_listen_socket( usockaddr* usaP );
-static void handle_request( void );
+static void handle_request( void ) __attribute__((noreturn));
+static void finish_request( int exitstatus ) __attribute__((noreturn));
static void de_dotdot( char* f );
static int get_pathinfo( void );
static void do_file( void );
@@ -269,7 +273,7 @@ static int send_error_file( char* filename );
static void send_error_tail( void );
static void add_headers( int s, char* title, char* extra_header, char* me, char* mt, off_t b, time_t mod );
static void start_request( void );
-static void add_to_request( char* str );
+static void add_to_request( char* str, size_t len );
static char* get_request_line( void );
static void start_response( void );
static void add_to_response( char* str );
@@ -279,9 +283,10 @@ static void send_via_sendfile( int fd, int s, off_t size );
static ssize_t my_read( char* buf, size_t size );
static ssize_t my_write( void* buf, size_t size );
#ifdef HAVE_SENDFILE
-static int my_sendfile( int fd, int s, off_t offset, size_t nbytes );
+static ssize_t my_sendfile( int fd, int s, off_t offset, size_t nbytes );
#endif /* HAVE_SENDFILE */
static void add_str( char** bufP, size_t* bufsizeP, size_t* buflenP, char* str );
+static void add_data( char** bufP, size_t* bufsizeP, size_t* buflenP, char* str, size_t len );
static void make_log_entry( void );
static void check_referrer( void );
static int really_check_referrer( void );
@@ -553,9 +558,10 @@ main( int argc, char** argv )
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
ssl_ctx = SSL_CTX_new( SSLv23_server_method() );
- SSL_CTX_set_options( ssl_ctx, SSL_OP_NO_SSLv3 );
+ SSL_CTX_set_options( ssl_ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3 );
if ( certfile[0] != '\0' )
if ( SSL_CTX_use_certificate_file( ssl_ctx, certfile, SSL_FILETYPE_PEM ) == 0 ||
+ SSL_CTX_use_certificate_chain_file( ssl_ctx, certfile ) == 0 ||
SSL_CTX_use_PrivateKey_file( ssl_ctx, certfile, SSL_FILETYPE_PEM ) == 0 ||
SSL_CTX_check_private_key( ssl_ctx ) == 0 )
{
@@ -857,7 +863,6 @@ main( int argc, char** argv )
if ( listen6_fd != -1 )
(void) close( listen6_fd );
handle_request();
- exit( 0 );
}
(void) close( conn_fd );
}
@@ -1196,7 +1201,7 @@ handle_request( void )
if ( SSL_accept( ssl ) == 0 )
{
ERR_print_errors_fp( stderr );
- exit( 1 );
+ finish_request( 1 );
}
}
#endif /* USE_SSL */
@@ -1205,15 +1210,14 @@ handle_request( void )
start_request();
for (;;)
{
- char buf[10000];
+ char buf[50000];
int rr = my_read( buf, sizeof(buf) - 1 );
if ( rr < 0 && ( errno == EINTR || errno == EAGAIN ) )
continue;
if ( rr <= 0 )
break;
(void) alarm( READ_TIMEOUT );
- buf[rr] = '\0';
- add_to_request( buf );
+ add_to_request( buf, rr );
if ( strstr( request, "\015\012\015\012" ) != (char*) 0 ||
strstr( request, "\012\012" ) != (char*) 0 )
break;
@@ -1273,7 +1277,8 @@ handle_request( void )
cp = &line[5];
cp += strspn( cp, " \t" );
host = cp;
- if ( strchr( host, '/' ) != (char*) 0 || host[0] == '.' )
+ if ( host[0] == '\0' || host[0] == '.' ||
+ strchr( host, '/' ) != (char*) 0 )
send_error( 400, "Bad Request", "", "Can't parse request." );
}
else if ( strncasecmp( line, "If-Modified-Since:", 18 ) == 0 )
@@ -1308,6 +1313,12 @@ handle_request( void )
method = METHOD_HEAD;
else if ( strcasecmp( method_str, get_method_str( METHOD_POST ) ) == 0 )
method = METHOD_POST;
+ else if ( strcasecmp( method_str, get_method_str( METHOD_PUT ) ) == 0 )
+ method = METHOD_PUT;
+ else if ( strcasecmp( method_str, get_method_str( METHOD_DELETE ) ) == 0 )
+ method = METHOD_DELETE;
+ else if ( strcasecmp( method_str, get_method_str( METHOD_TRACE ) ) == 0 )
+ method = METHOD_TRACE;
else
send_error( 501, "Not Implemented", "", "That method is not implemented." );
@@ -1388,6 +1399,63 @@ handle_request( void )
#ifdef USE_SSL
SSL_free( ssl );
#endif /* USE_SSL */
+
+ finish_request( 0 );
+ }
+
+
+static void
+finish_request( int exitstatus )
+ {
+#undef LINGER_SOCKOPT
+#define LINGER_READ
+
+#define LINGER_SECS 5
+
+#ifdef LINGER_SOCKOPT
+ /* The sockopt version of lingering close. Doesn't actually work. */
+ struct linger lin;
+
+ shutdown( conn_fd, SHUT_WR );
+ lin.l_onoff = 1;
+ lin.l_linger = LINGER_SECS;
+ (void) setsockopt(
+ conn_fd, SOL_SOCKET, SO_LINGER, (void*) &lin, sizeof(lin) );
+#endif /* LINGER_SOCKOPT */
+
+#ifdef LINGER_READ
+ /* The "non-blocking read until error/eof/timeout" version of
+ ** lingering close.
+ */
+ int flags;
+ fd_set rfds;
+ struct timeval tv;
+ int r;
+ char* buf[1024];
+
+ flags = fcntl( conn_fd, F_GETFL, 0 );
+ if ( flags != -1 )
+ {
+ flags |= (int) O_NDELAY;
+ (void) fcntl( conn_fd, F_SETFL, flags );
+ }
+ shutdown( conn_fd, SHUT_WR );
+ for (;;)
+ {
+ FD_ZERO( &rfds );
+ FD_SET( conn_fd, &rfds );
+ tv.tv_sec = LINGER_SECS;
+ tv.tv_usec = 0;
+ r = select( conn_fd + 1, &rfds, (fd_set*) 0, (fd_set*) 0, &tv );
+ if ( r <= 0 ) /* timeout or error */
+ break;
+ r = read( conn_fd, (void*) buf, sizeof(buf) );
+ if ( r <= 0 ) /* eof or error */
+ break;
+ }
+#endif /* LINGER_READ */
+
+ exit( exitstatus );
}
@@ -1508,9 +1576,12 @@ do_file( void )
do_cgi();
return;
}
- else if ( pathinfo != (char*) 0 )
+ if ( pathinfo != (char*) 0 )
send_error( 404, "Not Found", "", "File not found." );
+ if ( method != METHOD_GET && method != METHOD_HEAD )
+ send_error( 501, "Not Implemented", "", "That method is not implemented." );
+
fd = open( file, O_RDONLY );
if ( fd < 0 )
{
@@ -1725,9 +1796,6 @@ do_cgi( void )
char* binary;
char* directory;
- if ( method != METHOD_GET && method != METHOD_POST )
- send_error( 501, "Not Implemented", "", "That method is not implemented for CGI." );
-
/* If the socket happens to be using one of the stdin/stdout/stderr
** descriptors, move it to another descriptor so that the dup2 calls
** below don't screw things up. We arbitrarily pick fd 3 - if there
@@ -1774,7 +1842,7 @@ do_cgi( void )
/* Interposer process. */
(void) close( p[0] );
cgi_interpose_input( p[1] );
- exit( 0 );
+ finish_request( 0 );
}
(void) close( p[1] );
if ( p[0] != STDIN_FILENO )
@@ -1816,7 +1884,7 @@ do_cgi( void )
/* Interposer process. */
(void) close( p[1] );
cgi_interpose_output( p[0], parse_headers );
- exit( 0 );
+ finish_request( 0 );
}
(void) close( p[0] );
if ( p[1] != STDOUT_FILENO )
@@ -1900,6 +1968,14 @@ cgi_interpose_input( int wfd )
ssize_t r, r2;
char buf[1024];
+ /* Set up the timeout for reading again, since we're in a sub-process. */
+#ifdef HAVE_SIGSET
+ (void) sigset( SIGALRM, handle_read_timeout );
+#else /* HAVE_SIGSET */
+ (void) signal( SIGALRM, handle_read_timeout );
+#endif /* HAVE_SIGSET */
+ (void) alarm( READ_TIMEOUT );
+
c = request_len - request_idx;
if ( c > 0 )
{
@@ -1929,6 +2005,7 @@ cgi_interpose_input( int wfd )
break;
}
c += r;
+ (void) alarm( READ_TIMEOUT );
}
post_post_garbage_hack();
}
@@ -1967,6 +2044,14 @@ cgi_interpose_output( int rfd, int parse_headers )
ssize_t r, r2;
char buf[1024];
+ /* Set up the timeout for writing again, since we're in a sub-process. */
+#ifdef HAVE_SIGSET
+ (void) sigset( SIGALRM, handle_write_timeout );
+#else /* HAVE_SIGSET */
+ (void) signal( SIGALRM, handle_write_timeout );
+#endif /* HAVE_SIGSET */
+ (void) alarm( WRITE_TIMEOUT );
+
if ( ! parse_headers )
{
/* If we're not parsing headers, write out the default status line
@@ -1994,10 +2079,10 @@ cgi_interpose_output( int rfd, int parse_headers )
/* Slurp in all headers. */
headers_size = 0;
- add_str( &headers, &headers_size, &headers_len, (char*) 0 );
+ add_data( &headers, &headers_size, &headers_len, (char*) 0, 0 );
for (;;)
{
- r = read( rfd, buf, sizeof(buf) - 1 );
+ r = read( rfd, buf, sizeof(buf) );
if ( r < 0 && ( errno == EINTR || errno == EAGAIN ) )
{
sleep( 1 );
@@ -2008,15 +2093,14 @@ cgi_interpose_output( int rfd, int parse_headers )
br = &(headers[headers_len]);
break;
}
- buf[r] = '\0';
- add_str( &headers, &headers_size, &headers_len, buf );
+ add_data( &headers, &headers_size, &headers_len, buf, r );
if ( ( br = strstr( headers, "\015\012\015\012" ) ) != (char*) 0 ||
( br = strstr( headers, "\012\012" ) ) != (char*) 0 )
break;
}
/* If there were no headers, bail. */
- if ( headers[0] == '\0' )
+ if ( headers_len == 0 )
return;
/* Figure out the status. */
@@ -2069,7 +2153,7 @@ cgi_interpose_output( int rfd, int parse_headers )
continue;
}
if ( r <= 0 )
- goto done;
+ return;
for (;;)
{
r2 = my_write( buf, r );
@@ -2079,12 +2163,11 @@ cgi_interpose_output( int rfd, int parse_headers )
continue;
}
if ( r2 != r )
- goto done;
+ return;
break;
}
+ (void) alarm( WRITE_TIMEOUT );
}
- done:
- shutdown( conn_fd, SHUT_WR );
}
@@ -2391,7 +2474,7 @@ send_error( int s, char* title, char* extra_header, char* text )
#ifdef USE_SSL
SSL_free( ssl );
#endif /* USE_SSL */
- exit( 1 );
+ finish_request( 1 );
}
@@ -2576,9 +2659,9 @@ start_request( void )
}
static void
-add_to_request( char* str )
+add_to_request( char* str, size_t len )
{
- add_str( &request, &request_size, &request_len, str );
+ add_data( &request, &request_size, &request_len, str, len );
}
static char*
@@ -2704,6 +2787,7 @@ send_via_write( int fd, off_t size )
return;
break;
}
+ (void) alarm( WRITE_TIMEOUT );
}
}
}
@@ -2769,14 +2853,19 @@ my_write( void* buf, size_t size )
#ifdef HAVE_SENDFILE
-static int
+static ssize_t
my_sendfile( int fd, int s, off_t offset, size_t nbytes )
{
#ifdef HAVE_LINUX_SENDFILE
- off_t lo = offset;
- return sendfile( s, fd, &lo, nbytes );
+ off_t lo = offset;
+ return sendfile( s, fd, &lo, nbytes );
#else /* HAVE_LINUX_SENDFILE */
- return sendfile( fd, s, offset, nbytes, (struct sf_hdtr*) 0, (off_t*) 0, 0 );
+ int r;
+ r = sendfile( fd, s, offset, nbytes, (struct sf_hdtr*) 0, (off_t*) 0, 0 );
+ if ( r == 0 )
+ return nbytes;
+ else
+ return r;
#endif /* HAVE_LINUX_SENDFILE */
}
#endif /* HAVE_SENDFILE */
@@ -2791,14 +2880,20 @@ add_str( char** bufP, size_t* bufsizeP, size_t* buflenP, char* str )
len = 0;
else
len = strlen( str );
+ add_data( bufP, bufsizeP, buflenP, str, len );
+ }
+
+static void
+add_data( char** bufP, size_t* bufsizeP, size_t* buflenP, char* str, size_t len )
+ {
if ( *bufsizeP == 0 )
{
*bufsizeP = len + 500;
*buflenP = 0;
*bufP = (char*) e_malloc( *bufsizeP );
}
- else if ( *buflenP + len >= *bufsizeP )
+ else if ( *buflenP + len >= *bufsizeP ) /* allow for NUL */
{
*bufsizeP = *buflenP + len + 500;
*bufP = (char*) e_realloc( (void*) *bufP, *bufsizeP );
@@ -2997,6 +3092,9 @@ get_method_str( int m )
case METHOD_GET: return "GET";
case METHOD_HEAD: return "HEAD";
case METHOD_POST: return "POST";
+ case METHOD_PUT: return "PUT";
+ case METHOD_DELETE: return "DELETE";
+ case METHOD_TRACE: return "TRACE";
default: return "UNKNOWN";
}
}
@@ -3262,7 +3360,7 @@ static void
handle_write_timeout( int sig )
{
syslog( LOG_INFO, "%.80s connection timed out writing", ntoa( &client_addr ) );
- exit( 1 );
+ finish_request( 1 );
}
diff --git a/scripts/mini_httpd.sh b/scripts/mini_httpd.sh
index 372ecee..61e7922 100755
--- a/scripts/mini_httpd.sh
+++ b/scripts/mini_httpd.sh
@@ -2,13 +2,16 @@
#
# mini_httpd.sh - startup script for mini_httpd on FreeBSD
#
-# This goes in /usr/local/etc/rc.d and gets run at boot-time.
+# This should be manually installed as:
+# /usr/local/etc/rc.d/mini_httpd
+# It gets run at boot-time.
#
# Variables available:
-# mini_httpd_enable='YES/NO'
-# mini_httpd_program='path'
-# mini_httpd_pidfile='path'
-# mini_httpd_devfs='path'
+# mini_httpd_enable='YES'
+# mini_httpd_program='/usr/local/sbin/mini_httpd'
+# mini_httpd_pidfile='/var/run/mini_httpd.pid'
+# mini_httpd_devfs=...
+# mini_httpd_flags=...
#
# PROVIDE: mini_httpd
# REQUIRE: LOGIN FILESYSTEMS
@@ -18,31 +21,21 @@
name='mini_httpd'
rcvar='mini_httpd_enable'
+start_precmd='mini_httpd_precmd'
+mini_httpd_enable_defval='NO'
load_rc_config "$name"
-
-# Defaults.
-mini_httpd_enable="${mini_httpd_enable:-'NO'}"
-mini_httpd_program="${mini_httpd_program:-'/usr/local/sbin/mini_httpd'}"
-mini_httpd_pidfile="${mini_httpd_pidfile:-'/var/run/mini_httpd.pid'}"
+command="${mini_httpd_program:-/usr/local/sbin/${name}}"
+pidfile="${mini_httpd_pidfile:-/var/run/${name}.pid}"
+command_args="-i ${pidfile}"
mini_httpd_precmd ()
- {
- if [ '' != "$mini_httpd_devfs" ] ; then
- mount -t devfs devfs "$mini_httpd_devfs"
- devfs -m "$mini_httpd_devfs" rule -s 1 applyset
- devfs -m "$mini_httpd_devfs" rule -s 2 applyset
- fi
- }
-
-mini_httpd_stop ()
- {
- kill -USR1 `cat "$pidfile"`
- }
-
-command="$mini_httpd_program"
-pidfile="$mini_httpd_pidfile"
-start_precmd='mini_httpd_precmd'
-stop_cmd='mini_httpd_stop'
+{
+ if [ -n "$mini_httpd_devfs" ] ; then
+ mount -t devfs devfs "$mini_httpd_devfs"
+ devfs -m "$mini_httpd_devfs" rule -s 1 applyset
+ devfs -m "$mini_httpd_devfs" rule -s 2 applyset
+ fi
+}
run_rc_command "$1"
diff --git a/version.h b/version.h
index 22b8730..18441eb 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,7 @@
#ifndef _VERSION_H_
#define _VERSION_H_
-#define SERVER_SOFTWARE "mini_httpd/1.23 28Dec2015"
+#define SERVER_SOFTWARE "mini_httpd/1.30 26Oct2018"
#define SERVER_URL "http://www.acme.com/software/mini_httpd/"
#endif /* _VERSION_H_ */