/[hydra]/hydra/src/cgi_header.c
ViewVC logotype

Contents of /hydra/src/cgi_header.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (show annotations)
Sat Jul 24 23:39:48 2004 UTC (19 years, 8 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_1_6_without_hic, hydra_0_1_7, hydra_0_1_6, hydra_0_1_8, HEAD
Changes since 1.6: +2 -3 lines
File MIME type: text/plain
*** empty log message ***

1 /*
2 * Hydra, an http server
3 * cgi_header.c - cgi header parsing and control
4 * Copyright (C) 1997-99 Jon Nelson <jnelson@boa.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 1, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22 #include "boa.h"
23
24 /* process_cgi_header
25
26 * returns 0 -=> error or HEAD, close down.
27 * returns 1 -=> done processing
28 * leaves req->cgi_status as WRITE
29 */
30
31 /*
32 The server MUST also resolve any conflicts between header fields returned by
33 the script and header fields that it would otherwise send itself.
34
35 ...
36
37 At least one CGI-Field MUST be supplied, but no CGI field name may be used
38 more than once in a response. If a body is supplied, then a
39 "Content-type" header field MUST be supplied by the script,
40 otherwise the script MUST send a "Location" or "Status" header
41 field. If a Location CGI-Field is returned, then the script
42 MUST NOT supply any HTTP-Fields.
43 */
44
45 /* TODO:
46 We still need to cycle through the data before the end of the headers,
47 line-by-line, and check for any problems with the CGI
48 outputting overriding http responses, etc...
49 */
50 int process_cgi_header(request * req)
51 {
52 char *buf;
53 char *c;
54
55 if (req->cgi_status != CGI_DONE)
56 req->cgi_status = CGI_BUFFER;
57
58 buf = req->header_line;
59
60 c = strstr(buf, "\n\r\n");
61 if (c == NULL) {
62 c = strstr(buf, "\n\n");
63 if (c == NULL) {
64 log_error_time();
65 fputs("cgi_header: unable to find LFLF\n", stderr);
66 #ifdef FASCIST_LOGGING
67 log_error_time();
68 fprintf(stderr, "\"%s\"\n", buf);
69 #endif
70 send_r_bad_gateway(req);
71 return 0;
72 }
73 }
74 if (req->http_version == HTTP_0_9) {
75 if (*(c + 1) == '\r')
76 req->header_line = c + 2;
77 else
78 req->header_line = c + 1;
79 return 1;
80 }
81 if (!strncasecmp(buf, "Location: ", 10)) { /* got a location header */
82 #ifdef FASCIST_LOGGING
83
84 log_error_time();
85 fprintf(stderr, "%s:%d - found Location header \"%s\"\n",
86 __FILE__, __LINE__, buf + 10);
87 #endif
88
89
90 if (buf[10] == '/') { /* virtual path */
91 log_error_time();
92 fprintf(stderr,
93 "server does not support internal redirection: " \
94 "\"%s\"\n", buf + 10);
95 send_r_bad_request(req);
96
97 /*
98 * We (I, Jon) have declined to support absolute-path parsing
99 * because I see it as a major security hole.
100 * Location: /etc/passwd or Location: /etc/shadow is not funny.
101 *
102 * Also, the below code is borked.
103 * request_uri could contain /cgi-bin/bob/extra_path
104 */
105
106 /*
107 strcpy(req->request_uri, buf + 10);
108 return internal_redirect(req);
109 */
110 } else { /* URL */
111 char *c2;
112 c2 = strchr(buf + 10, '\n');
113 /* c2 cannot ever equal NULL here because we already have found one */
114
115 --c2;
116 while (*c2 == '\r')
117 --c2;
118 ++c2;
119 /* c2 now points to a '\r' or the '\n' */
120 *c2++ = '\0'; /* end header */
121
122 /* first next header, or is at req->header_end */
123 while ((*c2 == '\n' || *c2 == '\r') && c2 < req->header_end)
124 ++c2;
125 if (c2 == req->header_end)
126 send_r_moved_temp(req, buf + 10, "");
127 else
128 send_r_moved_temp(req, buf + 10, c2);
129 }
130 req->status = DONE;
131 return 1;
132 } else { /* not location */
133 char *dest;
134 int howmuch;
135
136 if (!strncasecmp(buf, "Status: ", 8)) {
137 char str_status[4];
138 char desc[32];
139 int len;
140 char *p = buf+8;
141
142 len = 0;
143 while(*p != '\r' && *p != ' ' && *p != 0) { len++; p++; }
144
145 if (len > sizeof(str_status)-1) { /* status code too long! */
146 req->buffer_start = req->buffer_end = 0;
147 log_error_time();
148 fprintf(stderr, "status code (%d bytes) is too long\n", len);
149 send_r_error(req);
150 return 0;
151 }
152 memcpy( str_status, buf+8, 3);
153 str_status[3] = 0;
154
155 len = 0;
156 if (*p == ' ') p++;
157 while( (*p != '\r') && *p != 0) { len++; p++; }
158
159 if (len > sizeof(desc)-1) { /* description long! */
160 req->buffer_start = req->buffer_end = 0;
161 log_error_time();
162 fprintf(stderr, "description (%d bytes) is too long\n", len);
163 send_r_error(req);
164 return 0;
165 }
166
167 memcpy( desc, p-len, len);
168 desc[len] = 0;
169
170 send_r_request_cgi_status(req, str_status, desc); /* does not terminate */
171
172 if (*p=='\r' && *(p+1)=='\n')
173 p+=2; /* skip \r\n and move to the next line */
174
175 req->header_line = p;
176 } else {
177 send_r_request_cgi_status(req, "200", "OK"); /* does not terminate */
178 }
179
180 /* got to do special things because
181 a) we have a single buffer divided into 2 pieces
182 b) we need to merge those pieces
183 Easiest way is to memmove the cgi data backward until
184 it touches the buffered data, then reset the cgi data pointers
185 */
186 dest = req->buffer + req->buffer_end;
187 if (req->method == M_HEAD) {
188 if (*(c + 1) == '\r')
189 req->header_end = c + 2;
190 else
191 req->header_end = c + 1;
192 req->cgi_status = CGI_DONE;
193 }
194 howmuch = req->header_end - req->header_line;
195
196 if (dest + howmuch > req->buffer + BUFFER_SIZE) {
197 /* big problem */
198 log_error_time();
199 fprintf(stderr, "Too much data to move! Aborting! %s %d\n",
200 __FILE__, __LINE__);
201 /* reset buffer pointers because we already called
202 send_r_request_ok... */
203 req->buffer_start = req->buffer_end = 0;
204 send_r_error(req);
205 return 0;
206 }
207 memmove(dest, req->header_line, howmuch);
208 req->buffer_end += howmuch;
209 req->header_line = req->buffer + req->buffer_end;
210 req->header_end = req->header_line;
211 req_flush(req);
212
213 if (req->method == M_HEAD)
214 return 0;
215 }
216 return 1;
217 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26