Sunday, November 26, 2017

Web Server Hack

I needed a quick hack of a web server that would simply serve up files on an embedded Linux machine that has only a minimal kernel and shell.  This assumes a working knowledge of Linux and shell scripting.  The script text should be put in a text file and marked as executable.  In my case I chose to use /usr/bin/wwwd.

Tell Linux this is a shell script.

#! /bin/sh
# 

Define the end of line sequence and the location of our web pages.

eol=$(printf "\r\n")
base=/var/www


We let inetd deal with the network part of being a web server.  We just read the HTTP request and then parse (and ignore) the header of the request.

read request


Find the end of the header (it is separated from the body by a blank line.)

while /bin/true; do
  read header
  [ "$header" == "$eol" ] && break;
done


Parse the request and construct a path to the desired file.

url="${request#GET }"
url="${url% HTTP/*}"
filename="$base$url" 


If the file exists, then send it to the client with a minimal HTTP header.  If the file does not exist, then issue a 404 error.
 
if [ -f "$filename" ]; then
  echo -e "HTTP/1.1 200 OK\r"
  echo -e "Content-Type: text/html\r"
  echo -e "\r"
  cat "$filename"
  echo -e "\r"
else
  echo -e "HTTP/1.1 404 Not Found\r"
  echo -e "Content-Type: text/html\r"
  echo -e "\r"
  echo -e "404 Not Found\r"
  echo -e "\r"
fi


exit

That is really all there is to this hack and this is about as minimalistic as you can get.  If you want to add CGI capabilities, we would need to construct an environment variable to pass to the program to be executed to give it the query that was issued and then pass the program output back as the result of the HTTP GET request.  Since I don't need this ability yet, I will leave that as an exercise for the interested reader. 

In order to integrate with inetd we need to add a line to /etc/inetd.conf to tell inetd what application to launch when web connections are received.  In my case this script is named /usr/bin/wwwd.  Don't forget to make it executable:

chmod +x /usr/bin/wwwd

Add the following line, adjusting the path as necessary to point to your script.  You can find full details on inetd here.

www     stream tcp nowait nobody /usr/bin/wwwd wwwd 

You then need to restart inetd which can be accomplished by killing that process.  On my embedded Linux machine, the following command line will suffice:

kill -SIGHUP $(cat /var/run/inetd.pid)

You should now be able to point your web browser to your device and fetch any of the files (HTML or otherwise) that are contained in /var/www.

As always, if you have any questions or issues, I am happy to help. 
 

No comments:

Post a Comment