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