refactored PA-TNC message handling by IMVs
[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 bool create_sid(private_session_t *this)
82 {
83 char buf[COOKIE_LEN];
84 rng_t *rng;
85
86 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
87 if (!rng)
88 {
89 return FALSE;
90 }
91 if (!rng->get_bytes(rng, sizeof(buf), buf))
92 {
93 rng->destroy(rng);
94 return FALSE;
95 }
96 rng->destroy(rng);
97 chunk_to_hex(chunk_create(buf, sizeof(buf)), this->sid, FALSE);
98 return TRUE;
99 }
100
101 /**
102 * run all registered filters
103 */
104 static bool run_filter(private_session_t *this, request_t *request, char *p0,
105 char *p1, char *p2, char *p3, char *p4, char *p5)
106 {
107 enumerator_t *enumerator;
108 filter_t *filter;
109
110 enumerator = this->filters->create_enumerator(this->filters);
111 while (enumerator->enumerate(enumerator, &filter))
112 {
113 if (!filter->run(filter, request, p0, p1, p2, p3, p4, p5))
114 {
115 enumerator->destroy(enumerator);
116 return FALSE;
117 }
118 }
119 enumerator->destroy(enumerator);
120 return TRUE;
121 }
122
123 METHOD(session_t, process, void,
124 private_session_t *this, request_t *request)
125 {
126 char *pos, *start, *param[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
127 enumerator_t *enumerator;
128 bool handled = FALSE;
129 controller_t *current;
130 int i = 0;
131
132 if (!this->cookie_sent)
133 {
134 request->add_cookie(request, "SID", this->sid);
135 this->cookie_sent = TRUE;
136 }
137
138 start = request->get_path(request);
139 if (start)
140 {
141 if (*start == '/')
142 {
143 start++;
144 }
145 while ((pos = strchr(start, '/')) != NULL && i < 5)
146 {
147 param[i++] = strndupa(start, pos - start);
148 start = pos + 1;
149 }
150 param[i] = strdupa(start);
151
152 if (run_filter(this, request, param[0], param[1], param[2], param[3],
153 param[4], param[5]))
154 {
155 enumerator = this->controllers->create_enumerator(this->controllers);
156 while (enumerator->enumerate(enumerator, &current))
157 {
158 if (streq(current->get_name(current), param[0]))
159 {
160 current->handle(current, request, param[1], param[2],
161 param[3], param[4], param[5]);
162 handled = TRUE;
163 break;
164 }
165 }
166 enumerator->destroy(enumerator);
167 }
168 else
169 {
170 handled = TRUE;
171 }
172 }
173 if (!handled)
174 {
175 if (this->controllers->get_first(this->controllers,
176 (void**)&current) == SUCCESS)
177 {
178 request->streamf(request,
179 "Status: 301 Moved permanently\nLocation: %s/%s\n\n",
180 request->get_base(request), current->get_name(current));
181 }
182 }
183 }
184
185 METHOD(session_t, get_sid, char*,
186 private_session_t *this)
187 {
188 return this->sid;
189 }
190
191 METHOD(session_t, destroy, void,
192 private_session_t *this)
193 {
194 this->controllers->destroy_offset(this->controllers, offsetof(controller_t, destroy));
195 this->filters->destroy_offset(this->filters, offsetof(filter_t, destroy));
196 DESTROY_IF(this->context);
197 free(this);
198 }
199
200 /*
201 * see header file
202 */
203 session_t *session_create(context_t *context)
204 {
205 private_session_t *this;
206
207 INIT(this,
208 .public = {
209 .add_controller = _add_controller,
210 .add_filter = _add_filter,
211 .process = _process,
212 .get_sid = _get_sid,
213 .destroy = _destroy,
214 },
215 .controllers = linked_list_create(),
216 .filters = linked_list_create(),
217 .context = context,
218 );
219 if (!create_sid(this))
220 {
221 destroy(this);
222 return NULL;
223 }
224
225 return &this->public;
226 }
227