aboutsummaryrefslogtreecommitdiff
path: root/www/pserv/files/patch-main.c
diff options
context:
space:
mode:
authorNorikatsu Shigemura <nork@FreeBSD.org>2003-10-17 08:11:55 +0000
committerNorikatsu Shigemura <nork@FreeBSD.org>2003-10-17 08:11:55 +0000
commit148e621cf93c5996d66f69a43ed8e95e985439ff (patch)
tree3c1c6f9533ea58f6b3ec476deef054fb9d5f0d04 /www/pserv/files/patch-main.c
parentab6dc456b9e0b7b9d7ebb098ad4061431a8b3dd1 (diff)
Notes
Diffstat (limited to 'www/pserv/files/patch-main.c')
-rw-r--r--www/pserv/files/patch-main.c386
1 files changed, 386 insertions, 0 deletions
diff --git a/www/pserv/files/patch-main.c b/www/pserv/files/patch-main.c
new file mode 100644
index 000000000000..e9ae61cbe1b6
--- /dev/null
+++ b/www/pserv/files/patch-main.c
@@ -0,0 +1,386 @@
+--- main.c.orig Mon Sep 22 10:39:24 2003
++++ main.c Thu Oct 16 14:00:02 2003
+@@ -23,6 +23,7 @@
+ char defaultFileName[MAX_PATH_LEN+1];
+ char logFileName[MAX_PATH_LEN+1];
+ char mimeTypesFileName[MAX_PATH_LEN+1];
++char phpFileName[MAX_PATH_LEN+1];
+ char cgiRoot[MAX_PATH_LEN+1]; /* root for CGI scripts exec */
+ struct timeval sockTimeVal;
+ mimeData *mimeArray; /* here we will hold all MIME data, inited once, never to be changed */
+@@ -206,10 +207,10 @@
+ int reqSize;
+ int readLines;
+ int tokenEnd;
+-
+- /* we copy the header lines to an array for easier parsing */
++
++ /* we copy the header lines to an array for easier parsing */
+ /* but first we make sure that our string has a newline and an end */
+- req[BUFFER_SIZE] = '\0';
++ req[BUFFER_SIZE] = '\0';
+ reqSize = strlen(req);
+ req[reqSize] = '\n';
+ reqSize++;
+@@ -230,7 +231,7 @@
+ for (k = 0; k < readLines; k++)
+ printf("%d - |%s|\n", k, reqArray[k]);
+ #endif
+-
++
+ /* first line: method, path and protocol version */
+ /* we copy to a temporary buffer to be more secure against overflows */
+ i = j = 0;
+@@ -246,7 +247,7 @@
+ else
+ tokenEnd = NO;
+ i++;
+-
++
+ /* we look for the document address */
+ j = 0;
+ reqStruct->documentAddress[0] = '\0';
+@@ -259,14 +260,14 @@
+ else
+ token[j] = '\0'; /* to make sure we have a string */
+ /* now we need to convert some escapings from the path like %20 */
+- convertPercents(token, j);
++ convertPercents(token, j);
+ strcpy(reqStruct->documentAddress, token); /* copy back */
+ if (reqArray[0][i] == '\0')
+ tokenEnd = YES;
+ else
+ tokenEnd = NO;
+ i++;
+-
++
+ /* we need now to separate path from query string ("?" separated) */
+ if (reqArray[0][i-1] == '?')
+ {
+@@ -282,7 +283,7 @@
+ i++;
+ }
+ }
+-
++
+ /* we analyze the HTTP protocol version */
+ /* default is 0.9 since that version didn't report itself */
+ strcpy(reqStruct->protocolVersion, "HTTP/0.9");
+@@ -306,10 +307,13 @@
+ else if (!strncmp(reqArray[1], "Connection: Keep-Alive", strlen("Connection: keep-alive")))
+ reqStruct->keepAlive = YES;
+
+- /* user-agent, content-length and else */
++ /* user-agent, content-length, content-type, cookie and else */
+ i = 1;
+ j = NO;
+ reqStruct->userAgent[0] = '\0';
++ reqStruct->contentLength = -1;
++ reqStruct->contentType[0] = '\0';
++ reqStruct->cookie[0] = '\0';
+ while (i < readLines)
+ {
+ if (!strncmp(reqArray[i], "User-Agent:", strlen("User-Agent:")))
+@@ -317,14 +321,28 @@
+ strncpy(reqStruct->userAgent, &reqArray[i][strlen("User-Agent: ")], USER_AGENT_LEN - 1);
+ reqStruct->userAgent[USER_AGENT_LEN] = '\0';
+ }
+- else if (!strncmp(reqArray[i], "Content-Length:", strlen("Content-length:")) || !strncmp(reqArray[i], "Content-length:", strlen("Content-length:")))
+- {
+- strcpy(token, &reqArray[i][strlen("Content-length: ")]);
+- sscanf(token, "%ld", &(reqStruct->contentLength));
++ else if (!strncmp(reqArray[i], "Content-Length:", strlen("Content-length:")) || !strncmp(reqArray[i], "Content-length:", strlen("Content-length:")))
++ {
++ strcpy(token, &reqArray[i][strlen("Content-length: ")]);
++ sscanf(token, "%ld", &(reqStruct->contentLength));
+ #ifdef PRINTF_DEBUG
+- printf("content length %ld\n", reqStruct->contentLength);
++ printf("content length %ld\n", reqStruct->contentLength);
+ #endif
+- }
++ }
++ else if (!strncmp(reqArray[i], "Content-Type:", strlen("Content-type:")) || !strncmp(reqArray[i], "Content-type:", strlen("Content-type:")))
++ {
++ strncpy(reqStruct->contentType, &reqArray[i][strlen("Content-type: ")], CONTENT_TYPE_LEN - 1);
++#ifdef PRINTF_DEBUG
++ printf("content type %s\n", reqStruct->contentType);
++#endif
++ }
++ else if (!strncmp(reqArray[i], "Cookie:", strlen("Cookie:")))
++ {
++ strncpy(reqStruct->cookie, &reqArray[i][strlen("Cookie: ")], MAX_COOKIE_LEN - 1);
++#ifdef PRINTF_DEBUG
++ printf("cookie %s\n", reqStruct->cookie);
++#endif
++ }
+ i++;
+ }
+ /* if we didn't find a User-Aget we fill in a (N)ot(R)ecognized */
+@@ -414,18 +432,39 @@
+ /* we append the default file name */
+ strcat(completeFilePath, defaultFileName);
+ analyzeExtension(mimeType, completeFilePath);
+- dumpFile(sock, completeFilePath, mimeType, req);
++#ifdef PHP
++ if (strncmp(mimeType, "application/x-httpd-php", 23))
++#endif
++ dumpFile(sock, completeFilePath, mimeType, req);
++#ifdef PHP
++ else
++ phpHandler(port, sock, phpFileName, completeFilePath, req, NULL);
++#endif
+ }
+ #else
+ /* we append the default file name */
+ strcat(completeFilePath, defaultFileName);
+ analyzeExtension(mimeType, completeFilePath);
+- dumpFile(sock, completeFilePath, mimeType, req);
++#ifdef PHP
++ if (strncmp(mimeType, "application/x-httpd-php", 23))
++#endif
++ dumpFile(sock, completeFilePath, mimeType, req);
++#ifdef PHP
++ else
++ phpHandler(port, sock, phpFileName, completeFilePath, req, NULL);
++#endif
+ #endif
+ } else
+ { /* it is a plain file */
+ analyzeExtension(mimeType, completeFilePath);
+- dumpFile(sock, completeFilePath, mimeType, req);
++#ifdef PHP
++ if (strncmp(mimeType, "application/x-httpd-php", 23))
++#endif
++ dumpFile(sock, completeFilePath, mimeType, req);
++#ifdef PHP
++ else
++ phpHandler(port, sock, phpFileName, completeFilePath, req, NULL);
++#endif
+ }
+ }
+ } else if (!strcmp(req.method, "HEAD"))
+@@ -494,7 +533,14 @@
+ strcat(completeFilePath, defaultFileName);
+ }
+ analyzeExtension(mimeType, completeFilePath);
+- dumpHeader(sock, completeFilePath, mimeType, req);
++#ifdef PHP
++ if (strncmp(mimeType, "application/x-httpd-php", 23))
++#endif
++ dumpFile(sock, completeFilePath, mimeType, req);
++#ifdef PHP
++ else
++ phpHandler(port, sock, phpFileName, completeFilePath, req, NULL);
++#endif
+ }
+ } else if (!strcmp(req.method, "POST"))
+ {
+@@ -507,13 +553,6 @@
+ int readFinished;
+
+ printf("Handling of POST method\n");
+- /* first we check if the path contains the directory selected for cgi's and in case handle it */
+- if (strncmp(req.documentAddress, CGI_MATCH_STRING, strlen(CGI_MATCH_STRING)))
+- {
+- /* non cgi POST is not supported */
+- sayError(sock, UNHANDLED_METHOD, "", req);
+- return -1;
+- }
+ #ifdef PRINTF_DEBUG
+ printf ("begin of post handling\n");
+
+@@ -523,9 +562,15 @@
+ totalRead = 0;
+ stuckCounter = 0;
+ timeOutCounter = 0;
+- while (!readFinished)
+- {
+- howMany = recv(newSocket, tempBuff, BUFFER_SIZE, 0);
++
++ /* SECURITY: Avoid malicious Content-Length -- check \r\n\r\n\0 also */
++ if (req.contentLength < 0 || req.contentLength >= BUFFER_SIZE-5) {
++ sayError(sock, 500, "", req);
++ return -1;
++ }
++
++ /* SECURITY: Remove loop to prevent buffer overflow */
++ howMany = recv(newSocket, tempBuff, req.contentLength+5, 0);
+ tempBuff[howMany] = '\0'; /* seems that some Unices need this */
+ #ifdef PRINTF_DEBUG
+ printf ("read: %d\n%s\n", howMany, tempBuff);
+@@ -579,16 +624,15 @@
+ if (howMany == req.contentLength)
+ readFinished = YES;
+ }
+- }
+ #ifdef PRINTF_DEBUG
+- printf("total read %d\n", totalRead);
++ printf("total read %d\n", totalRead);
+ #endif
+- if (totalRead == 0)
+- {
+- printf("Request read error\n");
+- } else
+- {
+- if (buff[totalRead - 1] != '\n') /* we need a trailing \n or the script will wait forever */
++ if (totalRead == 0)
++ {
++ printf("Request read error\n");
++ } else
++ {
++ if (buff[totalRead - 1] != '\n') /* we need a trailing \n or the script will wait forever */
+ {
+ buff[totalRead++] = '\n';
+ buff[totalRead] = '\0';
+@@ -596,7 +640,77 @@
+ #ifdef PRINTF_DEBUG
+ printf("buff: |%s|\n", buff);
+ #endif
+- cgiHandler(port, sock, req, buff);
++ if (!strncmp(req.documentAddress, CGI_MATCH_STRING, strlen(CGI_MATCH_STRING)))
++ {
++ cgiHandler(port, sock, req, buff);
++ } else
++ {
++#ifdef PHP
++ strcpy(completeFilePath, homePath);
++ strcat(completeFilePath, req.documentAddress);
++ /* now we check if the given path tries to get out of the root */
++ {
++ int i,j;
++ int sL;
++ char dirName[MAX_PATH_LEN+1];
++ int depthCount = 0;
++
++ sL = strlen(req.documentAddress);
++ dirName[0] = '\0';
++ if (sL > 3) {
++ dirName[0] = req.documentAddress[1];
++ dirName[1] = req.documentAddress[2];
++ dirName[2] = req.documentAddress[3];
++ dirName[3] ='\0';
++ if (!strcmp(dirName, "../"))
++ {
++ sayError(sock, FORBIDDEN, req.documentAddress, req);
++ return -1;
++ }
++ }
++ j = 0;
++ for (i = 1; i < sL; i++) {
++ if (req.documentAddress[i] == '/')
++ {
++ dirName[j] = '\0';
++ if (strcmp(dirName, ".."))
++ depthCount ++;
++ else
++ depthCount--;
++ j = 0;
++ } else
++ dirName[j++] = req.documentAddress[i];
++ }
++ if (depthCount < 0)
++ {
++ sayError(sock, FORBIDDEN, req.documentAddress, req);
++ return -1;
++ }
++ }
++ /* now we check if the given file is a directory or a plain file */
++ stat(completeFilePath, &fileStats);
++ if ((fileStats.st_mode & S_IFDIR) == S_IFDIR)
++ {
++ /* if does not end with a slash, we get an error */
++ if(completeFilePath[strlen(completeFilePath)-1] != '/')
++ {
++ sayError(sock, NOT_FOUND, req.documentAddress, req);
++ return -1;
++ }
++ /* we append the default file name */
++ strcat(completeFilePath, defaultFileName);
++ }
++ analyzeExtension(mimeType, completeFilePath);
++ if (strncmp(mimeType, "application/x-httpd-php", 23))
++ {
++#endif
++ /* non cgi POST is not supported */
++ sayError(sock, UNHANDLED_METHOD, "", req);
++ return -1;
++#ifdef PHP
++ } else phpHandler(port, sock, phpFileName, completeFilePath, req, buff);
++#endif
++ }
+ }
+ } else
+ {
+@@ -625,7 +739,7 @@
+ f = fopen(configFile, "r");
+ if (f == NULL)
+ {
+- printf("Error opening config file. Setting defaults.\n");
++ printf("Config file not found. Setting defaults.\n");
+ *serverPort = DEFAULT_PORT;
+ *maxChildren = DEFAULT_MAX_CHILDREN;
+ strcpy(homePath, DEFAULT_DOCS_LOCATION);
+@@ -634,7 +748,9 @@
+ sockTimeVal.tv_usec = DEFAULT_USEC_TO;
+ strcpy(logFileName, DEFAULT_LOG_FILE);
+ strcpy(mimeTypesFileName, DEFAULT_MIME_FILE);
++ strcpy(phpFileName, DEFAULT_PHP_FILE);
+ strcpy(cgiRoot, DEFAULT_CGI_ROOT);
++ initMimeTypes();
+ return -1;
+ }
+ if (!feof(f)) fscanf(f, "%s %s", str1, str2);
+@@ -735,11 +851,25 @@
+ if (mimeTypesFileName == NULL)
+ {
+ strcpy(mimeTypesFileName, DEFAULT_MIME_FILE);
+- printf("Error reading mimeTypesFileName from file, setting default, %s\n", mimeTypesFileName);
++ printf("Error reading mimeTypesFile from file, setting default, %s\n", mimeTypesFileName);
+ }
+ } else {
+ strcpy(mimeTypesFileName, DEFAULT_MIME_FILE);
+- printf("Error reading mimeTypesFileName from file, setting default, %s\n", mimeTypesFileName);
++ printf("Error reading mimeTypesFile from file, setting default, %s\n", mimeTypesFileName);
++ }
++ if (!feof(f)) fscanf(f, "%s %s", str1, str2);
++ if (str1 != NULL && str2 != NULL && !strcmp(str1, "phpFile"))
++ {
++ sscanf(str2, "%s", phpFileName);
++ if (logFileName == NULL)
++ {
++ strcpy(phpFileName, DEFAULT_LOG_FILE);
++ printf("Error reading phpFile from file, setting default, %s\n", phpFileName);
++ }
++ } else
++ {
++ strcpy(phpFileName, DEFAULT_PHP_FILE);
++ printf("Error reading phpFile from file, setting default, %s\n", phpFileName);
+ }
+ if (!feof(f)) fscanf(f, "%s %s", str1, str2);
+ if (str1 != NULL && str2 != NULL && !strcmp(str1, "cgiRoot"))
+@@ -775,6 +905,7 @@
+ int readFinished;
+ struct request gottenReq;
+ int isKeepAlive;
++ int bool;
+ struct sockaddr_in listenName; /* data struct for the listen port */
+ struct sockaddr_in acceptedSockStruct; /* sockaddr for the internetworking */
+ int acceptedSocketLen; /* size of the structure */
+@@ -808,9 +939,16 @@
+ printf("socket creation error occoured\n");
+ return -1;
+ }
++ bool = 1;
++ error = setsockopt (theSocket, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool));
++ if (error == -1)
++ { if (errno == EADDRINUSE)
++ printf("set socket option error occoured\n");
++ return -1;
++ }
+ error = bind (theSocket, (struct sockaddr*) &listenName, sizeof(listenName));
+ if (error == -1)
+- {
++ { if (errno == EADDRINUSE)
+ printf("socket binding error occoured\n");
+ return -2;
+ }