1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include "cgiutils.h"
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <inttypes.h>
42
43 #include "../util/util.h"
44 #include "../util/pblock.h"
45 #include "../daemon/protocol.h"
46
47
48
49
50
51
52 #define CGI_VERSION "CGI/1.1"
53
54
55 #define MAX_CGI_COMMON_VARS 23
56 #define MAX_CGI_SPECIFIC_VARS 10
57 #define MAX_CGI_CLIENT_AUTH_VARS 64
58
59
60
61
62
63 int cgi_parse_query(
char **argv,
int n,
char *q)
64 {
65 int i =
0;
66
67 for (;;) {
68
69 char *arg = q;
70 while (*q !=
' ' && *q !=
'\0')
71 q++;
72
73
74 WS_ASSERT(i < n);
75 if (i >= n)
76 return -
1;
77
78
79 char c = *q;
80 *q =
'\0';
81 argv[i] = util_sh_escape(arg);
82 *q = c;
83
84
85 if (!argv[i] || !util_uri_unescape_strict(argv[i]))
86 return -
1;
87
88
89 i++;
90
91
92 if (*q ==
'\0')
93 break;
94
95 q++;
96 }
97
98 return i;
99 }
100
101
102
103
104
105 char **cgi_create_argv(
const char *program,
const char *script,
const char *query)
106 {
107 int nargs =
1;
108
109
110 if (script)
111 nargs++;
112
113
114 char *qargs =
NULL;
115 if (query && !strchr(query,
'=')) {
116 qargs =
STRDUP(query);
117 if (!qargs)
118 return NULL;
119 nargs++;
120 for (
char *t = qargs; *t; t++) {
121 if (*t ==
'+')
122 *t =
' ';
123 if (*t ==
' ')
124 nargs++;
125 }
126 }
127
128
129 char **argv = (
char **)
MALLOC((nargs +
1) *
sizeof(
char *));
130 if (!argv)
131 return NULL;
132
133 int i =
0;
134
135
136 argv[i] =
STRDUP(program);
137 i++;
138
139
140 if (script) {
141 argv[i] =
STRDUP(script);
142 i++;
143 }
144
145
146 if (qargs) {
147 int n = cgi_parse_query(&argv[i], nargs - i, qargs);
148 if (n >
0)
149 i += n;
150 }
151
152
153 argv[i] =
NULL;
154
155 return argv;
156 }
157
158 void cgi_free_argv(
char **args) {
159 int i =
0;
160 while(args[i] !=
NULL) {
161 free(args[i]);
162 i++;
163 }
164 free(args);
165 }
166
167
168
169
170
171 char* cgi_get_request_uri(Request *req)
172 {
173
174 char *clf_request = pblock_findkeyval(pb_key_clf_request, req->reqpb);
175 if (clf_request) {
176
177 char *method = clf_request;
178 while (*method && isspace(*method))
179 method++;
180
181
182 char *uri = method;
183 while (*uri && !isspace(*uri))
184 uri++;
185
186
187 while (*uri && isspace(*uri))
188 uri++;
189
190
191 char *end = uri;
192 while (*end && !isspace(*end))
193 end++;
194
195
196 int len = end - uri;
197 char* request_uri = (
char*)
MALLOC(len+
1);
198 memcpy(request_uri, uri, len);
199 request_uri[len] =
'\0';
200
201 return request_uri;
202 }
203
204
205 return NULL;
206 }
207
208
209
210
211
212 char** cgi_specific_vars(Session *sn, Request *rq,
const char *args,
213 char** env,
int scriptVars)
214 {
215 int y;
216 register pblock *pb;
217 char c, *t, *u;
218
219 pb = rq->reqpb;
220
221 int x;
222 env = util_env_create(env,
MAX_CGI_SPECIFIC_VARS, &x);
223 env[x++] = util_env_str(
"GATEWAY_INTERFACE",
CGI_VERSION);
224
225
226 t = pblock_findval(
"protocol", pb);
227 if (t ==
NULL) {
228 log_ereport(
LOG_FAILURE,
"cgi_specific_vars",
"missing \"protocol\" in rq->reqpb");
229 return NULL;
230 }
231 env[x++] = util_env_str(
"SERVER_PROTOCOL", t);
232
233 t = pblock_findval(
"method", pb);
234 if (t ==
NULL) {
235 log_ereport(
LOG_FAILURE,
"cgi_specific_vars",
"missing \"request method\" in rq->reqpb");
236 return NULL;
237 }
238 env[x++] = util_env_str(
"REQUEST_METHOD", t);
239
240 if (args)
241 env[x++] = util_env_str(
"QUERY_STRING", args);
242
243
244 if (rq->orig_rq) {
245 t = cgi_get_request_uri(rq->orig_rq);
246 }
else {
247 t = cgi_get_request_uri(rq);
248 }
249 if (t) {
250 env[x++] = util_env_str(
"REQUEST_URI", t);
251 FREE(t);
252 }
253
254 if (scriptVars) {
255 t = pblock_findval(
"uri", pb);
256
257
258 if ((u = pblock_findval(
"path-info", rq->vars))) {
259 y = strlen(t) - strlen(u);
260 if (y >=
0) {
261 c = t[y];
262 t[y] =
'\0';
263 }
264 env[x++] = util_env_str(
"SCRIPT_NAME", t);
265 if (y >=
0) {
266 t[y] = c;
267 }
268
269 env[x++] = util_env_str(
"PATH_INFO", u);
270
271
272
273
274
275
276
277
278
279
280
281 }
else {
282 env[x++] = util_env_str(
"SCRIPT_NAME", t);
283 }
284
285 if ((t = pblock_findval(
"path", rq->vars)))
286 env[x++] = util_env_str(
"SCRIPT_FILENAME", t);
287 }
288
289 env[x] =
NULL;
290 return env;
291 }
292
293
294
295
296
297 char** cgi_common_vars(Session *sn, Request *rq,
char **env)
298 {
299 char *t;
300 int x;
301
302 env = util_env_create(env,
MAX_CGI_COMMON_VARS, &x);
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 char *scheme;
319 char *host;
320 uint16_t port;
321 http_get_scheme_host_port(sn, rq, &scheme, &host, &port);
322 char portstr[
8];
323 snprintf(portstr,
8,
"%" PRIu16, (
int)port);
324 env[x++] = util_env_str(
"SERVER_PORT", portstr);
325 env[x++] = util_env_str(
"SERVER_NAME", host);
326
327
328
329
330
331 char *ip;
332 ip = pblock_findval(
"ip", sn->client);
333 t = session_dns(sn);
334 env[x++] = util_env_str(
"REMOTE_HOST", (t ? t : ip));
335 env[x++] = util_env_str(
"REMOTE_ADDR", ip);
336
337 if((t = pblock_findval(
"auth-user", rq->vars))) {
338 env[x++] = util_env_str(
"REMOTE_USER", t);
339 if((t = pblock_findval(
"auth-type", rq->vars))) {
340 env[x++] = util_env_str(
"AUTH_TYPE", t);
341 }
342 if((t = pblock_findval(
"auth-userdn", rq->vars))) {
343 env[x++] = util_env_str(
"REMOTE_USERDN", t);
344 }
345 }
346 if((t = pblock_findval(
"password-policy", rq->vars))) {
347
348 env[x++] = util_env_str(
"PASSWORD_POLICY", t);
349 }
350
351
352 if (rq->orig_rq != rq) {
353 if ((t = pblock_findval(
"uri", rq->orig_rq->reqpb))) {
354 env[x++] = util_env_str(
"REDIRECT_URL", t);
355 }
356 if ((t = pblock_findval(
"status", rq->orig_rq->srvhdrs))) {
357 env[x++] = util_env_str(
"REDIRECT_STATUS", t);
358 }
359 }
360
361 if(sn->ssl) {
362 env[x++] = util_env_str(
"HTTPS",
"ON");
363 }
364
365 #if 0
366 if (GetSecurity(sn)) {
367 env[x++] = util_env_str(
"HTTPS",
"ON");
368
369 if (t = pblock_findval(
"keysize", sn->client))
370 env[x++] = util_env_str(
"HTTPS_KEYSIZE", t);
371
372 if (t = pblock_findval(
"secret-keysize", sn->client))
373 env[x++] = util_env_str(
"HTTPS_SECRETKEYSIZE", t);
374
375 t = pblock_findval(
"ssl-id", sn->client);
376 env[x++] = util_env_str(
"HTTPS_SESSIONID", t ? t : (
char *)
"");
377
378 unsigned char random_bytes[
NUM_RANDOM_BYTES +
2];
379 char random_string[
NUM_RANDOM_BYTES*
2 +
2];
380 PK11_GenerateRandom(random_bytes,
NUM_RANDOM_BYTES);
381
382 int i;
383 for(i =
0; i <
NUM_RANDOM_BYTES; i++) {
384 sprintf(&random_string[i*
2],
"%02x",
385 (
unsigned int)(random_bytes[i] & 0xff));
386 }
387 random_string[
NUM_RANDOM_BYTES*
2] =
'\0';
388 env[x++] = util_env_str(
"HTTPS_RANDOM", random_string);
389
390 }
else {
391 env[x++] = util_env_str(
"HTTPS",
"OFF");
392 }
393 #endif
394
395 env[x] =
NULL;
396
397
398
399 return env;
400
401 }
402