int serveconnection(int sockfd) { FILE *in; char tempdata[8192], *ptr, *ptr2, *host_ptr1, *host_ptr2; char tempstring[8192], mimetype[50]; char filename[255]; unsigned int loop=0, flag=0; int numbytes=0; struct sockaddr_in sa; int addrlen = sizeof(struct sockaddr_in); t_vhost *thehost; thehost = &defaulthost; // tempdata is the full header, tempstring is just the command while(!strstr(tempdata, "\r\n\r\n") && !strstr(tempdata, "\n\n")) { if((numbytes=recv(sockfd, tempdata+numbytes, 4096-numbytes, 0))==-1) return -1; } for(loop=0; loop<4096 && tempdata[loop]!='\n' && tempdata[loop]!='\r'; loop++) tempstring[loop] = tempdata[loop]; tempstring[loop] = '\0'; ptr = strtok(tempstring, " "); if(ptr == 0) return -1; if(strcmp(ptr, "GET")) { strcpy(filename, SERVERROOT); strcat(filename, "/cmderror.html"); goto sendpage; } ptr = strtok(NULL, " "); if(ptr == NULL) { strcpy(filename, SERVERROOT); strcat(filename, "/cmderror.html"); goto sendpage; } host_ptr1 = strstr(tempdata, "Host:"); if(host_ptr1) { host_ptr2 = strtok(host_ptr1+6, " \r\n\t"); for(loop=0; loop<no_vhosts; loop++) if(!gstricmp(vhosts[loop].host, host_ptr2)) thehost = &vhosts[loop]; } else thehost = &defaulthost; if(strstr(ptr, "/..")) { strcpy(filename, SERVERROOT); strcat(filename, "/404.html"); goto sendpage; } getpeername(sockfd, (struct sockaddr *)&sa, &addrlen); Log("Connection from %s, request = \"GET %s\"", inet_ntoa(sa.sin_addr), ptr); if(!strncmp(ptr, thehost->CGIBINDIR, strlen(thehost->CGIBINDIR))) {/* Trying to execute a cgi-bin file ? lets check */ ptr2 = strstr(ptr, "?"); if(ptr2!=NULL) { ptr2[0] = '\0'; flag = 1; } strcpy(filename, thehost->CGIBINROOT); ptr += strlen(thehost->CGIBINDIR); strcat(filename, ptr); // Filename = program to execute // ptr = filename in cgi-bin dir // ptr2+1 = parameters if(does_file_exist(filename)==TRUE && isDirectory(filename)==FALSE) { if(send(sockfd, "HTTP/1.1 200 OK\n", 16, 0)==-1) { fclose(in); return -1; } if(send(sockfd, "Server: "SERVERNAME"\n", strlen("Server: "SERVERNAME"\n"), 0)==-1) { fclose(in); return -1; } // Is a CGI-program that needs executing if(0 != dup2(sockfd, 0) || 1 != dup2(sockfd, 1)) return -1; setbuf(stdin, 0); setbuf(stdout, 0); if(flag==1) setenv("QUERY_STRING", ptr2+1, 1); chdir(thehost->CGIBINROOT); execl(filename, ""); } strcpy(filename, SERVERROOT); strcat(filename, "/cgierror.html"); goto sendpage; } strcpy(filename, thehost->DOCUMENTROOT); strcat(filename, ptr); if(does_file_exist(filename)==FALSE) { if(filename[strlen(filename)-1] == '/') strcat(filename, thehost->DEFAULTPAGE); else { strcat(filename, "/"); strcat(filename, thehost->DEFAULTPAGE); } if(does_file_exist(filename) == FALSE) { filename[strlen(filename)-strlen(thehost->DEFAULTPAGE)-1] = '\0'; // Get rid of the /index.. if(isDirectory(filename) == TRUE) { showdir(filename, sockfd, thehost); return 0; } // File does not exist, so we need to display the 404 error page.. strcpy(filename, SERVERROOT); strcat(filename, "/404.html"); } } sendpage: if((in = fopen(filename, "rb"))==NULL) return -1; fseek(in, 0, SEEK_END); if(send(sockfd, "HTTP/1.1 200 OK\n", 16, 0)==-1) { fclose(in); return -1; } if(send(sockfd, "Server: "SERVERNAME"\n", strlen("Server: "SERVERNAME"\n"), 0)==-1) { fclose(in); return -1; } sprintf(tempstring, "Content-Length: %d\n", ftell(in)); if(send(sockfd, tempstring, strlen(tempstring), 0)==-1) { fclose(in); return -1; } getmimetype(filename, mimetype); sprintf(tempstring, "Content-Type: %s\n\n", mimetype); if(send(sockfd, tempstring, strlen(tempstring), 0)==-1) { fclose(in); return -1; } fseek(in, 0, SEEK_SET); while(!feof(in)) { numbytes = fread(tempdata, 1, 1024, in); if(send(sockfd, tempdata, numbytes, 0)==-1) { fclose(in); return -1; } } fclose(in); close(sockfd); return 0; }
/* In this function we assume that the file has been checked for * maliciousness (".."s, etc) and has been decoded */ void procsendhead(struct connstruct *cn) { char buf[MAXREQUESTLENGTH]; struct stat stbuf; time_t t_time; struct tm *ptm; char date[32]; char last_modified[32]; char expires[32]; int file_exists; /* are we trying to access a file over the HTTP connection instead of a * HTTPS connection? Or is this directory disabled? */ if (htaccess_check(cn)) { send_error(cn, 403); return; } #ifdef CONFIG_HTTP_HAS_AUTHORIZATION if (auth_check(cn)) { /* see if there is a '.htpasswd' file */ #ifdef CONFIG_HTTP_VERBOSE printf("axhttpd: access to %s denied\n", cn->filereq); TTY_FLUSH(); #endif removeconnection(cn); return; } #endif file_exists = stat(cn->actualfile, &stbuf); #if defined(CONFIG_HTTP_HAS_CGI) if (file_exists != -1 && cn->is_cgi) { proccgi(cn); return; } #endif /* look for "index.html"? */ if (isdir(cn->actualfile)) { char tbuf[MAXREQUESTLENGTH]; snprintf(tbuf, MAXREQUESTLENGTH, "%s%s", cn->actualfile, index_file); if ((file_exists = stat(tbuf, &stbuf)) != -1) my_strncpy(cn->actualfile, tbuf, MAXREQUESTLENGTH); else { #if defined(CONFIG_HTTP_DIRECTORIES) /* If not, we do a directory listing of it */ procdirlisting(cn); #else send_error(cn, 404); #endif return; } } if (file_exists == -1) { send_error(cn, 404); return; } time(&t_time); ptm = gmtime(&t_time); strftime(date, sizeof(date), rfc1123_format, ptm); /* has the file been read before? */ if (cn->if_modified_since != -1) { ptm = gmtime(&stbuf.st_mtime); t_time = mktime(ptm); if (cn->if_modified_since >= t_time) { snprintf(buf, sizeof(buf), HTTP_VERSION" 304 Not Modified\nServer: " "%s\nDate: %s\n\n", server_version, date); special_write(cn, buf, strlen(buf)); cn->state = STATE_WANT_TO_READ_HEAD; return; } } if (cn->reqtype == TYPE_HEAD) { removeconnection(cn); return; } else { int flags = O_RDONLY; #if defined(CONFIG_PLATFORM_CYGWIN) flags |= O_BINARY; #endif cn->filedesc = open(cn->actualfile, flags); if (cn->filedesc < 0) { send_error(cn, 404); return; } ptm = gmtime(&stbuf.st_mtime); strftime(last_modified, sizeof(last_modified), rfc1123_format, ptm); t_time += CONFIG_HTTP_TIMEOUT; ptm = gmtime(&t_time); strftime(expires, sizeof(expires), rfc1123_format, ptm); snprintf(buf, sizeof(buf), HTTP_VERSION" 200 OK\nServer: %s\n" "Content-Type: %s\nContent-Length: %ld\n" "Date: %s\nLast-Modified: %s\nExpires: %s\n\n", server_version, getmimetype(cn->actualfile), (long) stbuf.st_size, date, last_modified, expires); special_write(cn, buf, strlen(buf)); #ifdef CONFIG_HTTP_VERBOSE printf("axhttpd: %s:/%s\n", cn->is_ssl ? "https" : "http", cn->filereq); TTY_FLUSH(); #endif cn->state = STATE_WANT_TO_READ_FILE; } }