#include "cgiutils.h"
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "../util/util.h"
#include "../util/pblock.h"
#include "../daemon/protocol.h"
#define CGI_VERSION "CGI/1.1"
#define MAX_CGI_COMMON_VARS 23
#define MAX_CGI_SPECIFIC_VARS 10
#define MAX_CGI_CLIENT_AUTH_VARS 64
int cgi_parse_query(
char **argv,
int n,
char *q)
{
int i =
0;
for (;;) {
char *arg = q;
while (*q !=
' ' && *q !=
'\0')
q++;
WS_ASSERT(i < n);
if (i >= n)
return -
1;
char c = *q;
*q =
'\0';
argv[i] = util_sh_escape(arg);
*q = c;
if (!argv[i] || !util_uri_unescape_strict(argv[i]))
return -
1;
i++;
if (*q ==
'\0')
break;
q++;
}
return i;
}
char **cgi_create_argv(
const char *program,
const char *script,
const char *query)
{
int nargs =
1;
if (script)
nargs++;
char *qargs =
NULL;
if (query && !strchr(query,
'=')) {
qargs =
STRDUP(query);
if (!qargs)
return NULL;
nargs++;
for (
char *t = qargs; *t; t++) {
if (*t ==
'+')
*t =
' ';
if (*t ==
' ')
nargs++;
}
}
char **argv = (
char **)
MALLOC((nargs +
1) *
sizeof(
char *));
if (!argv)
return NULL;
int i =
0;
argv[i] =
STRDUP(program);
i++;
if (script) {
argv[i] =
STRDUP(script);
i++;
}
if (qargs) {
int n = cgi_parse_query(&argv[i], nargs - i, qargs);
if (n >
0)
i += n;
}
argv[i] =
NULL;
return argv;
}
void cgi_free_argv(
char **args) {
int i =
0;
while(args[i] !=
NULL) {
free(args[i]);
i++;
}
free(args);
}
char* cgi_get_request_uri(Request *req)
{
char *clf_request = pblock_findkeyval(pb_key_clf_request, req->reqpb);
if (clf_request) {
char *method = clf_request;
while (*method && isspace(*method))
method++;
char *uri = method;
while (*uri && !isspace(*uri))
uri++;
while (*uri && isspace(*uri))
uri++;
char *end = uri;
while (*end && !isspace(*end))
end++;
int len = end - uri;
char* request_uri = (
char*)
MALLOC(len+
1);
memcpy(request_uri, uri, len);
request_uri[len] =
'\0';
return request_uri;
}
return NULL;
}
char** cgi_specific_vars(Session *sn, Request *rq,
const char *args,
char** env,
int scriptVars)
{
int y;
register pblock *pb;
char c, *t, *u;
pb = rq->reqpb;
int x;
env = util_env_create(env,
MAX_CGI_SPECIFIC_VARS, &x);
env[x++] = util_env_str(
"GATEWAY_INTERFACE",
CGI_VERSION);
t = pblock_findval(
"protocol", pb);
if (t ==
NULL) {
log_ereport(
LOG_FAILURE,
"cgi_specific_vars",
"missing \"protocol\" in rq->reqpb");
return NULL;
}
env[x++] = util_env_str(
"SERVER_PROTOCOL", t);
t = pblock_findval(
"method", pb);
if (t ==
NULL) {
log_ereport(
LOG_FAILURE,
"cgi_specific_vars",
"missing \"request method\" in rq->reqpb");
return NULL;
}
env[x++] = util_env_str(
"REQUEST_METHOD", t);
if (args)
env[x++] = util_env_str(
"QUERY_STRING", args);
if (rq->orig_rq) {
t = cgi_get_request_uri(rq->orig_rq);
}
else {
t = cgi_get_request_uri(rq);
}
if (t) {
env[x++] = util_env_str(
"REQUEST_URI", t);
FREE(t);
}
if (scriptVars) {
t = pblock_findval(
"uri", pb);
if ((u = pblock_findval(
"path-info", rq->vars))) {
y = strlen(t) - strlen(u);
if (y >=
0) {
c = t[y];
t[y] =
'\0';
}
env[x++] = util_env_str(
"SCRIPT_NAME", t);
if (y >=
0) {
t[y] = c;
}
env[x++] = util_env_str(
"PATH_INFO", u);
}
else {
env[x++] = util_env_str(
"SCRIPT_NAME", t);
}
if ((t = pblock_findval(
"path", rq->vars)))
env[x++] = util_env_str(
"SCRIPT_FILENAME", t);
}
env[x] =
NULL;
return env;
}
char** cgi_common_vars(Session *sn, Request *rq,
char **env)
{
char *t;
int x;
env = util_env_create(env,
MAX_CGI_COMMON_VARS, &x);
char *scheme;
char *host;
uint16_t port;
http_get_scheme_host_port(sn, rq, &scheme, &host, &port);
char portstr[
8];
snprintf(portstr,
8,
"%" PRIu16, (
int)port);
env[x++] = util_env_str(
"SERVER_PORT", portstr);
env[x++] = util_env_str(
"SERVER_NAME", host);
char *ip;
ip = pblock_findval(
"ip", sn->client);
t = session_dns(sn);
env[x++] = util_env_str(
"REMOTE_HOST", (t ? t : ip));
env[x++] = util_env_str(
"REMOTE_ADDR", ip);
if((t = pblock_findval(
"auth-user", rq->vars))) {
env[x++] = util_env_str(
"REMOTE_USER", t);
if((t = pblock_findval(
"auth-type", rq->vars))) {
env[x++] = util_env_str(
"AUTH_TYPE", t);
}
if((t = pblock_findval(
"auth-userdn", rq->vars))) {
env[x++] = util_env_str(
"REMOTE_USERDN", t);
}
}
if((t = pblock_findval(
"password-policy", rq->vars))) {
env[x++] = util_env_str(
"PASSWORD_POLICY", t);
}
if (rq->orig_rq != rq) {
if ((t = pblock_findval(
"uri", rq->orig_rq->reqpb))) {
env[x++] = util_env_str(
"REDIRECT_URL", t);
}
if ((t = pblock_findval(
"status", rq->orig_rq->srvhdrs))) {
env[x++] = util_env_str(
"REDIRECT_STATUS", t);
}
}
if(sn->ssl) {
env[x++] = util_env_str(
"HTTPS",
"ON");
}
#if 0
if (GetSecurity(sn)) {
env[x++] = util_env_str(
"HTTPS",
"ON");
if (t = pblock_findval(
"keysize", sn->client))
env[x++] = util_env_str(
"HTTPS_KEYSIZE", t);
if (t = pblock_findval(
"secret-keysize", sn->client))
env[x++] = util_env_str(
"HTTPS_SECRETKEYSIZE", t);
t = pblock_findval(
"ssl-id", sn->client);
env[x++] = util_env_str(
"HTTPS_SESSIONID", t ? t : (
char *)
"");
unsigned char random_bytes[
NUM_RANDOM_BYTES +
2];
char random_string[
NUM_RANDOM_BYTES*
2 +
2];
PK11_GenerateRandom(random_bytes,
NUM_RANDOM_BYTES);
int i;
for(i =
0; i <
NUM_RANDOM_BYTES; i++) {
sprintf(&random_string[i*
2],
"%02x",
(
unsigned int)(random_bytes[i] & 0xff));
}
random_string[
NUM_RANDOM_BYTES*
2] =
'\0';
env[x++] = util_env_str(
"HTTPS_RANDOM", random_string);
}
else {
env[x++] = util_env_str(
"HTTPS",
"OFF");
}
#endif
env[x] =
NULL;
return env;
}