diff --git a/Makefile b/Makefile index e979eb1c7..4771e6f1c 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,8 @@ release: $(MAKE) -C config/scripts/config clean -$(MAKE) clean -@rm config/*.msi config/*.back.aip config/config.h config/.config* - @rm -fr $(STAGE) + -@rm www/index.20* + -@rm -fr $(STAGE) @echo "#define AXTLS_VERSION \"$(VERSION)\"" > ssl/version.h cd ../; tar cvfz $(RELEASE).tar.gz --wildcards-match-slash --exclude .svn axTLS; cd -; diff --git a/httpd/axhttp.h b/httpd/axhttp.h index 8b05d3e03..affe5e051 100644 --- a/httpd/axhttp.h +++ b/httpd/axhttp.h @@ -24,7 +24,7 @@ #ifdef CONFIG_HTTP_HAS_IPV6 #define HAVE_IPV6 #endif - +#define MAXPOSTDATASIZE 30000 #define MAXREQUESTLENGTH 256 #define BLOCKSIZE 4096 @@ -88,6 +88,9 @@ struct connstruct #if defined(CONFIG_HTTP_HAS_AUTHORIZATION) char authorization[MAXREQUESTLENGTH]; #endif + int post_read; + int post_state; + char *post_data; }; struct serverstruct @@ -125,7 +128,7 @@ void procreadhead(struct connstruct *cn); void procsendhead(struct connstruct *cn); void procreadfile(struct connstruct *cn); void procsendfile(struct connstruct *cn); - +void read_post_data(struct connstruct *cn); /* misc.c prototypes */ char *my_strncpy(char *dest, const char *src, size_t n); diff --git a/httpd/axhttpd.c b/httpd/axhttpd.c index c67c08eca..c594e8f85 100644 --- a/httpd/axhttpd.c +++ b/httpd/axhttpd.c @@ -24,6 +24,20 @@ #include #include "axhttp.h" +#if AXDEBUG +#define AXDEBUGSTART \ + { \ + FILE *dout; \ + dout = fopen("/var/log/axdebug", "a"); \ + +#define AXDEBUGEND \ + fclose(dout); \ + } +#else /* AXDEBUG */ +#define AXDEBUGSTART +#define AXDEBUGEND +#endif /* AXDEBUG */ + struct serverstruct *servers; struct connstruct *usedconns; struct connstruct *freeconns; @@ -161,6 +175,7 @@ int main(int argc, char *argv[]) #if defined(CONFIG_HTTP_HAS_CGI) addcgiext(CONFIG_HTTP_CGI_EXTENSIONS); + printf("addcgiext %s\n",CONFIG_HTTP_CGI_EXTENSIONS); #endif #if defined(CONFIG_HTTP_VERBOSE) printf("%s: listening on ports %d (http) and %d (https)\n", @@ -176,6 +191,7 @@ int main(int argc, char *argv[]) setuid(32767); #endif #ifdef CONFIG_HTTP_IS_DAEMON + fprintf(stderr, "ERR: fork is not working on uclinux\n"); if (fork() > 0) /* parent will die */ exit(0); @@ -283,6 +299,9 @@ int main(int argc, char *argv[]) FD_ISSET(to->networkdesc, &rfds)) { active--; + if (to->post_state) + read_post_data(to); + else procreadhead(to); } diff --git a/httpd/proc.c b/httpd/proc.c index 32127e862..2333bc657 100644 --- a/httpd/proc.c +++ b/httpd/proc.c @@ -54,6 +54,20 @@ static void decode_path_info(struct connstruct *cn, char *path_info); static int auth_check(struct connstruct *cn); #endif +#if AXDEBUG +#define AXDEBUGSTART \ + { \ + FILE *axdout; \ + axdout = fopen("/var/log/axdebug", "a"); \ + +#define AXDEBUGEND \ + fclose(axdout); \ + } +#else /* AXDEBUG */ +#define AXDEBUGSTART +#define AXDEBUGEND +#endif /* AXDEBUG */ + /* Returns 1 if elems should continue being read, 0 otherwise */ static int procheadelem(struct connstruct *cn, char *buf) { @@ -267,11 +281,113 @@ static void urlencode(const uint8_t *s, char *t) #endif +int init_read_post_data(char *buf, char *data, struct connstruct *cn, int old_rv) +{ + char *next; + int rv; + char *post_data; + + rv=old_rv; + next=data; + + /* Too much Post data to send. MAXPOSTDATASIZE should be + configured (now it can be chaged in the header file) */ + if (cn->content_length > MAXPOSTDATASIZE) + { + send_error(cn, 418); + return 0; + } + + /* remove CRLF */ + while ((*next == '\r' || *next == '\n') && (next < &buf[rv])) + next++; + + if (cn->post_data == NULL) + { + cn->post_data = (char *) calloc(1, (cn->content_length + 1)); + /* Allocate buffer for the POST data that will be used by proccgi + to send POST data to the CGI script */ + + if (cn->post_data == NULL) + { + printf("axhttpd: could not allocate memory for POST data\n"); + TTY_FLUSH(); + send_error(cn, 599); + return 0; + } + } + + cn->post_state = 0; + cn->post_read = 0; + post_data = cn->post_data; + + while (next < &buf[rv]) + { + /*copy POST data to buffer*/ + *post_data = *next; + post_data++; + next++; + cn->post_read++; + if (cn->post_read == cn->content_length) + { + /* No more POST data to be copied */ + *post_data = '\0'; + return 1; + } + } + + /* More POST data has to be read. read_post_data will continue with that */ + cn->post_state = 1; + return 0; +} + +void read_post_data(struct connstruct *cn) +{ + char buf[MAXREQUESTLENGTH*4], *next; + char *post_data; + int rv; + + bzero(buf,MAXREQUESTLENGTH*4); + rv = special_read(cn, buf, sizeof(buf)-1); + if (rv <= 0) + { + if (rv < 0) /* really dead? */ + removeconnection(cn); + return; + } + + buf[rv] = '\0'; + next = buf; + + post_data = &cn->post_data[cn->post_read]; + + while (next < &buf[rv]) + { + *post_data = *next; + post_data++; + next++; + cn->post_read++; + if (cn->post_read == cn->content_length) + { + /* No more POST data to be copied */ + *post_data='\0'; + cn->post_state = 0; + buildactualfile(cn); + cn->state = STATE_WANT_TO_SEND_HEAD; + return; + } + } + + /* More POST data to read */ +} + + void procreadhead(struct connstruct *cn) { char buf[MAXREQUESTLENGTH*4], *tp, *next; int rv; + bzero(buf,MAXREQUESTLENGTH*4); rv = special_read(cn, buf, sizeof(buf)-1); if (rv <= 0) { @@ -293,6 +409,12 @@ void procreadhead(struct connstruct *cn) /* If we have a blank line, advance to next stage */ if (*next == '\r' || *next == '\n') { + if ((cn->reqtype == TYPE_POST)&&(cn->content_length > 0)) + { + if (init_read_post_data(buf,next,cn,rv) == 0) + return; + } + buildactualfile(cn); cn->state = STATE_WANT_TO_SEND_HEAD; return; @@ -349,6 +471,7 @@ void procsendhead(struct connstruct *cn) file_exists = stat(cn->actualfile, &stbuf); #if defined(CONFIG_HTTP_HAS_CGI) + if (file_exists != -1 && cn->is_cgi) { if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile)) @@ -503,12 +626,13 @@ void procsendfile(struct connstruct *cn) static void proccgi(struct connstruct *cn) { - int tpipe[2]; + int tpipe[2], spipe[2]; char *myargs[2]; char cgienv[CGI_ARG_SIZE][MAXREQUESTLENGTH]; char * cgiptr[CGI_ARG_SIZE+4]; const char *type = "HEAD"; int cgi_index = 0, i; + pid_t pid; #ifdef WIN32 int tmp_stdout; #endif @@ -531,10 +655,41 @@ static void proccgi(struct connstruct *cn) /* win32 cgi is a bit too painful */ #ifndef WIN32 - pipe(tpipe); - - if (fork() > 0) /* parent */ + /* set up pipe that is used for sending POST query data to CGI script*/ + if (cn->reqtype == TYPE_POST) { + if (pipe(spipe) == -1) + { + printf("[CGI]: could not create pipe"); + TTY_FLUSH(); + return; + } + } + + if (pipe(tpipe) == -1) + { + printf("[CGI]: could not create pipe"); + TTY_FLUSH(); + return; + } +#ifdef EMBED + if ((pid = vfork()) > 0) /* parent */ +#else + if ((pid = fork()) > 0) /* parent */ +#endif + { + /* Send POST query data to CGI script */ + if ((cn->reqtype == TYPE_POST) && (cn->content_length > 0)) + { + write(spipe[1], cn->post_data, cn->content_length); + close(spipe[0]); + close(spipe[1]); + + /* free the memory that is allocated in read_post_data() */ + free(cn->post_data); + cn->post_data = NULL; + } + /* Close the write descriptor */ close(tpipe[1]); cn->filedesc = tpipe[0]; @@ -543,6 +698,9 @@ static void proccgi(struct connstruct *cn) return; } + if (pid < 0) /* fork failed */ + exit(1); + /* The problem child... */ /* Our stdout/stderr goes to the socket */ @@ -551,13 +709,10 @@ static void proccgi(struct connstruct *cn) /* If it was a POST request, send the socket data to our stdin */ if (cn->reqtype == TYPE_POST) - dup2(cn->networkdesc, 0); + dup2(spipe[0], 0); else /* Otherwise we can shutdown the read side of the sock */ shutdown(cn->networkdesc, 0); - close(tpipe[0]); - close(tpipe[1]); - myargs[0] = cn->actualfile; myargs[1] = NULL; @@ -617,7 +772,7 @@ static void proccgi(struct connstruct *cn) if (cgi_index >= CGI_ARG_SIZE) { printf("Content-type: text/plain\n\nToo many CGI args\n"); - return; + exit(1); } /* copy across the pointer indexes */ @@ -631,6 +786,7 @@ static void proccgi(struct connstruct *cn) execve(myargs[0], myargs, cgiptr); printf("Content-type: text/plain\n\nshouldn't get here\n"); + exit(1); #endif } @@ -815,10 +971,14 @@ static void buildactualfile(struct connstruct *cn) if (cn->is_lua) #ifdef CONFIG_PLATFORM_CYGWIN sprintf(cn->actualfile, "%s/bin/cgi.exe", CONFIG_HTTP_LUA_PREFIX); +#else +#ifdef EMBED + sprintf(cn->actualfile, "%s", CONFIG_HTTP_LUA_PREFIX); #else sprintf(cn->actualfile, "%s/bin/cgi", CONFIG_HTTP_LUA_PREFIX); #endif #endif +#endif } static int sanitizefile(const char *buf) @@ -1007,6 +1167,11 @@ static void send_error(struct connstruct *cn, int err) text = title; break; + case 418: + title = "POST data size is to large"; + text = title; + break; + default: title = "Unknown"; text = "Unknown";