Commit | Line | Data |
---|---|---|
460b9539 | 1 | /* |
2 | * This file is part of DisOrder. | |
ac169f8a | 3 | * Copyright (C) 2004, 2005, 2007, 2008 Richard Kettlewell |
460b9539 | 4 | * |
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. | |
9 | * | |
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. | |
14 | * | |
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 | |
18 | * USA | |
19 | */ | |
9faa7a88 RK |
20 | /** @file server/cgimain.c |
21 | * @brief DisOrder CGI | |
22 | */ | |
460b9539 | 23 | |
1e97629d | 24 | #include "disorder-cgi.h" |
9faa7a88 | 25 | |
ac169f8a | 26 | /** @brief Return true if @p a is better than @p b |
27 | * | |
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. | |
34 | * | |
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. | |
38 | */ | |
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); | |
43 | else if(a->path) | |
44 | /* If only @p a has a path then it is better */ | |
45 | return 1; | |
46 | else | |
47 | /* If neither have a path, or if only @p b has a path, then @p b is | |
48 | * better */ | |
49 | return 0; | |
50 | } | |
51 | ||
460b9539 | 52 | int main(int argc, char **argv) { |
fdf98378 | 53 | const char *cookie_env, *conf; |
ac169f8a | 54 | int n, best_cookie; |
fdf98378 | 55 | struct cookiedata cd; |
460b9539 | 56 | |
9faa7a88 RK |
57 | if(argc > 0) |
58 | progname = argv[0]; | |
ad9bae0b | 59 | /* RFC 3875 s8.2 recommends rejecting PATH_INFO if we don't make use of |
60 | * it. */ | |
61 | if(getenv("PATH_INFO")) { | |
9faa7a88 | 62 | /* TODO it might be nice to link back to the right place... */ |
ad9bae0b | 63 | printf("Content-Type: text/html\n"); |
64 | printf("Status: 404\n"); | |
65 | printf("\n"); | |
66 | printf("<p>Sorry, PATH_INFO not supported.</p>\n"); | |
67 | exit(0); | |
68 | } | |
71634563 | 69 | cgi_init(); |
9faa7a88 RK |
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")) | |
75 | debugging = 1; | |
76 | if(config_read(0)) | |
77 | exit(EXIT_FAILURE); | |
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. */ | |
36bde473 | 80 | if(!config->url) |
81 | config->url = infer_url(); | |
fdf98378 | 82 | /* See if there's a cookie */ |
83 | cookie_env = getenv("HTTP_COOKIE"); | |
84 | if(cookie_env) { | |
85 | /* This will be an HTTP header */ | |
86 | if(!parse_cookie(cookie_env, &cd)) { | |
ac169f8a | 87 | /* Pick the best available cookie from all those offered */ |
88 | best_cookie = -1; | |
89 | for(n = 0; n < cd.ncookies; ++n) { | |
90 | /* Is this the right cookie? */ | |
91 | if(strcmp(cd.cookies[n].name, "disorder")) | |
92 | continue; | |
93 | /* Is it better than anything we've seen so far? */ | |
94 | if(best_cookie < 0 | |
95 | || better_cookie(&cd.cookies[n], &cd.cookies[best_cookie])) | |
96 | best_cookie = n; | |
97 | } | |
98 | if(best_cookie != -1) | |
1e97629d | 99 | dcgi_cookie = cd.cookies[best_cookie].value; |
06819653 | 100 | } else |
101 | error(0, "could not parse cookie field '%s'", cookie_env); | |
460b9539 | 102 | } |
9faa7a88 RK |
103 | /* Register expansions */ |
104 | mx_register_builtin(); | |
1e97629d | 105 | dcgi_expansions(); |
9faa7a88 RK |
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); | |
bca4e2b7 | 110 | /* Never cache anythging */ |
71634563 RK |
111 | if(printf("Cache-Control: no-cache\n") < 0) |
112 | fatal(errno, "error writing to stdout"); | |
9faa7a88 RK |
113 | /* Create the initial connection, trying the cookie if we found a suitable |
114 | * one. */ | |
1e97629d | 115 | dcgi_login(); |
9faa7a88 | 116 | /* The main program... */ |
1e97629d | 117 | dcgi_action(NULL); |
9faa7a88 RK |
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"); | |
460b9539 | 122 | return 0; |
123 | } | |
124 | ||
125 | /* | |
126 | Local Variables: | |
127 | c-basic-offset:2 | |
128 | comment-column:40 | |
ac169f8a | 129 | fill-column:79 |
130 | indent-tabs-mode:nil | |
460b9539 | 131 | End: |
132 | */ |