]>
Commit | Line | Data |
---|---|---|
965e99b5 MW |
1 | /* |
2 | * Copyright (C) 2007 Martin Willi | |
19ef2aec TB |
3 | * |
4 | * Copyright (C) secunet Security Networks AG | |
965e99b5 MW |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
15 | */ | |
16 | ||
17 | #define _GNU_SOURCE | |
18 | ||
890f2098 | 19 | #include "fast_session.h" |
965e99b5 MW |
20 | |
21 | #include <string.h> | |
22 | #include <fcgiapp.h> | |
23 | #include <stdio.h> | |
24 | ||
12642a68 | 25 | #include <collections/linked_list.h> |
965e99b5 | 26 | |
a6225e49 MW |
27 | #define COOKIE_LEN 16 |
28 | ||
890f2098 | 29 | typedef struct private_fast_session_t private_fast_session_t; |
965e99b5 MW |
30 | |
31 | /** | |
32 | * private data of the task manager | |
33 | */ | |
890f2098 | 34 | struct private_fast_session_t { |
965e99b5 MW |
35 | |
36 | /** | |
37 | * public functions | |
38 | */ | |
890f2098 | 39 | fast_session_t public; |
7daf5226 | 40 | |
965e99b5 MW |
41 | /** |
42 | * session ID | |
43 | */ | |
a6225e49 MW |
44 | char sid[COOKIE_LEN * 2 + 1]; |
45 | ||
46 | /** | |
47 | * have we sent the session cookie? | |
48 | */ | |
49 | bool cookie_sent; | |
7daf5226 | 50 | |
965e99b5 MW |
51 | /** |
52 | * list of controller instances controller_t | |
53 | */ | |
54 | linked_list_t *controllers; | |
7daf5226 | 55 | |
552cc11b MW |
56 | /** |
57 | * list of filter instances filter_t | |
58 | */ | |
59 | linked_list_t *filters; | |
7daf5226 | 60 | |
965e99b5 MW |
61 | /** |
62 | * user defined session context | |
63 | */ | |
890f2098 | 64 | fast_context_t *context; |
965e99b5 MW |
65 | }; |
66 | ||
890f2098 MW |
67 | METHOD(fast_session_t, add_controller, void, |
68 | private_fast_session_t *this, fast_controller_t *controller) | |
965e99b5 MW |
69 | { |
70 | this->controllers->insert_last(this->controllers, controller); | |
71 | } | |
72 | ||
890f2098 MW |
73 | METHOD(fast_session_t, add_filter, void, |
74 | private_fast_session_t *this, fast_filter_t *filter) | |
552cc11b MW |
75 | { |
76 | this->filters->insert_last(this->filters, filter); | |
77 | } | |
78 | ||
965e99b5 MW |
79 | /** |
80 | * Create a session ID and a cookie | |
81 | */ | |
890f2098 | 82 | static bool create_sid(private_fast_session_t *this) |
965e99b5 | 83 | { |
a6225e49 | 84 | char buf[COOKIE_LEN]; |
6a365f07 | 85 | rng_t *rng; |
7daf5226 | 86 | |
6a365f07 | 87 | rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); |
9181784f | 88 | if (!rng) |
6a365f07 | 89 | { |
76a98ee2 MW |
90 | return FALSE; |
91 | } | |
92 | if (!rng->get_bytes(rng, sizeof(buf), buf)) | |
93 | { | |
6a365f07 | 94 | rng->destroy(rng); |
76a98ee2 | 95 | return FALSE; |
6a365f07 | 96 | } |
76a98ee2 | 97 | rng->destroy(rng); |
a6225e49 | 98 | chunk_to_hex(chunk_create(buf, sizeof(buf)), this->sid, FALSE); |
76a98ee2 | 99 | return TRUE; |
965e99b5 MW |
100 | } |
101 | ||
552cc11b MW |
102 | /** |
103 | * run all registered filters | |
104 | */ | |
890f2098 MW |
105 | static bool run_filter(private_fast_session_t *this, fast_request_t *request, |
106 | char *p0, char *p1, char *p2, char *p3, char *p4, char *p5) | |
552cc11b | 107 | { |
69767897 | 108 | enumerator_t *enumerator; |
890f2098 | 109 | fast_filter_t *filter; |
7daf5226 | 110 | |
69767897 MW |
111 | enumerator = this->filters->create_enumerator(this->filters); |
112 | while (enumerator->enumerate(enumerator, &filter)) | |
552cc11b | 113 | { |
69767897 | 114 | if (!filter->run(filter, request, p0, p1, p2, p3, p4, p5)) |
552cc11b | 115 | { |
69767897 | 116 | enumerator->destroy(enumerator); |
552cc11b MW |
117 | return FALSE; |
118 | } | |
119 | } | |
69767897 | 120 | enumerator->destroy(enumerator); |
552cc11b MW |
121 | return TRUE; |
122 | } | |
123 | ||
890f2098 MW |
124 | METHOD(fast_session_t, process, void, |
125 | private_fast_session_t *this, fast_request_t *request) | |
965e99b5 | 126 | { |
780050cb | 127 | char *pos, *start, *param[6] = {NULL, NULL, NULL, NULL, NULL, NULL}; |
69767897 | 128 | enumerator_t *enumerator; |
965e99b5 | 129 | bool handled = FALSE; |
890f2098 | 130 | fast_controller_t *current; |
780050cb | 131 | int i = 0; |
7daf5226 | 132 | |
a6225e49 | 133 | if (!this->cookie_sent) |
965e99b5 | 134 | { |
a6225e49 MW |
135 | request->add_cookie(request, "SID", this->sid); |
136 | this->cookie_sent = TRUE; | |
965e99b5 | 137 | } |
7daf5226 | 138 | |
780050cb MW |
139 | start = request->get_path(request); |
140 | if (start) | |
965e99b5 | 141 | { |
69767897 MW |
142 | if (*start == '/') |
143 | { | |
144 | start++; | |
145 | } | |
780050cb | 146 | while ((pos = strchr(start, '/')) != NULL && i < 5) |
965e99b5 | 147 | { |
69767897 | 148 | param[i++] = strndupa(start, pos - start); |
780050cb | 149 | start = pos + 1; |
965e99b5 | 150 | } |
69767897 | 151 | param[i] = strdupa(start); |
7daf5226 MW |
152 | |
153 | if (run_filter(this, request, param[0], param[1], param[2], param[3], | |
323f9f99 | 154 | param[4], param[5])) |
965e99b5 | 155 | { |
69767897 MW |
156 | enumerator = this->controllers->create_enumerator(this->controllers); |
157 | while (enumerator->enumerate(enumerator, ¤t)) | |
158 | { | |
159 | if (streq(current->get_name(current), param[0])) | |
7daf5226 | 160 | { |
552cc11b MW |
161 | current->handle(current, request, param[1], param[2], |
162 | param[3], param[4], param[5]); | |
163 | handled = TRUE; | |
69767897 | 164 | break; |
552cc11b | 165 | } |
780050cb | 166 | } |
69767897 | 167 | enumerator->destroy(enumerator); |
965e99b5 | 168 | } |
69767897 | 169 | else |
780050cb | 170 | { |
69767897 | 171 | handled = TRUE; |
965e99b5 MW |
172 | } |
173 | } | |
965e99b5 MW |
174 | if (!handled) |
175 | { | |
c01f7bf9 MW |
176 | if (this->controllers->get_first(this->controllers, |
177 | (void**)¤t) == SUCCESS) | |
178 | { | |
69e492f2 MW |
179 | request->streamf(request, |
180 | "Status: 301 Moved permanently\nLocation: %s/%s\n\n", | |
181 | request->get_base(request), current->get_name(current)); | |
c01f7bf9 | 182 | } |
965e99b5 MW |
183 | } |
184 | } | |
185 | ||
890f2098 MW |
186 | METHOD(fast_session_t, get_sid, char*, |
187 | private_fast_session_t *this) | |
965e99b5 MW |
188 | { |
189 | return this->sid; | |
190 | } | |
191 | ||
890f2098 MW |
192 | METHOD(fast_session_t, destroy, void, |
193 | private_fast_session_t *this) | |
965e99b5 | 194 | { |
890f2098 MW |
195 | this->controllers->destroy_offset(this->controllers, |
196 | offsetof(fast_controller_t, destroy)); | |
197 | this->filters->destroy_offset(this->filters, | |
198 | offsetof(fast_filter_t, destroy)); | |
69767897 | 199 | DESTROY_IF(this->context); |
965e99b5 MW |
200 | free(this); |
201 | } | |
202 | ||
203 | /* | |
204 | * see header file | |
205 | */ | |
890f2098 | 206 | fast_session_t *fast_session_create(fast_context_t *context) |
965e99b5 | 207 | { |
890f2098 | 208 | private_fast_session_t *this; |
7804b7f4 MW |
209 | |
210 | INIT(this, | |
211 | .public = { | |
212 | .add_controller = _add_controller, | |
213 | .add_filter = _add_filter, | |
214 | .process = _process, | |
215 | .get_sid = _get_sid, | |
216 | .destroy = _destroy, | |
217 | }, | |
218 | .controllers = linked_list_create(), | |
219 | .filters = linked_list_create(), | |
220 | .context = context, | |
221 | ); | |
76a98ee2 MW |
222 | if (!create_sid(this)) |
223 | { | |
224 | destroy(this); | |
225 | return NULL; | |
226 | } | |
7daf5226 | 227 | |
965e99b5 MW |
228 | return &this->public; |
229 | } |