[Gllug] SSH client and httpd
Richard Jones
rich at annexia.org
Tue Apr 15 11:31:29 UTC 2003
On Mon, Apr 14, 2003 at 10:55:33PM +0100, Adrian McMenamin wrote:
> I would like a very small (when built statically) ssh client and httpd server
> to run on a Dreamcast - so I can fufil a promise I made a long time ago to
> run a httpd off the filesystem on the visual memory system on this thing.
>
> (Actually the ssh client is to allow me to access my other boxes from the
> Dreamcast rather than anything to do with a webserver)
>
> Any recommendations? The simpler the better as I am not intending to serve
> anything beyond a static page or two. Further more something that preserved
> my mtd by caching the requested pages in memory would be extra welcome.
For the ssh client: OpenZaurus comes with OpenSSH. The client is:
$ ls -l `which ssh`
-rwxr-xr-x 1 root root 226020 Jan 1 1970 /usr/bin/ssh
I don't know if that's small enough for you.
I have a webserver, rws, which is very small, but unfortunately
it would require some small amount of porting to the Hitachi micro-
processor used in the Dreamcast. http://www.annexia.org/freeware/rws/
Also see below.
Rich.
----------------------------------------------------------------------
/* This is the C version of httpd.pl (the Perl minimal webserver).
*
* By Richard W.M. Jones <rich at annexia.org>
*
* To compile:
*
* gcc -Wall -Os -s httpd.c -o httpd
*
* To install, add the following line to /etc/inetd.conf:
*
* port stream tcp nowait root /usr/sbin/tcpd /path/to/httpd /path/to/content/dir user
*
* ``user'' is the user that the webserver changes to on running. I
* suggest using ``nobody''. The /path/to/content/dir is the top level
* directory containing files to serve. The webserver chroot's to this
* directory when it runs.
*
* Reasonable steps have been made to ensure that this webserver is
* secure against denial of service attacks and buffer overflows. It
* is believed to be secure, however use at your own risk and check the
* code yourself first. There's not much of it.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <syslog.h>
int
main (int argc, char *argv[])
{
const char *web_content_dir, *user;
char request[8192];
char data[8192];
int n, nbytes, i, fd;
struct stat statbuf;
struct passwd *pw;
/* Open a connection to syslogd. */
openlog ("httpd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
/* Check arguments. */
if (argc != 3)
{
syslog (LOG_ERR, "usage: httpd /path/to/content/dir user");
exit (1);
}
web_content_dir = argv[1];
user = argv[2];
/* Chroot and change user and group ID. */
if ((pw = getpwnam (user)) == 0)
{
syslog (LOG_ERR, "getpwnam: %s: %m", user);
exit (1);
}
initgroups (user, pw->pw_gid);
if (chdir (web_content_dir) == -1)
{
syslog (LOG_ERR, "chdir: %s: %m", web_content_dir);
exit (1);
}
if (chroot (".") == -1)
{
syslog (LOG_ERR, "chroot: %m");
exit (1);
}
if (setgid (pw->pw_gid) == -1 ||
setuid (pw->pw_uid) == -1)
{
syslog (LOG_ERR, "setgid or setuid: %m");
exit (1);
}
/* Time out the request after 30 seconds. */
alarm (30);
/* Read the request into memory. */
if ((n = read (0, request, sizeof request)) <= 0)
{
syslog (LOG_ERR, "read: %m");
exit (1);
}
/* We're only into HTTP/0.9, so no keepalives or anything. */
shutdown (0, 0);
/* Parse the request. */
if (n < 5 || request[0] != 'G' || request[1] != 'E' ||
request[2] != 'T' || request[3] != ' ')
{
syslog (LOG_ERR, "not a GET method");
exit (1);
}
for (i = 4; i < n; ++i)
{
if (request[i] == '\0' || request[i] == ' ' ||
request[i] == '\t' || request[i] == '\n' ||
request[i] == '\r')
{
request[i] = '\0';
break;
}
}
if (i == n)
{
syslog (LOG_ERR, "URL too long\n");
exit (1);
}
if (i == 4)
{
syslog (LOG_ERR, "no URL in GET request");
exit (1);
}
/* Stat the file. If it's a directory, then append /index.html. */
if (stat (&request[4], &statbuf) == -1)
{
syslog (LOG_ERR, "%s: %m", &request[4]);
exit (1);
}
if (S_ISDIR (statbuf.st_mode))
{
/* Check there's enough room to append in-place before we
* actually append.
*/
if (i >= sizeof request - 12)
{
syslog (LOG_ERR, "URL too long to append index.html to name");
exit (1);
}
request[i++] = '/';
request[i++] = 'i';
request[i++] = 'n';
request[i++] = 'd';
request[i++] = 'e';
request[i++] = 'x';
request[i++] = '.';
request[i++] = 'h';
request[i++] = 't';
request[i++] = 'm';
request[i++] = 'l';
request[i++] = '\0';
}
/* Open the file and send it back to the user. */
fd = open (&request[4], O_RDONLY);
if (fd == -1)
{
syslog (LOG_ERR, "%s: %m", &request[4]);
exit (1);
}
nbytes = 0;
while ((n = read (fd, data, sizeof data)) > 0)
{
/* Time out the write after a further 30 seconds. */
alarm (30);
if (write (1, data, n) < n)
{
syslog (LOG_ERR, "write: %m");
exit (1);
}
nbytes += n;
}
if (n == -1)
{
syslog (LOG_ERR, "read: %m");
exit (1);
}
if (close (fd) == -1)
{
syslog (LOG_ERR, "close: %m");
exit (1);
}
/* Shut down the socket cleanly. */
if (close (1) == -1)
{
syslog (LOG_ERR, "close: %m");
exit (1);
}
/* Log the fact that the connection happened. */
syslog (LOG_INFO, "\"%s\" %d OK", request, nbytes);
exit (0);
}
----------------------------------------------------------------------
--
Richard Jones, Red Hat Inc. (London) and Merjis Ltd. http://www.merjis.com/
http://www.annexia.org/ Freshmeat projects: http://freshmeat.net/users/rwmj
NET::FTPSERVER is a full-featured, secure, configurable, database-backed
FTP server written in Perl: http://www.annexia.org/freeware/netftpserver/
--
Gllug mailing list - Gllug at linux.co.uk
http://list.ftech.net/mailman/listinfo/gllug
More information about the GLLUG
mailing list