diff --git a/src/.config b/src/.config index d9d62ed13..bf00fa412 100644 --- a/src/.config +++ b/src/.config @@ -86,7 +86,6 @@ STATIC_GET_SOURCE_URL=http://s.minos.io/s # CLOUD_FOUNDRY_CLI_URL=http://cli.run.pivotal.io/stable?release=linux64-binary&source=github - #################################################### # # # This section contains configuration properties # @@ -171,11 +170,13 @@ COPY_SOURCE_ISO=true # lua - scripting language # static_get - portable binaries for Linux (http://s.minos.io) # cf_cli - CLoud Foundry CLI (command line interface) +# nweb - simple mini http server # # Refer to the README file for more information. # #OVERLAY_BUNDLES=glibc_full,links,dropbear,java,felix,mll_utils,lua,static_get,cf_cli #OVERLAY_BUNDLES=cf_cli +OVERLY_BUNDLES=nweb # This property enables the standard penguin boot logo in the upper left corner # of the screen. The property is used in 'xx_build_kernel.sh'. The default value diff --git a/src/README b/src/README index f0f32fbf8..0968a783f 100644 --- a/src/README +++ b/src/README @@ -63,6 +63,8 @@ Currently available overlay bundles: * Lua - The Lua Scripting Language 5.3. Requires ~ 800kb additional space. Use the "lua" command to run an interactive lua interpreter +* nweb - nweb is a very small and easy to use webserver + ### ### ### I only provide the build scripts. It's entirely up to you to configure and diff --git a/src/minimal_overlay/bundles/nweb/bundle.sh b/src/minimal_overlay/bundles/nweb/bundle.sh new file mode 100755 index 000000000..def88ed6b --- /dev/null +++ b/src/minimal_overlay/bundles/nweb/bundle.sh @@ -0,0 +1,33 @@ +#!/bin/sh +SRC_DIR=$(pwd) + +# Find the main source directory +cd ../../.. +MAIN_SRC_DIR=$(pwd) +cd $SRC_DIR + +cd $MAIN_SRC_DIR/work/overlay/nweb + +# nweb +cc -O2 $(SRC_DIR)/nweb23.c -o nweb + +# client +#cc -O2 $(SRC_DIR)/client.c -o client + +echo "nweb has been build." + +install -d -m755 "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/usr" +install -d -m755 "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/usr/bin" +install -m755 nweb "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/usr/bin/nweb" +#install -m755 client "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/usr/bin/client" +install -d -m755 "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/srv/www" # FHS compliant location +install -m022 "$(SRC_DIR)/index.html" "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/svc/www/index.html" +install -m022 "$(SRC_DIR)/favicon.ico" "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/svc/www/favicon.ico" +install -d -m755 "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/usr/share" +install -d -m755 "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/usr/share/man" +install -d -m755 "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/usr/share/man/man8" +install -m022 "$(SRC_DIR)/nweb.8" "$MAIN_SRC_DIR/work/src/minimal_overlay/rootfs/usr/share/man/man8/nweb.8" + +echo "nweb has been installed." +echo "type 'man nweb' to see what it can do on your mimial system" + diff --git a/src/minimal_overlay/bundles/nweb/client.c b/src/minimal_overlay/bundles/nweb/client.c new file mode 100644 index 000000000..55887f9a9 --- /dev/null +++ b/src/minimal_overlay/bundles/nweb/client.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* YOU WILL HAVE TO CHANGE THESE TWO LINES TO MATCH YOUR CONFIG */ +#define PORT 8181 /* Port number as an integer - web server default is 80 */ +#define IP_ADDRESS "192.168.0.8" /* IP Address as a string */ + +char *command = "GET /index.html HTTP/1.0 \r\n\r\n" ; +/* Note: spaces are delimiters and VERY important */ + +#define BUFSIZE 8196 + +pexit(char * msg) +{ + perror(msg); + exit(1); +} + +main() +{ +int i,sockfd; +char buffer[BUFSIZE]; +static struct sockaddr_in serv_addr; + + printf("client trying to connect to %s and port %d\n",IP_ADDRESS,PORT); + if((sockfd = socket(AF_INET, SOCK_STREAM,0)) <0) + pexit("socket() failed"); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(IP_ADDRESS); + serv_addr.sin_port = htons(PORT); + + /* Connect tot he socket offered by the web server */ + if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) <0) + pexit("connect() failed"); + + /* Now the sockfd can be used to communicate to the server the GET request */ + printf("Send bytes=%d %s\n",strlen(command), command); + write(sockfd, command, strlen(command)); + + /* This displays the raw HTML file (if index.html) as received by the browser */ + while( (i=read(sockfd,buffer,BUFSIZE)) > 0) + write(1,buffer,i); +} diff --git a/src/minimal_overlay/bundles/nweb/favicon.ico b/src/minimal_overlay/bundles/nweb/favicon.ico new file mode 100644 index 000000000..c7a2123c1 Binary files /dev/null and b/src/minimal_overlay/bundles/nweb/favicon.ico differ diff --git a/src/minimal_overlay/bundles/nweb/index.html b/src/minimal_overlay/bundles/nweb/index.html new file mode 100644 index 000000000..d99085b24 --- /dev/null +++ b/src/minimal_overlay/bundles/nweb/index.html @@ -0,0 +1,13 @@ + + +nweb + + +

