diff -Nru hello-2.1.1/debian/changelog hello-insecure-2.1.1/debian/changelog --- hello-2.1.1/debian/changelog 2006-05-02 12:32:57.000000000 +0200 +++ hello-insecure-2.1.1/debian/changelog 2006-05-02 09:57:52.000000000 +0200 @@ -1,3 +1,10 @@ +hello (2.1.1-5) unstable; urgency=low + + * *Insecure* version of the hello world program. Sets up a daemon + listener with a buffer overflow and fails to drop privileges. + + -- Javier Fernandez-Sanguino Pen~a Tue, 2 May 2006 09:57:17 +0200 + hello (2.1.1-4) unstable; urgency=low * Updated config.guess and config.sub for GNU/K*BSD. diff -Nru hello-2.1.1/debian/control hello-insecure-2.1.1/debian/control --- hello-2.1.1/debian/control 2006-05-02 12:32:57.000000000 +0200 +++ hello-insecure-2.1.1/debian/control 2006-05-02 09:59:28.000000000 +0200 @@ -1,17 +1,16 @@ Source: hello Section: devel -Priority: optional -Maintainer: Santiago Vila +Priority: extra +Maintainer: Javier Fernandez-Sanguino Pen~a Standards-Version: 3.6.1 -Package: hello +Package: hello-daemon-insecure Architecture: any Depends: ${shlibs:Depends} -Description: The classic greeting, and a good example +Description: The classic greeting, and a good example of insecure programming The GNU hello program produces a familiar, friendly greeting. It allows non-programmers to use a classic computer science tool which would otherwise be unavailable to them. . - Seriously, though: this is an example of how to do a Debian package. - It is the Debian version of the GNU Project's `hello world' program - (which is itself an example for the GNU Project). + This is an example of how *not* to do a Debian package that provides + a network daemon. diff -Nru hello-2.1.1/debian/hello.init hello-insecure-2.1.1/debian/hello.init --- hello-2.1.1/debian/hello.init 1970-01-01 01:00:00.000000000 +0100 +++ hello-insecure-2.1.1/debian/hello.init 2006-05-02 12:13:55.000000000 +0200 @@ -0,0 +1,88 @@ +#! /bin/sh +# /etc/init.d/hello: start the hello world! daemon. + +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +pidfile=/var/run/hello.pid +binpath=/usr/bin/hello + +test -x $binpath || exit 0 + +# Options for the daemon +OPTIONS="-s" + +running() +{ + # No pidfile, probably no daemon present + # + if [ ! -f $pidfile ] + then + return 1 + fi + + pid=`cat $pidfile` + + # No pid, probably no daemon present + # + if [ -z "$pid" ] + then + return 1 + fi + + if [ ! -d /proc/$pid ] + then + return 1 + fi + + cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1` + + # No daemon? + # + if [ "$cmd" != "$binpath" ] + then + return 1 + fi + + return 0 +} + +case "$1" in + start) + echo -n "Starting hello world daemon: hello" + start-stop-daemon --background --make-pidfile --pidfile $pidfile --start --quiet --exec $binpath -- -s + echo "." + ;; + stop) + echo -n "Stopping hello world daemon: hello" + start-stop-daemon --stop --quiet --exec $binpath --pidfile $pidfile + echo "." + ;; + reload|force-reload) + echo -n "Reloading hello world daemon: hello" + start-stop-daemon --stop --quiet --signal 1 --exec $binpath --pidfile $pidfile + echo "." + ;; + restart) + echo -n "Restarting hello world daemon: hello" + start-stop-daemon --stop --quiet --exec $binpath --pidfile $pidfile + sleep 1 + start-stop-daemon --start --quiet --exec $binpath -- $OPTIONS + echo "." + ;; + reload-or-restart) + if running + then + echo -n "Reloading hello world daemon: hello" + start-stop-daemon --stop --quiet --signal 1 --exec $binpath --pidfile $pidfile + else + echo -n "Restarting hello world daemon: hello" + start-stop-daemon --start --quiet --exec $binpath -- $SYSLOGD + fi + echo "." + ;; + *) + echo "Usage: /etc/init.d/hello {start|stop|reload|restart|force-reload|reload-or-restart}" + exit 1 +esac + +exit 0 diff -Nru hello-2.1.1/debian/postinst hello-insecure-2.1.1/debian/postinst --- hello-2.1.1/debian/postinst 2006-05-02 12:32:57.000000000 +0200 +++ hello-insecure-2.1.1/debian/postinst 2006-05-18 19:36:08.000000000 +0200 @@ -1,4 +1,43 @@ -#!/bin/sh +#!/bin/sh set -e install-info --quiet --section Development Development \ /usr/share/info/hello.info + +# Setup the config file +if [ -e /etc/default/hello ] ; then + sed -e 's/=no/=yes/' /tmp/hello_default.$$ + mv /tmp/hello_default.$$ /etc/default/hello +else + echo -e "start=no\n">>/etc/default/hello +fi + +# Install the daemon +if [ "$1" = "configure" ] +then + if [ -f /etc/init.d/hello ] + then + set +e + if [ -x /usr/sbin/invoke-rc.d ] + then + invoke-rc.d hello stop + else + sh /etc/init.d/hello stop + fi + set -e + fi + + update-rc.d hello defaults 10 90 >/dev/null + if [ -f /etc/init.d/hello ] + then + set +e + if [ -x /usr/sbin/invoke-rc.d ] + then + invoke-rc.d hello start + else + sh /etc/init.d/hello start + fi + set -e + fi +fi + + diff -Nru hello-2.1.1/debian/postrm hello-insecure-2.1.1/debian/postrm --- hello-2.1.1/debian/postrm 1970-01-01 01:00:00.000000000 +0100 +++ hello-insecure-2.1.1/debian/postrm 2006-05-02 12:17:04.000000000 +0200 @@ -0,0 +1,8 @@ +#! /bin/sh + +set -e + +if [ "$1" = "purge" ] +then + update-rc.d hello remove >/dev/null +fi diff -Nru hello-2.1.1/debian/rules hello-insecure-2.1.1/debian/rules --- hello-2.1.1/debian/rules 2006-05-02 12:32:57.000000000 +0200 +++ hello-insecure-2.1.1/debian/rules 2006-05-18 19:21:52.000000000 +0200 @@ -11,7 +11,7 @@ docdir = debian/tmp/usr/share/doc/$(package) CC = gcc -CFLAGS = -g -Wall +CFLAGS = -g -Wall -DDEBUG INSTALL_PROGRAM = install ifeq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) @@ -43,10 +43,12 @@ $(checkdir) rm -rf debian/tmp install -d debian/tmp/DEBIAN $(docdir) - install -m 755 debian/postinst debian/prerm debian/tmp/DEBIAN + install -m 755 debian/postinst debian/prerm debian/postrm debian/tmp/DEBIAN $(MAKE) INSTALL_PROGRAM="$(INSTALL_PROGRAM)" \ prefix=$$(pwd)/debian/tmp/usr install cd debian/tmp && mv usr/info usr/man usr/share + install -d debian/tmp/etc/init.d/ + install -m 755 debian/hello.init debian/tmp/etc/init.d/hello cp -a NEWS debian/copyright $(docdir) cp -a debian/changelog $(docdir)/changelog.Debian cp -a ChangeLog $(docdir)/changelog diff -Nru hello-2.1.1/man/hello.1 hello-insecure-2.1.1/man/hello.1 --- hello-2.1.1/man/hello.1 2002-06-09 07:30:03.000000000 +0200 +++ hello-insecure-2.1.1/man/hello.1 2006-05-18 19:36:21.000000000 +0200 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.24. -.TH HELLO "1" "June 2002" "GNU hello 2.1.1" GNU +.TH HELLO "1" "May 2006" "GNU hello 2.1.1" GNU .SH NAME hello \- Friendly Greeting Program .SH SYNOPSIS @@ -20,6 +20,9 @@ \fB\-n\fR, \fB\-\-next\-generation\fR use next-generation greeting format .TP +\fB\-s\fR, \fB\-\-server\fR +set up a network server +.TP \fB\-m\fR, \fB\-\-mail\fR print your mail .SH "REPORTING BUGS" diff -Nru hello-2.1.1/src/hello.c hello-insecure-2.1.1/src/hello.c --- hello-2.1.1/src/hello.c 2006-05-02 12:32:57.000000000 +0200 +++ hello-insecure-2.1.1/src/hello.c 2006-05-02 10:24:52.000000000 +0200 @@ -102,6 +102,7 @@ { "traditional", no_argument, NULL, 't' }, { "next-generation", no_argument, NULL, 'n' }, { "mail", no_argument, NULL, 'm' }, + { "server", no_argument, NULL, 's' }, { NULL, 0, NULL, 0 } }; @@ -115,7 +116,7 @@ char *argv[]; { int optc; - int h = 0, v = 0, t = 0, m = 0, n = 0, lose = 0, z = 0; + int h = 0, v = 0, t = 0, m = 0, n = 0, lose = 0, z = 0, s=0; progname = argv[0]; @@ -131,7 +132,7 @@ #endif #define king - while ((optc = getopt_long (argc, argv, "hmntv", longopts, (int *) 0)) + while ((optc = getopt_long (argc, argv, "hmnstv", longopts, (int *) 0)) != EOF) switch (optc) { @@ -150,6 +151,9 @@ case 't': t = 1; break; + case 's': + s = 1; + break; default: lose = 1; break; @@ -195,6 +199,7 @@ fputs (_("\ -t, --traditional use traditional greeting format\n\ -n, --next-generation use next-generation greeting format\n\ + -s, --server set up a network server\n\ -m, --mail print your mail\n"), stdout); printf ("\n"); @@ -325,6 +330,9 @@ else if (z) puts (_("Nothing happens here.")); + else if (s) + server(1025); + else /* Print greeting message and exit. */ { diff -Nru hello-2.1.1/src/Makefile.am hello-insecure-2.1.1/src/Makefile.am --- hello-2.1.1/src/Makefile.am 2002-05-22 19:10:19.000000000 +0200 +++ hello-insecure-2.1.1/src/Makefile.am 2006-05-02 10:21:20.000000000 +0200 @@ -19,7 +19,7 @@ ## Process this file with automake to produce Makefile.in. bin_PROGRAMS = hello -hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h +hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h server.h server.c # hello_SOURCES = getopt.c getopt1.c getopt.h hello.c system.h \ # version-etc.h version-etc.c hello_LDADD = @LIBINTL@ @ALLOCA@ diff -Nru hello-2.1.1/src/Makefile.in hello-insecure-2.1.1/src/Makefile.in --- hello-2.1.1/src/Makefile.in 2002-06-09 07:29:18.000000000 +0200 +++ hello-insecure-2.1.1/src/Makefile.in 2006-05-02 10:21:47.000000000 +0200 @@ -102,7 +102,7 @@ ke_PRE = @ke_PRE@ bin_PROGRAMS = hello -hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h +hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h server.h server.c # hello_SOURCES = getopt.c getopt1.c getopt.h hello.c system.h \ # version-etc.h version-etc.c hello_LDADD = @LIBINTL@ @ALLOCA@ @@ -119,7 +119,7 @@ PROGRAMS = $(bin_PROGRAMS) am_hello_OBJECTS = hello.$(OBJEXT) version.$(OBJEXT) getopt.$(OBJEXT) \ - getopt1.$(OBJEXT) + getopt1.$(OBJEXT) server.$(OBJEXT) hello_OBJECTS = $(am_hello_OBJECTS) hello_DEPENDENCIES = @ALLOCA@ hello_LDFLAGS = @@ -131,7 +131,7 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = $(DEPDIR)/alloca.Po ./$(DEPDIR)/getopt.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/getopt1.Po ./$(DEPDIR)/hello.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/version.Po +@AMDEP_TRUE@ ./$(DEPDIR)/version.Po ./$(DEPDIR)/server.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -191,6 +191,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hello.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ distclean-depend: -rm -rf $(DEPDIR) ./$(DEPDIR) diff -Nru hello-2.1.1/src/server.c hello-insecure-2.1.1/src/server.c --- hello-2.1.1/src/server.c 1970-01-01 01:00:00.000000000 +0100 +++ hello-insecure-2.1.1/src/server.c 2006-05-18 19:21:52.000000000 +0200 @@ -0,0 +1,266 @@ +/* micro_inetd - simple network service spawner +** +** Copyright (C)1996,2000 by Jef Poskanzer . +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED) +#define USE_IPV6 +#endif + +#ifdef DEBUG +#define LOG "/tmp/server.log" +#endif + +static int initialize_listen_socket( int pf, int af, unsigned short port ); +static void child_handler( int sig ); + + + +/* TODO: make it possible to set the IP address */ +int +server( unsigned short port ) +{ + int listen_fd, conn_fd; + struct sockaddr_in sin; + socklen_t sz; + char buffer[1024]; + char *answer; + answer = malloc(sizeof(char)*10); + int success; + int pid; + int status; +#ifdef DEBUG + FILE * logfile; +#endif + + bzero(buffer, sizeof buffer); + bzero(answer, sizeof answer); + + /* Initialize listen socket. If we have v6 use that, since its sockets + ** will accept v4 connections too. Otherwise just use v4. + */ +#ifdef USE_IPV6 + listen_fd = initialize_listen_socket( PF_INET6, AF_INET6, port ); +#else /* USE_IPV6 */ + listen_fd = initialize_listen_socket( PF_INET, AF_INET, port ); +#endif /* USE_IPV6 */ + + printf ("Server socket initialized\n"); + + /* Initialise log file */ + + /* Set up a signal handler for child reaping. */ + /* (void) signal( SIGCHLD, child_handler ); */ + + for (;;) + { + /* Accept a new connection. */ + sz = sizeof(sin); + conn_fd = accept( listen_fd, (struct sockaddr*) &sin, &sz ); + if ( conn_fd < 0 ) + { + if ( errno == EINTR ) /* because of SIGCHLD (or ptrace) */ + continue; + perror( "accept" ); + exit( 1 ); + } + + printf ("New connection\n"); /* TODO: print where from */ + /* Fork a sub-process to handle the connection. */ + pid = fork(); + if ( pid < 0 ) { + perror("fork"); + exit(1); + } + if ( pid == 0 ) { + /* Close standard descriptors and the listen socket. */ + (void) close(0); + (void) close(1); + (void) close(2); + (void) close(listen_fd); +#ifdef DEBUG + logfile = fopen( LOG, "a+" ); +#endif + + /* Read a limited string from the socket */ + success = read (conn_fd, buffer, sizeof buffer-1); + buffer[sizeof(buffer)]=0; + if (success < 0) { +#ifdef DEBUG + fprintf (logfile, strerror (errno)); + fclose(logfile); +#endif + exit(1); + } + /* Say hello! */ +#ifdef DEBUG + fprintf (logfile, "Read %i bytes\n", success); + fprintf (logfile, "Answering to "); + fprintf (logfile, buffer); + fprintf (logfile, "\n"); +#endif + printf ("Answering back.\n"); /* TODO: print where to */ + sprintf (answer, "hello, %s\n", buffer); + /* success = send(conn_fd, "hello, ", strlen("hello, "), 0); + if (success < 0) { +#ifdef DEBUG + fprintf (logfile, strerror (errno)); + fclose(logfile); +#endif + exit(1); + } + strcpy(answer[strlen(answer)], buffer); */ + printf ("Answer length is %i\n", strlen(answer)); + success = send(conn_fd, answer, strlen(answer), 0); + if (success < 0) { +#ifdef DEBUG + fprintf (logfile, strerror (errno)); + fclose(logfile); +#endif + exit(1); + } + printf ("Answer sent.\n"); /* TODO: print where to */ +#ifdef DEBUG + fclose(logfile); +#endif + exit(0); + } + /* Parent process. */ + printf ("Forked children %i\n", pid); + (void) close( conn_fd ); + printf ("Waiting for children %i to die...\n", pid); + waitpid(-1, &status, 0); + if ( ! WIFEXITED(status) ) { + printf ("The children did not die normally, exit %i, signal %i\n", WEXITSTATUS(status), WTERMSIG(status)); + } else { + printf ("Child died.\n"); + } + } +} + + + static void +child_handler( int sig ) +{ + pid_t pid; + int status; + + /* Set up the signal handler again. Don't need to do this on BSD + ** systems, but it doesn't hurt. + */ + (void) signal( SIGCHLD, child_handler ); + + /* Reap defunct children until there aren't any more. */ + for (;;) + { + pid = waitpid( (pid_t) -1, &status, WNOHANG ); + if ( (int) pid == 0 ) /* none left */ + break; + if ( (int) pid < 0 ) + { + if ( errno == EINTR ) /* because of ptrace */ + continue; + /* ECHILD shouldn't happen with the WNOHANG option, but with + ** some kernels it does anyway. Ignore it. + */ + if ( errno != ECHILD ) + perror( "waitpid" ); + break; + } + } +} + + + static int +initialize_listen_socket( int pf, int af, unsigned short port ) +{ + int listen_fd; + int on; +#ifdef USE_IPV6 + struct sockaddr_in6 sa; +#else /* USE_IPV6 */ + struct sockaddr_in sa; +#endif /* USE_IPV6 */ + + /* Create socket. */ + listen_fd = socket( pf, SOCK_STREAM, 0 ); + if ( listen_fd < 0 ) + { + perror( "socket" ); + exit( 1 ); + } + + /* Allow reuse of local addresses. */ + on = 1; + if ( setsockopt( + listen_fd, SOL_SOCKET, SO_REUSEADDR, (char*) &on, sizeof(on) ) < 0 ) + { + perror( "setsockopt SO_REUSEADDR" ); + exit( 1 ); + } + + /* Set up the sockaddr. */ + (void) memset( (char*) &sa, 0, sizeof(sa) ); +#ifdef USE_IPV6 + sa.sin6_family = af; + sa.sin6_addr = in6addr_any; + sa.sin6_port = htons( port ); +#else /* USE_IPV6 */ + sa.sin_family = af; + sa.sin_addr.s_addr = htonl( INADDR_ANY ); + sa.sin_port = htons( port ); +#endif /* USE_IPV6 */ + + /* Bind it to the socket. */ + if ( bind( listen_fd, (struct sockaddr*) &sa, sizeof(sa) ) < 0 ) + { + perror( "bind" ); + exit( 1 ); + } + + /* Start a listen going. */ + if ( listen( listen_fd, 1024 ) < 0 ) + { + perror( "listen" ); + exit( 1 ); + } + + return listen_fd; +} diff -Nru hello-2.1.1/src/server.h hello-insecure-2.1.1/src/server.h --- hello-2.1.1/src/server.h 1970-01-01 01:00:00.000000000 +0100 +++ hello-insecure-2.1.1/src/server.h 2006-05-02 10:18:24.000000000 +0200 @@ -0,0 +1,30 @@ +/* micro_inetd - simple network service spawner +** +** Copyright (C)1996,2000 by Jef Poskanzer . +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +*/ + +int server( unsigned short port ); +int initialize_listen_socket( int pf, int af, unsigned short port ); +void child_handler( int sig );