Skip to content

Commit e0ff903

Browse files
committed
Provide all environment variables to kreq
Prior to this change, only HTTP_ variables were available to the kreq structure, and these were formatted back into HTTP normal form. Other environment variables (even those referenced in the CGI and FastCGI specs) were discarded. This introduces new variables to kreq, "envs" and "envsz", that has all unmodified variables. This allows callers to access all possible variables and not just those deemed worthy by kcgi(3). Fixes #50
1 parent 0d70214 commit e0ff903

File tree

7 files changed

+157
-16
lines changed

7 files changed

+157
-16
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ REGRESS = regress/test-abort-validator \
218218
regress/test-digest \
219219
regress/test-digest-auth-int \
220220
regress/test-digest-auth-int-bad \
221+
regress/test-environment \
221222
regress/test-epoch2datetime \
222223
regress/test-epoch2str \
223224
regress/test-epoch2tm \

child.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,17 +1060,23 @@ kworker_child_env(const struct env *env, int fd, size_t envsz)
10601060
char c;
10611061
const char *cp;
10621062

1063-
for (reqs = i = 0; i < envsz; i++)
1063+
/* Serialise all environment variables and count HTTPs. */
1064+
1065+
fullwrite(fd, &envsz, sizeof(size_t));
1066+
1067+
for (reqs = i = 0; i < envsz; i++) {
1068+
fullwrite(fd, &env[i].keysz, sizeof(size_t));
1069+
fullwrite(fd, env[i].key, env[i].keysz);
1070+
fullwrite(fd, &env[i].valsz, sizeof(size_t));
1071+
fullwrite(fd, env[i].val, env[i].valsz);
10641072
if (strncmp(env[i].key, "HTTP_", 5) == 0 &&
10651073
env[i].key[5] != '\0')
10661074
reqs++;
1075+
}
10671076

1068-
fullwrite(fd, &reqs, sizeof(size_t));
1077+
/* Serialise known headers (starting with HTTP_). */
10691078

1070-
/*
1071-
* Process known headers (starting with HTTP_).
1072-
* We must have non-zero-length keys.
1073-
*/
1079+
fullwrite(fd, &reqs, sizeof(size_t));
10741080

