2 * This file is part of DisOrder.
3 * Copyright (C) 2004, 2005, 2007, 2008 Richard Kettlewell
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 /** @file server/cgimain.c
24 #include "disorder-cgi.h"
26 /** @brief Return true if @p a is better than @p b
28 * NB. We don't bother checking if the path is right, we merely check for the
29 * longest path. This isn't a security hole: if the browser wants to send us
30 * bad cookies it's quite capable of sending just the right path anyway. The
31 * point of choosing the longest path is to avoid using a cookie set by another
32 * CGI script which shares a path prefix with us, which would allow it to
33 * maliciously log users out.
35 * Such a script could still "maliciously" log someone in, if it had acquired a
36 * suitable cookie. But it could just log in directly if it had that, so there
37 * is no obvious vulnerability here either.
39 static int better_cookie(const struct cookie *a, const struct cookie *b) {
40 if(a->path && b->path)
41 /* If both have a path then the one with the longest path is best */
42 return strlen(a->path) > strlen(b->path);
44 /* If only @p a has a path then it is better */
47 /* If neither have a path, or if only @p b has a path, then @p b is
52 int main(int argc, char **argv) {
53 const char *cookie_env, *conf;
59 /* RFC 3875 s8.2 recommends rejecting PATH_INFO if we don't make use of
61 if(getenv("PATH_INFO")) {
62 /* TODO it might be nice to link back to the right place... */
63 printf("Content-Type: text/html\n");
64 printf("Status: 404\n");
66 printf("<p>Sorry, PATH_INFO not supported.</p>\n");
70 /* We allow various things to be overridden from the environment. This is
71 * intended for debugging and is not a documented feature. */
72 if((conf = getenv("DISORDER_CONFIG")))
73 configfile = xstrdup(conf);
74 if(getenv("DISORDER_DEBUG"))
78 /* Figure out our URL. This can still be overridden from the config file if
79 * necessary but it shouldn't be necessary in ordinary installations. */
81 config->url = infer_url();
82 /* See if there's a cookie */
83 cookie_env = getenv("HTTP_COOKIE");
85 /* This will be an HTTP header */
86 if(!parse_cookie(cookie_env, &cd)) {
87 /* Pick the best available cookie from all those offered */
89 for(n = 0; n < cd.ncookies; ++n) {
90 /* Is this the right cookie? */
91 if(strcmp(cd.cookies[n].name, "disorder"))
93 /* Is it better than anything we've seen so far? */
95 || better_cookie(&cd.cookies[n], &cd.cookies[best_cookie]))
99 dcgi_cookie = cd.cookies[best_cookie].value;
101 error(0, "could not parse cookie field '%s'", cookie_env);
103 /* Register expansions */
104 mx_register_builtin();
106 /* Update search path. We look in the config directory first and the data
107 * directory second, so that the latter overrides the former. */
108 mx_search_path(pkgconfdir);
109 mx_search_path(pkgdatadir);
110 /* Never cache anythging */
111 if(printf("Cache-Control: no-cache\n") < 0)
112 fatal(errno, "error writing to stdout");
113 /* Create the initial connection, trying the cookie if we found a suitable
116 /* The main program... */
118 /* In practice if a write fails that probably means the web server went away,
119 * but we log it anyway. */
120 if(fclose(stdout) < 0)
121 fatal(errno, "error closing stdout");