nweb test page

+
+

It works!

+

All rights go to the original author of nweb Nigel Griffiths nag@uk.ibm.com

+

Feedback is welcome to Nigel Griffiths nag@uk.ibm.com

+

+ + diff --git a/src/minimal_overlay/bundles/nweb/nweb.8 b/src/minimal_overlay/bundles/nweb/nweb.8 new file mode 100644 index 000000000..047e0763c --- /dev/null +++ b/src/minimal_overlay/bundles/nweb/nweb.8 @@ -0,0 +1,25 @@ +.TH NWEB 8 "June 19, 2017" +.SH NAME +nweb \- small and very safe mini web server +.SH SYNPOSIS +.B nweb +[\fIport\fR] +[\fItopdir\fR] +.SH DESCRIPTION +nweb only servers out file/web pages with extensions named below and only from the named directory or its sub-directories. + +There is no fancy features = safe and secure. + +Only Supports: gif jpg jpeg png ico zip gz tar htm html + +Not Supported: URLs including "..", Java, Javascript, CGI + +Not Supported: directories / /etc /bin /lib /tmp /usr /dev /sbin + +No warranty given or implied + +Nigel Griffiths nag@uk.ibm.com +.SH EXAMPLES + "nweb 8181 /srv/www &" + +Runs nweb on port 8181 serving files in /srv/www diff --git a/src/minimal_overlay/bundles/nweb/nweb23.c b/src/minimal_overlay/bundles/nweb/nweb23.c new file mode 100644 index 000000000..da5a6d3b1 --- /dev/null +++ b/src/minimal_overlay/bundles/nweb/nweb23.c @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define VERSION 23 +#define BUFSIZE 8096 +#define ERROR 42 +#define LOG 44 +#define FORBIDDEN 403 +#define NOTFOUND 404 + +#ifndef SIGCLD +# define SIGCLD SIGCHLD +#endif + +struct { + char *ext; + char *filetype; +} extensions [] = { + {"gif", "image/gif" }, + {"jpg", "image/jpg" }, + {"jpeg","image/jpeg"}, + {"png", "image/png" }, + {"ico", "image/ico" }, + {"zip", "image/zip" }, + {"gz", "image/gz" }, + {"tar", "image/tar" }, + {"htm", "text/html" }, + {"html","text/html" }, + {0,0} }; + +void logger(int type, char *s1, char *s2, int socket_fd) +{ + int fd ; + char logbuffer[BUFSIZE*2]; + + switch (type) { + case ERROR: (void)sprintf(logbuffer,"ERROR: %s:%s Errno=%d exiting pid=%d",s1, s2, errno,getpid()); + break; + case FORBIDDEN: + (void)write(socket_fd, "HTTP/1.1 403 Forbidden\nContent-Length: 185\nConnection: close\nContent-Type: text/html\n\n\n403 Forbidden\n\n

Forbidden

\nThe requested URL, file type or operation is not allowed on this simple static file webserver.\n\n",271); + (void)sprintf(logbuffer,"FORBIDDEN: %s:%s",s1, s2); + break; + case NOTFOUND: + (void)write(socket_fd, "HTTP/1.1 404 Not Found\nContent-Length: 136\nConnection: close\nContent-Type: text/html\n\n\n404 Not Found\n\n

Not Found

