Lines 1-5
Link Here
|
1 |
--- main.c.orig Mon Sep 22 10:39:24 2003 |
1 |
--- sources/main.c.orig Sat Dec 20 11:16:21 2003 |
2 |
+++ main.c Thu Oct 16 14:00:02 2003 |
2 |
+++ sources/main.c Thu Jan 8 12:27:13 2004 |
3 |
@@ -23,6 +23,7 @@ |
3 |
@@ -23,6 +23,7 @@ |
4 |
char defaultFileName[MAX_PATH_LEN+1]; |
4 |
char defaultFileName[MAX_PATH_LEN+1]; |
5 |
char logFileName[MAX_PATH_LEN+1]; |
5 |
char logFileName[MAX_PATH_LEN+1]; |
Lines 8-75
Link Here
|
8 |
char cgiRoot[MAX_PATH_LEN+1]; /* root for CGI scripts exec */ |
8 |
char cgiRoot[MAX_PATH_LEN+1]; /* root for CGI scripts exec */ |
9 |
struct timeval sockTimeVal; |
9 |
struct timeval sockTimeVal; |
10 |
mimeData *mimeArray; /* here we will hold all MIME data, inited once, never to be changed */ |
10 |
mimeData *mimeArray; /* here we will hold all MIME data, inited once, never to be changed */ |
11 |
@@ -206,10 +207,10 @@ |
11 |
@@ -316,10 +317,13 @@ |
12 |
int reqSize; |
12 |
reqStruct->keepAlive = YES; |
13 |
int readLines; |
|
|
14 |
int tokenEnd; |
15 |
- |
16 |
- /* we copy the header lines to an array for easier parsing */ |
17 |
+ |
18 |
+ /* we copy the header lines to an array for easier parsing */ |
19 |
/* but first we make sure that our string has a newline and an end */ |
20 |
- req[BUFFER_SIZE] = '\0'; |
21 |
+ req[BUFFER_SIZE] = '\0'; |
22 |
reqSize = strlen(req); |
23 |
req[reqSize] = '\n'; |
24 |
reqSize++; |
25 |
@@ -230,7 +231,7 @@ |
26 |
for (k = 0; k < readLines; k++) |
27 |
printf("%d - |%s|\n", k, reqArray[k]); |
28 |
#endif |
29 |
- |
30 |
+ |
31 |
/* first line: method, path and protocol version */ |
32 |
/* we copy to a temporary buffer to be more secure against overflows */ |
33 |
i = j = 0; |
34 |
@@ -246,7 +247,7 @@ |
35 |
else |
36 |
tokenEnd = NO; |
37 |
i++; |
38 |
- |
39 |
+ |
40 |
/* we look for the document address */ |
41 |
j = 0; |
42 |
reqStruct->documentAddress[0] = '\0'; |
43 |
@@ -259,14 +260,14 @@ |
44 |
else |
45 |
token[j] = '\0'; /* to make sure we have a string */ |
46 |
/* now we need to convert some escapings from the path like %20 */ |
47 |
- convertPercents(token, j); |
48 |
+ convertPercents(token, j); |
49 |
strcpy(reqStruct->documentAddress, token); /* copy back */ |
50 |
if (reqArray[0][i] == '\0') |
51 |
tokenEnd = YES; |
52 |
else |
53 |
tokenEnd = NO; |
54 |
i++; |
55 |
- |
56 |
+ |
57 |
/* we need now to separate path from query string ("?" separated) */ |
58 |
if (reqArray[0][i-1] == '?') |
59 |
{ |
60 |
@@ -282,7 +283,7 @@ |
61 |
i++; |
62 |
} |
63 |
} |
64 |
- |
65 |
+ |
66 |
/* we analyze the HTTP protocol version */ |
67 |
/* default is 0.9 since that version didn't report itself */ |
68 |
strcpy(reqStruct->protocolVersion, "HTTP/0.9"); |
69 |
@@ -306,10 +307,13 @@ |
70 |
else if (!strncmp(reqArray[1], "Connection: Keep-Alive", strlen("Connection: keep-alive"))) |
13 |
else if (!strncmp(reqArray[1], "Connection: Keep-Alive", strlen("Connection: keep-alive"))) |
71 |
reqStruct->keepAlive = YES; |
14 |
reqStruct->keepAlive = YES; |
72 |
|
|
|
73 |
- /* user-agent, content-length and else */ |
15 |
- /* user-agent, content-length and else */ |
74 |
+ /* user-agent, content-length, content-type, cookie and else */ |
16 |
+ /* user-agent, content-length, content-type, cookie and else */ |
75 |
i = 1; |
17 |
i = 1; |
Lines 81-87
Link Here
|
81 |
while (i < readLines) |
23 |
while (i < readLines) |
82 |
{ |
24 |
{ |
83 |
if (!strncmp(reqArray[i], "User-Agent:", strlen("User-Agent:"))) |
25 |
if (!strncmp(reqArray[i], "User-Agent:", strlen("User-Agent:"))) |
84 |
@@ -317,14 +321,28 @@ |
26 |
@@ -327,14 +331,28 @@ |
85 |
strncpy(reqStruct->userAgent, &reqArray[i][strlen("User-Agent: ")], USER_AGENT_LEN - 1); |
27 |
strncpy(reqStruct->userAgent, &reqArray[i][strlen("User-Agent: ")], USER_AGENT_LEN - 1); |
86 |
reqStruct->userAgent[USER_AGENT_LEN] = '\0'; |
28 |
reqStruct->userAgent[USER_AGENT_LEN] = '\0'; |
87 |
} |
29 |
} |
Lines 93-103
Link Here
|
93 |
+ { |
35 |
+ { |
94 |
+ strcpy(token, &reqArray[i][strlen("Content-length: ")]); |
36 |
+ strcpy(token, &reqArray[i][strlen("Content-length: ")]); |
95 |
+ sscanf(token, "%ld", &(reqStruct->contentLength)); |
37 |
+ sscanf(token, "%ld", &(reqStruct->contentLength)); |
96 |
#ifdef PRINTF_DEBUG |
38 |
+#ifdef PRINTF_DEBUG |
97 |
- printf("content length %ld\n", reqStruct->contentLength); |
|
|
98 |
+ printf("content length %ld\n", reqStruct->contentLength); |
39 |
+ printf("content length %ld\n", reqStruct->contentLength); |
99 |
#endif |
40 |
+#endif |
100 |
- } |
|
|
101 |
+ } |
41 |
+ } |
102 |
+ else if (!strncmp(reqArray[i], "Content-Type:", strlen("Content-type:")) || !strncmp(reqArray[i], "Content-type:", strlen("Content-type:"))) |
42 |
+ else if (!strncmp(reqArray[i], "Content-Type:", strlen("Content-type:")) || !strncmp(reqArray[i], "Content-type:", strlen("Content-type:"))) |
103 |
+ { |
43 |
+ { |
Lines 109-122
Link Here
|
109 |
+ else if (!strncmp(reqArray[i], "Cookie:", strlen("Cookie:"))) |
49 |
+ else if (!strncmp(reqArray[i], "Cookie:", strlen("Cookie:"))) |
110 |
+ { |
50 |
+ { |
111 |
+ strncpy(reqStruct->cookie, &reqArray[i][strlen("Cookie: ")], MAX_COOKIE_LEN - 1); |
51 |
+ strncpy(reqStruct->cookie, &reqArray[i][strlen("Cookie: ")], MAX_COOKIE_LEN - 1); |
112 |
+#ifdef PRINTF_DEBUG |
52 |
#ifdef PRINTF_DEBUG |
|
|
53 |
- printf("content length %ld\n", reqStruct->contentLength); |
113 |
+ printf("cookie %s\n", reqStruct->cookie); |
54 |
+ printf("cookie %s\n", reqStruct->cookie); |
114 |
+#endif |
55 |
#endif |
|
|
56 |
- } |
115 |
+ } |
57 |
+ } |
116 |
i++; |
58 |
i++; |
117 |
} |
59 |
} |
118 |
/* if we didn't find a User-Aget we fill in a (N)ot(R)ecognized */ |
60 |
/* if we didn't find a User-Agent we fill in a (N)ot(R)ecognized */ |
119 |
@@ -414,18 +432,39 @@ |
61 |
@@ -431,18 +449,39 @@ |
120 |
/* we append the default file name */ |
62 |
/* we append the default file name */ |
121 |
strcat(completeFilePath, defaultFileName); |
63 |
strcat(completeFilePath, defaultFileName); |
122 |
analyzeExtension(mimeType, completeFilePath); |
64 |
analyzeExtension(mimeType, completeFilePath); |
Lines 159-165
Link Here
|
159 |
} |
101 |
} |
160 |
} |
102 |
} |
161 |
} else if (!strcmp(req.method, "HEAD")) |
103 |
} else if (!strcmp(req.method, "HEAD")) |
162 |
@@ -494,7 +533,14 @@ |
104 |
@@ -511,7 +550,14 @@ |
163 |
strcat(completeFilePath, defaultFileName); |
105 |
strcat(completeFilePath, defaultFileName); |
164 |
} |
106 |
} |
165 |
analyzeExtension(mimeType, completeFilePath); |
107 |
analyzeExtension(mimeType, completeFilePath); |
Lines 175-181
Link Here
|
175 |
} |
117 |
} |
176 |
} else if (!strcmp(req.method, "POST")) |
118 |
} else if (!strcmp(req.method, "POST")) |
177 |
{ |
119 |
{ |
178 |
@@ -507,13 +553,6 @@ |
120 |
@@ -525,13 +571,6 @@ |
179 |
int readFinished; |
121 |
int readFinished; |
180 |
|
122 |
|
181 |
printf("Handling of POST method\n"); |
123 |
printf("Handling of POST method\n"); |
Lines 189-238
Link Here
|
189 |
#ifdef PRINTF_DEBUG |
131 |
#ifdef PRINTF_DEBUG |
190 |
printf ("begin of post handling\n"); |
132 |
printf ("begin of post handling\n"); |
191 |
|
133 |
|
192 |
@@ -523,9 +562,15 @@ |
134 |
@@ -625,7 +664,77 @@ |
193 |
totalRead = 0; |
|
|
194 |
stuckCounter = 0; |
195 |
timeOutCounter = 0; |
196 |
- while (!readFinished) |
197 |
- { |
198 |
- howMany = recv(newSocket, tempBuff, BUFFER_SIZE, 0); |
199 |
+ |
200 |
+ /* SECURITY: Avoid malicious Content-Length -- check \r\n\r\n\0 also */ |
201 |
+ if (req.contentLength < 0 || req.contentLength >= BUFFER_SIZE-5) { |
202 |
+ sayError(sock, 500, "", req); |
203 |
+ return -1; |
204 |
+ } |
205 |
+ |
206 |
+ /* SECURITY: Remove loop to prevent buffer overflow */ |
207 |
+ howMany = recv(newSocket, tempBuff, req.contentLength+5, 0); |
208 |
tempBuff[howMany] = '\0'; /* seems that some Unices need this */ |
209 |
#ifdef PRINTF_DEBUG |
210 |
printf ("read: %d\n%s\n", howMany, tempBuff); |
211 |
@@ -579,16 +624,15 @@ |
212 |
if (howMany == req.contentLength) |
213 |
readFinished = YES; |
214 |
} |
215 |
- } |
216 |
#ifdef PRINTF_DEBUG |
217 |
- printf("total read %d\n", totalRead); |
218 |
+ printf("total read %d\n", totalRead); |
219 |
#endif |
220 |
- if (totalRead == 0) |
221 |
- { |
222 |
- printf("Request read error\n"); |
223 |
- } else |
224 |
- { |
225 |
- if (buff[totalRead - 1] != '\n') /* we need a trailing \n or the script will wait forever */ |
226 |
+ if (totalRead == 0) |
227 |
+ { |
228 |
+ printf("Request read error\n"); |
229 |
+ } else |
230 |
+ { |
231 |
+ if (buff[totalRead - 1] != '\n') /* we need a trailing \n or the script will wait forever */ |
232 |
{ |
233 |
buff[totalRead++] = '\n'; |
234 |
buff[totalRead] = '\0'; |
235 |
@@ -596,7 +640,77 @@ |
236 |
#ifdef PRINTF_DEBUG |
135 |
#ifdef PRINTF_DEBUG |
237 |
printf("buff: |%s|\n", buff); |
136 |
printf("buff: |%s|\n", buff); |
238 |
#endif |
137 |
#endif |
Lines 311-317
Link Here
|
311 |
} |
210 |
} |
312 |
} else |
211 |
} else |
313 |
{ |
212 |
{ |
314 |
@@ -625,7 +739,7 @@ |
213 |
@@ -654,7 +763,7 @@ |
315 |
f = fopen(configFile, "r"); |
214 |
f = fopen(configFile, "r"); |
316 |
if (f == NULL) |
215 |
if (f == NULL) |
317 |
{ |
216 |
{ |
Lines 320-326
Link Here
|
320 |
*serverPort = DEFAULT_PORT; |
219 |
*serverPort = DEFAULT_PORT; |
321 |
*maxChildren = DEFAULT_MAX_CHILDREN; |
220 |
*maxChildren = DEFAULT_MAX_CHILDREN; |
322 |
strcpy(homePath, DEFAULT_DOCS_LOCATION); |
221 |
strcpy(homePath, DEFAULT_DOCS_LOCATION); |
323 |
@@ -634,7 +748,9 @@ |
222 |
@@ -663,7 +772,9 @@ |
324 |
sockTimeVal.tv_usec = DEFAULT_USEC_TO; |
223 |
sockTimeVal.tv_usec = DEFAULT_USEC_TO; |
325 |
strcpy(logFileName, DEFAULT_LOG_FILE); |
224 |
strcpy(logFileName, DEFAULT_LOG_FILE); |
326 |
strcpy(mimeTypesFileName, DEFAULT_MIME_FILE); |
225 |
strcpy(mimeTypesFileName, DEFAULT_MIME_FILE); |
Lines 330-336
Link Here
|
330 |
return -1; |
229 |
return -1; |
331 |
} |
230 |
} |
332 |
if (!feof(f)) fscanf(f, "%s %s", str1, str2); |
231 |
if (!feof(f)) fscanf(f, "%s %s", str1, str2); |
333 |
@@ -735,11 +851,25 @@ |
232 |
@@ -764,11 +875,25 @@ |
334 |
if (mimeTypesFileName == NULL) |
233 |
if (mimeTypesFileName == NULL) |
335 |
{ |
234 |
{ |
336 |
strcpy(mimeTypesFileName, DEFAULT_MIME_FILE); |
235 |
strcpy(mimeTypesFileName, DEFAULT_MIME_FILE); |
Lines 358-386
Link Here
|
358 |
} |
257 |
} |
359 |
if (!feof(f)) fscanf(f, "%s %s", str1, str2); |
258 |
if (!feof(f)) fscanf(f, "%s %s", str1, str2); |
360 |
if (str1 != NULL && str2 != NULL && !strcmp(str1, "cgiRoot")) |
259 |
if (str1 != NULL && str2 != NULL && !strcmp(str1, "cgiRoot")) |
361 |
@@ -775,6 +905,7 @@ |
|
|
362 |
int readFinished; |
363 |
struct request gottenReq; |
364 |
int isKeepAlive; |
365 |
+ int bool; |
366 |
struct sockaddr_in listenName; /* data struct for the listen port */ |
367 |
struct sockaddr_in acceptedSockStruct; /* sockaddr for the internetworking */ |
368 |
int acceptedSocketLen; /* size of the structure */ |
369 |
@@ -808,9 +939,16 @@ |
370 |
printf("socket creation error occoured\n"); |
371 |
return -1; |
372 |
} |
373 |
+ bool = 1; |
374 |
+ error = setsockopt (theSocket, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)); |
375 |
+ if (error == -1) |
376 |
+ { if (errno == EADDRINUSE) |
377 |
+ printf("set socket option error occoured\n"); |
378 |
+ return -1; |
379 |
+ } |
380 |
error = bind (theSocket, (struct sockaddr*) &listenName, sizeof(listenName)); |
381 |
if (error == -1) |
382 |
- { |
383 |
+ { if (errno == EADDRINUSE) |
384 |
printf("socket binding error occoured\n"); |
385 |
return -2; |
386 |
} |