Httpd Written In Postscript? Shell?
eMBee writes: "You thought the kernel-httpd is weird?
then look at these: a shell script, and another one in Postscript." Ya know, this kinda stuff gives me faith in humanity. Faith that we've evolved too far: it's time to back-up to, say ... using bone chips as knives ;)
"To install it, run from inetd:"
/usr/bin/gs gs -dNODISPLAY -q \
/home/pugo/src/postscript/pshttpd/pshttpd.ps
= == % PS-HTTPD V1.0 % = ==== /get_file % read file /infile /buff 2048 string def { % loop infile buff readstring { stdout exch writestring /read_command % read /command { /stdin (%stdin) (r) file def /inbuff 256 string def /command exch def } def /concatstr % (a) (b) -- (ab) { /beta exch def /alfa /buffer 1024 string def alfa buffer copy pop buffer alfa length beta putinterval buffer (\000) /hitcount { /hitfile (/usr/local/psweb/hits) (r) file def /hits 16 /hitfile (/usr/local/psweb/hits) (w+) file def cvi 1 /print_header { stdout (HTTP/1.0 200 /parse_result { command token { (GET) eq { ( ) search { root exch /filename exch def pop pop % define filename and clean stack filename /filename exch def } if % /infile exch (r) file def % open file print_header get_file } if } if } if } def % Init /stdout (%stdout) (w) file def /command () def % Root-path (root of WWW-pages)
8080 stream tcp nowait nobody
Here's the source, in case the server gets PSDotted:
%! %================================================
Copyright 2000 Anders Karlsson, pugo@pugo.org % License: GNU General Public License
%==============================================
and send it to %stdout {
} { stdout exch writestring infile closefile exit } ifelse } bind loop } def
command from stdin and define it to
stdin inbuff readline pop
exch def
search pop exch pop exch pop } def
string def hitfile hits readstring pop hitfile closefile
add hits cvs hitfile exch writestring hitfile closefile } def
OK\n\n) writestring % stdout (Server: PS-HTTPD/1.0\n) writestring % stdout (Content-type:
text/html\n) writestring } def
concatstr % build path
filename length 1 sub 1 getinterval (/) eq { filename (index.html) concatstr
add index.html filename (..) search { stdout (4711 Stupid user error!\n\n) writestring quit } if pop
filename
environment
/root (/usr/local/psweb) def %% Uncomment this and place a file named "/usr/local/psweb/hits" %%
(you can change the path in hitcount above) containing only a "0" to %% get a hitcount % % hitcount
% add one to the hitcount % Read a command from the server read_command parse_result quit
"... it's time to back-up to, say ... using bone chips as knives"
:-)
Funny you should mention that - a lot of very delicate eye-surgery these days is done with glass or obsidian knives because at the small sizes needed they're a lot sharper than steel. The blades are flaked by Aleuts, who've been fashioning such knives for centuries, because they're the only ones who still have the skills to do it (incidentally making some of the most dangerous water-based weaponry in the world).
OK, it's mostly off-topic, but it's still damned cool
Some years ago, somebody set out to implement various things using only dd and sh. Their accomplishments included a text editor, a web server and -- to prove a point -- a Turing machine. The things could be found on the now non-existant http://dd.sh/ (fantastic, eh? :) but are now located on http://www.assurdo.com/dd.sh/. These things warm my heart. *happy sigh*
A modestly ugly HTTP server written in emacs lisp.
;;; Luke's Emacs Webserver ("LEW" aka "Loo" aka any toilet joke you please)
;;; Copyright (C) 1998-1999 Luke Gorrie
;;;
;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU General Public License
;;; as published by the Free Software Foundation; either version 2
;;; of the License, or (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, write to the Free Software
;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;;; TODO list:
;;; support HEAD requests
;;; add some sort of dynamic content facility, either for elisp `servlets' or cgi
;;; $Id: http-server.el,v 1.2 1999/07/01 19:01:06 luke Exp luke $
(setq http-hits 0)
;;; configuration
(setq http-404-message
(concat "File not found."
"File not found"
"
"
;; append "index.html" to and directory name
;; protect against accessing ../../ to get above document base
;; file exists?
;; not a regular file
"The file requested does not exist, or is not a regular file, "
"or something."
""))
;; regex path -> mime-type mappings
(setq mimetypes-alist
'(("\\.gif" .
"image/gif")
("\\.jpg" .
"image/jpeg")
("\\.png" .
"image/png")
("\\.\\(el\\|txt\\|erl\\|scm\\)" .
"text/plain")
("\\.html" .
"text/html")
("\\.\\(tar\\|gz\\|tgz\\|zip\\|exe\\|pdf\\|ps\\)" .
"application/octet-stream")))
;; document root directory
(setq document-base "/mnt/baked/www/vegetable.org")
;;; http server code
;; open a socket to the connection-connector with a transaction callback to
;; serve the request when it arrives
(defun offer-http-service ()
(let ((service-successful nil))
(unwind-protect
(progn
(lexical-let ((proc (open-network-stream "bar" "baz" "localhost" 8012)))
(set-process-sentinel proc 'http-sentinel)
(let ((tq (tq-create proc)))
(tq-enqueue tq "" ".*\r\n\r\n" "Http Connection"
#'(lambda (closure answer)
(lexical-let ((answer answer))
(handle-http-request proc answer))))))
(setq service-successful t))
(if (not service-successful)
(progn (offer-http-service) (message "service failed"))))))
;; called if there's an error in between offer-http-service
;; and handle-http-request -- usually when the connection is broken
(defun http-sentinel (proc sentinel)
(offer-http-service))
;; read a file as a string
(defun filestring (filename)
(save-excursion
(switch-to-buffer "*loading-work*")
(insert-file-contents filename)
(let ((contents (buffer-string)))
(kill-buffer "*loading-work*")
contents)))
(defun process-send-file (process filename)
(save-excursion
(switch-to-buffer "*loading-work*")
(insert-file-contents filename)
(mark-whole-buffer)
(process-send-region process (point) (mark))
(kill-buffer "*loading-work")))
;; returns the file length
(defun load-file-for-io (filename)
(save-excursion
(switch-to-buffer "*loading-work*")
(insert-file-contents filename)
(mark-whole-buffer)
(- (mark) (point))))
(defun send-current-file (process)
(save-excursion
(switch-to-buffer "*loading-work*")
(mark-whole-buffer)
(process-send-region process (point) (mark))
(kill-buffer "*loading-work*")))
;; handle a http request. Takes a process and request with headers,
;; and sends the response
(defun handle-http-request (proc request)
(unwind-protect
(progn
(string-match "\\( \\)\\(.*\\)\\( \\)" request)
(let ((r-path (concat document-base (match-string 2 request))))
(message r-path)
(if (string-match "/$" r-path)
(setq r-path (concat r-path "index.html")))
(if (string-match "\\.\\." r-path)
(setq r-path (concat document-base "/index.html")))
(if (file-regular-p r-path)
(let ((length (load-file-for-io r-path)))
(message "request")
(process-send-string
proc (concat "HTTP/1.0 200 OK\r\n"
"Content-Type: "
(get-mimetype r-path mimetypes-alist "text/html")
"\r\n"
"Content-length: "
(number-to-string length) "\r\n"
"Server: " (version) "\r\n"
"Last-Modified: " (current-time-string) "\r\n"
"Connection: close\r\n"
"\r\n"
))
(send-current-file proc))
(process-send-string
proc (concat "HTTP/1.0 404 Not Found\r\n"
"Connection: close\r\n"
"Content-Type: text/html\r\n"
"\r\n"
http-404-message)))
(delete-process proc)
(setq http-hits (+ 1 http-hits)))))
(offer-http-service))
;; show number of hits
(defun show-http-stats ()
(message (concat "HTTP hits: " (number-to-string http-hits))))
;; determine the mimetype of path
(defun get-mimetype (path map default)
(if (eq map nil)
default
(let ((element (car map)))
(if (string-match (car element) path)
(cdr element)
(get-mimetype path (cdr map) default)))))
Man, trying to secure a httpd written in sh is gonna suck. Just for starters, try:/ ../../../../etc/passwd
http://jester.vip.net.pl:8081/../../../../../..
It also appears you can execute arbitrary commands by changing your reverse DNS to contain the command and '|', ';' and/or '&'.
There is a good reason not to write CGI scripts in shell, and an even better one not to write a whole httpd!
http://www3.l0pht.com/~dildog/webserver.doc
Note that you can upload files, download them, execute programs, and change file attributes by clicking on them in the directory list. The webserver shuts down when they close the document though, since I didn't bother to try to make the tool any more insidious than it was already.
Have fun.