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 | |
24 | #include <config.h> | |
6d2d327c | 25 | #include "types.h" |
460b9539 | 26 | |
27 | #include <stdio.h> | |
28 | #include <errno.h> | |
29 | #include <stdlib.h> | |
30 | #include <sys/types.h> | |
31 | #include <sys/socket.h> | |
32 | #include <locale.h> | |
33 | #include <string.h> | |
34 | #include <stdarg.h> | |
35 | ||
36 | #include "client.h" | |
37 | #include "sink.h" | |
71634563 | 38 | #include "hash.h" |
460b9539 | 39 | #include "mem.h" |
40 | #include "log.h" | |
41 | #include "configuration.h" | |
42 | #include "disorder.h" | |
43 | #include "api-client.h" | |
fdf98378 | 44 | #include "mime.h" |
b64c2805 | 45 | #include "printf.h" |
36bde473 | 46 | #include "url.h" |
9faa7a88 RK |
47 | #include "macros.h" |
48 | #include "macros-disorder.h" | |
71634563 RK |
49 | #include "cgi.h" |
50 | #include "actions.h" | |
51 | #include "defs.h" | |
9faa7a88 | 52 | |
ac169f8a | 53 | /** @brief Return true if @p a is better than @p b |
54 | * | |
55 | * NB. We don't bother checking if the path is right, we merely check for the | |
56 | * longest path. This isn't a security hole: if the browser wants to send us | |
57 | * bad cookies it's quite capable of sending just the right path anyway. The | |
58 | * point of choosing the longest path is to avoid using a cookie set by another | |
59 | * CGI script which shares a path prefix with us, which would allow it to | |
60 | * maliciously log users out. | |
61 | * | |
62 | * Such a script could still "maliciously" log someone in, if it had acquired a | |
63 | * suitable cookie. But it could just log in directly if it had that, so there | |
64 | * is no obvious vulnerability here either. | |
65 | */ | |
66 | static int better_cookie(const struct cookie *a, const struct cookie *b) { | |
67 | if(a->path && b->path) | |
68 | /* If both have a path then the one with the longest path is best */ | |
69 | return strlen(a->path) > strlen(b->path); | |
70 | else if(a->path) | |
71 | /* If only @p a has a path then it is better */ | |
72 | return 1; | |
73 | else | |
74 | /* If neither have a path, or if only @p b has a path, then @p b is | |
75 | * better */ | |
76 | return 0; | |
77 | } | |
78 | ||
460b9539 | 79 | int main(int argc, char **argv) { |
fdf98378 | 80 | const char *cookie_env, *conf; |
ac169f8a | 81 | int n, best_cookie; |
fdf98378 | 82 | struct cookiedata cd; |
460b9539 | 83 | |
9faa7a88 RK |
84 | if(argc > 0) |
85 | progname = argv[0]; | |
ad9bae0b | 86 | /* RFC 3875 s8.2 recommends rejecting PATH_INFO if we don't make use of |
87 | * it. */ | |
88 | if(getenv("PATH_INFO")) { | |
9faa7a88 | 89 | /* TODO it might be nice to link back to the right place... */ |
ad9bae0b | 90 | printf("Content-Type: text/html\n"); |
91 | printf("Status: 404\n"); | |
92 | printf("\n"); | |
93 | printf("<p>Sorry, PATH_INFO not supported.</p>\n"); | |
94 | exit(0); | |
95 | } | |
71634563 | 96 | cgi_init(); |
9faa7a88 RK |
97 | /* We allow various things to be overridden from the environment. This is |
98 | * intended for debugging and is not a documented feature. */ | |
99 | if((conf = getenv("DISORDER_CONFIG"))) | |
100 | configfile = xstrdup(conf); | |
101 | if(getenv("DISORDER_DEBUG")) | |
102 | debugging = 1; | |
103 | if(config_read(0)) | |
104 | exit(EXIT_FAILURE); | |
105 | /* Figure out our URL. This can still be overridden from the config file if | |
106 | * necessary but it shouldn't be necessary in ordinary installations. */ | |
36bde473 | 107 | if(!config->url) |
108 | config->url = infer_url(); | |
fdf98378 | 109 | /* See if there's a cookie */ |
110 | cookie_env = getenv("HTTP_COOKIE"); | |
111 | if(cookie_env) { | |
112 | /* This will be an HTTP header */ | |
113 | if(!parse_cookie(cookie_env, &cd)) { | |
ac169f8a | 114 | /* Pick the best available cookie from all those offered */ |
115 | best_cookie = -1; | |
116 | for(n = 0; n < cd.ncookies; ++n) { | |
117 | /* Is this the right cookie? */ | |
118 | if(strcmp(cd.cookies[n].name, "disorder")) | |
119 | continue; | |
120 | /* Is it better than anything we've seen so far? */ | |
121 | if(best_cookie < 0 | |
122 | || better_cookie(&cd.cookies[n], &cd.cookies[best_cookie])) | |
123 | best_cookie = n; | |
124 | } | |
125 | if(best_cookie != -1) | |
126 | login_cookie = cd.cookies[best_cookie].value; | |
06819653 | 127 | } else |
128 | error(0, "could not parse cookie field '%s'", cookie_env); | |
460b9539 | 129 | } |
9faa7a88 RK |
130 | /* Register expansions */ |
131 | mx_register_builtin(); | |
132 | register_disorder_expansions(); | |
133 | /* Update search path. We look in the config directory first and the data | |
134 | * directory second, so that the latter overrides the former. */ | |
135 | mx_search_path(pkgconfdir); | |
136 | mx_search_path(pkgdatadir); | |
bca4e2b7 | 137 | /* Never cache anythging */ |
71634563 RK |
138 | if(printf("Cache-Control: no-cache\n") < 0) |
139 | fatal(errno, "error writing to stdout"); | |
9faa7a88 RK |
140 | /* Create the initial connection, trying the cookie if we found a suitable |
141 | * one. */ | |
71634563 | 142 | disorder_cgi_login(); |
9faa7a88 | 143 | /* The main program... */ |
71634563 | 144 | disorder_cgi_action(NULL); |
9faa7a88 RK |
145 | /* In practice if a write fails that probably means the web server went away, |
146 | * but we log it anyway. */ | |
147 | if(fclose(stdout) < 0) | |
148 | fatal(errno, "error closing stdout"); | |
460b9539 | 149 | return 0; |
150 | } | |
151 | ||
152 | /* | |
153 | Local Variables: | |
154 | c-basic-offset:2 | |
155 | comment-column:40 | |
ac169f8a | 156 | fill-column:79 |
157 | indent-tabs-mode:nil | |
460b9539 | 158 | End: |
159 | */ |