\nThe requested URL was not found on this server.\n\n",224); + (void)sprintf(logbuffer,"NOT FOUND: %s:%s",s1, s2); + break; + case LOG: (void)sprintf(logbuffer," INFO: %s:%s:%d",s1, s2,socket_fd); break; + } + /* No checks here, nothing can be done with a failure anyway */ + if((fd = open("nweb.log", O_CREAT| O_WRONLY | O_APPEND,0644)) >= 0) { + (void)write(fd,logbuffer,strlen(logbuffer)); + (void)write(fd,"\n",1); + (void)close(fd); + } + if(type == ERROR || type == NOTFOUND || type == FORBIDDEN) exit(3); +} + +/* this is a child web server process, so we can exit on errors */ +void web(int fd, int hit) +{ + int j, file_fd, buflen; + long i, ret, len; + char * fstr; + static char buffer[BUFSIZE+1]; /* static so zero filled */ + + ret =read(fd,buffer,BUFSIZE); /* read Web request in one go */ + if(ret == 0 || ret == -1) { /* read failure stop now */ + logger(FORBIDDEN,"failed to read browser request","",fd); + } + if(ret > 0 && ret < BUFSIZE) /* return code is valid chars */ + buffer[ret]=0; /* terminate the buffer */ + else buffer[0]=0; + for(i=0;i 0 ) { + (void)write(fd,buffer,ret); + } + sleep(1); /* allow socket to drain before signalling the socket is closed */ + close(fd); + exit(1); +} + +int main(int argc, char **argv) +{ + int i, port, pid, listenfd, socketfd, hit; + socklen_t length; + static struct sockaddr_in cli_addr; /* static = initialised to zeros */ + static struct sockaddr_in serv_addr; /* static = initialised to zeros */ + + if( argc < 3 || argc > 3 || !strcmp(argv[1], "-?") ) { + (void)printf("hint: nweb Port-Number Top-Directory\t\tversion %d\n\n" + "\tnweb is a small and very safe mini web server\n" + "\tnweb only servers out file/web pages with extensions named below\n" + "\t and only from the named directory or its sub-directories.\n" + "\tThere is no fancy features = safe and secure.\n\n" + "\tExample: nweb 8181 /home/nwebdir &\n\n" + "\tOnly Supports:", VERSION); + for(i=0;extensions[i].ext != 0;i++) + (void)printf(" %s",extensions[i].ext); + + (void)printf("\n\tNot Supported: URLs including \"..\", Java, Javascript, CGI\n" + "\tNot Supported: directories / /etc /bin /lib /tmp /usr /dev /sbin \n" + "\tNo warranty given or implied\n\tNigel Griffiths nag@uk.ibm.com\n" ); + exit(0); + } + if( !strncmp(argv[2],"/" ,2 ) || !strncmp(argv[2],"/etc", 5 ) || + !strncmp(argv[2],"/bin",5 ) || !strncmp(argv[2],"/lib", 5 ) || + !strncmp(argv[2],"/tmp",5 ) || !strncmp(argv[2],"/usr", 5 ) || + !strncmp(argv[2],"/dev",5 ) || !strncmp(argv[2],"/sbin",6) ){ + (void)printf("ERROR: Bad top directory %s, see nweb -?\n",argv[2]); + exit(3); + } + if(chdir(argv[2]) == -1){ + (void)printf("ERROR: Can't Change to directory %s\n",argv[2]); + exit(4); + } + /* Become deamon + unstopable and no zombies children (= no wait()) */ + if(fork() != 0) + return 0; /* parent returns OK to shell */ + (void)signal(SIGCLD, SIG_IGN); /* ignore child death */ + (void)signal(SIGHUP, SIG_IGN); /* ignore terminal hangups */ + for(i=0;i<32;i++) + (void)close(i); /* close open files */ + (void)setpgrp(); /* break away from process group */ + logger(LOG,"nweb starting",argv[1],getpid()); + /* setup the network socket */ + if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0) + logger(ERROR, "system call","socket",0); + port = atoi(argv[1]); + if(port < 0 || port >60000) + logger(ERROR,"Invalid port number (try 1->60000)",argv[1],0); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(port); + if(bind(listenfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0) + logger(ERROR,"system call","bind",0); + if( listen(listenfd,64) <0) + logger(ERROR,"system call","listen",0); + for(hit=1; ;hit++) { + length = sizeof(cli_addr); + if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0) + logger(ERROR,"system call","accept",0); + if((pid = fork()) < 0) { + logger(ERROR,"system call","fork",0); + } + else { + if(pid == 0) { /* child */ + (void)close(listenfd); + web(socketfd,hit); /* never returns */ + } else { /* parent */ + (void)close(socketfd); + } + } + } +}