10751081
for (i = 0; i < envsz; i++) {
10761082
if (strncmp(env[i].key, "HTTP_", 5) ||

kcgi.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,11 @@ kreq_free(struct kreq *req)
903903
free(req->reqs[i].val);
904904
}
905905

906+
for (i = 0; i < req->envsz; i++) {
907+
free(req->envs[i].key);
908+
free(req->envs[i].val);
909+
}
910+
906911
free(req->reqs);
907912
kpair_free(req->cookies, req->cookiesz);
908913
kpair_free(req->fields, req->fieldsz);

kcgi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,8 @@ struct kreq {
455455
struct khead *reqmap[KREQU__MAX];
456456
struct khead *reqs;
457457
size_t reqsz;
458+
struct khead *envs;
459+
size_t envsz;
458460
enum kmethod method;
459461
enum kauth auth;
460462
struct khttpauth rawauth;

man/khttp_parse.3

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,22 +466,43 @@ header variable, or
466466
if that is not defined.
467467
The address format of the string is not checked.
468468
.It Vt "struct khead *" Ns Va reqmap Ns Bq Dv KREQU__MAX
469-
Mapping of
469+
Map of
470470
.Vt "enum krequ"
471-
enumeration values to
472-
.Va reqs
473-
parsed from the input stream.
471+
enumeration values to pairs in
472+
.Va reqs .
473+
If an enumerated request was not specified, it is
474+
.Dv NULL .
474475
.It Vt "struct khead *" Ns Va reqs
475-
List of all HTTP request headers, known via
476-
.Vt "enum krequ"
477-
and not known, parsed from the input stream, or
476+
List of all HTTP request headers or
478477
.Dv NULL
479478
if
480479
.Va reqsz
481480
is 0.
481+
The request headers are in HTTP syntax with all lowercase and
482+
underscores as hyphens, e.g., the CGI variable
483+
.Dv HTTP_ACCEPT_LANGUAGE
484+
is stored as
485+
.Dv http-accept-language .
486+
See
487+
.Va envs
488+
for unmodified environment variables.
482489
.It Vt size_t Va reqsz
483490
Number of request headers in
484491
.Va reqs .
492+
.It Vt "struct khead *" Ns Va envs
493+
List of all environment variables in the CGI or FastCGI context or
494+
.Dv NULL
495+
if
496+
.Va envsz
497+
is 0.
498+
See
499+
.Va reqs
500+
for parsed and formatted HTTP headers, defined as environment variables
501+
starting with
502+
.Dq HTTP_ .
503+
.It Vt size_t Va envsz
504+
Number of environment variables in
505+
.Va envs .
485506
.It Vt "enum kscheme" Va scheme
486507
The access scheme according to the
487508
.Ev HTTPS

parent.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,36 @@ kworker_parent(int fd, struct kreq *r, int eofok, size_t mimesz)
216216

217217
memset(&kp, 0, sizeof(struct kpair));
218218

219+
/* Read all environment variables. */
220+
221+
if (fullread(fd, &r->envsz, sizeof(size_t), 0, &ke) < 0) {
222+
kutil_warnx(NULL, NULL, "read environment size");
223+
goto out;
224+
}
225+
226+
if (r->envsz) {
227+
r->envs = kxcalloc(r->envsz, sizeof(struct khead));
228+
if (r->envs == NULL) {
229+
ke = KCGI_ENOMEM;
230+
goto out;
231+
}
232+
}
233+
234+
for (i = 0; i < r->envsz; i++) {
235+
if ((ke = fullreadword(fd, &r->envs[i].key)) != KCGI_OK) {
236+
kutil_warnx(NULL, NULL, "read environment key");
237+
goto out;
238+
}
239+
if ((ke = fullreadword(fd, &r->envs[i].val)) != KCGI_OK) {
240+
kutil_warnx(NULL, NULL, "read environment value");
241+
goto out;
242+
}
243+
}
244+
219245
/*
220-
* First read all of our parsed parameters.
221-
* Each parsed parameter is handled a little differently.
222-
* This list will end with META__MAX.
246+
* Read all of parsed and formatted HTTP parameters. If the
247+
* request value is not KREQU__MAX, assign the value to the
248+
* request map. (The last parsed wins.)
223249
*/
224250

225251
if (fullread(fd, &r->reqsz, sizeof(size_t), 0, &ke) < 0) {
@@ -252,6 +278,8 @@ kworker_parent(int fd, struct kreq *r, int eofok, size_t mimesz)
252278
r->reqmap[requ] = &r->reqs[i];
253279
}
254280

281+
/* Read remaining variables. */
282+
255283
if (fullread(fd, &r->method, sizeof(enum kmethod), 0, &ke) < 0) {
256284
kutil_warnx(NULL, NULL, "failed read request method");
257285
goto out;

regress/test-environment.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright (c) Kristaps Dzonsons <[email protected]>
3+
*
4+
* Permission to use, copy, modify, and distribute this software for any
5+
* purpose with or without fee is hereby granted, provided that the above
6+
* copyright notice and this permission notice appear in all copies.
7+
*
8+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15+
*/
16+
#include "../config.h"
17+
18+
#include <stdarg.h>
19+
#include <stdint.h>
20+
#include <stdlib.h>
21+
#include <string.h>
22+
#include <unistd.h>
23+
24+
#include <curl/curl.h>
25+
26+
#include "../kcgi.h"
27+
#include "regress.h"
28+
29+
static int
30+
parent(CURL *curl)
31+
{
32+
struct curl_slist *slist = NULL;
33+
int ret;
34+
35+
slist = curl_slist_append(slist, "Testing:123");
36+
slist = curl_slist_append(slist, "Testing-Test:321");
37+
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:17123/");
38+
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
39+
ret = curl_easy_perform(curl);
40+
curl_slist_free_all(slist);
41+
return ret == CURLE_OK;
42+
}
43+
44+
static int
45+
child(void)
46+
{
47+
struct kreq r;
48+
const char *page = "index";
49+
size_t i, found1 = 0, found2 = 0;
50+
51+
if (khttp_parse(&r, NULL, 0, &page, 1, 0) != KCGI_OK)
52+
return 0;
53+
54+
for (i = 0; i < r.envsz; i++) {
55+
if (strcmp(r.envs[i].key, "HTTP_TESTING") == 0)
56+
found1 += strcmp(r.envs[i].val, "123") == 0;
57+
else if (strcmp(r.envs[i].key, "HTTP_TESTING_TEST") == 0)
58+
found2 += strcmp(r.envs[i].val, "321") == 0;
59+
}
60+
61+
if (found1 != 1 || found2 != 1 )
62+
return 0;
63+
64+
khttp_head(&r, kresps[KRESP_STATUS],
65+
"%s", khttps[KHTTP_200]);
66+
khttp_head(&r, kresps[KRESP_CONTENT_TYPE],
67+
"%s", kmimetypes[KMIME_TEXT_HTML]);
68+
khttp_body(&r);
69+
khttp_free(&r);
70+
return 1;
71+
}
72+
73+
int
74+
main(int argc, char *argv[])
75+
{
76+
77+
return regress_cgi(parent, child) ? EXIT_SUCCESS : EXIT_FAILURE;
78+
}

0 commit comments

Comments
 (0)