Annotation of embedaddon/strongswan/src/medsrv/controller/user_controller.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008 Martin Willi
3: * Copyright (C) 2008 Philip Boetschi, Adrian Doerig
4: * HSR Hochschule fuer Technik Rapperswil
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: #include <string.h>
19:
20: #include "user_controller.h"
21:
22: #include <library.h>
23:
24: typedef struct private_user_controller_t private_user_controller_t;
25:
26: /**
27: * private data of the user_controller
28: */
29: struct private_user_controller_t {
30:
31: /**
32: * public functions
33: */
34: user_controller_t public;
35:
36: /**
37: * database connection
38: */
39: database_t *db;
40:
41: /**
42: * user session
43: */
44: user_t *user;
45:
46: /**
47: * minimum required password length
48: */
49: u_int password_length;
50: };
51:
52: /**
53: * hash the password for database storage
54: */
55: static chunk_t hash_password(char *login, char *password)
56: {
57: hasher_t *hasher;
58: chunk_t hash, data;
59:
60: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
61: if (!hasher)
62: {
63: return chunk_empty;
64: }
65: data = chunk_cata("cc", chunk_create(login, strlen(login)),
66: chunk_create(password, strlen(password)));
67: if (!hasher->allocate_hash(hasher, data, &hash))
68: {
69: hasher->destroy(hasher);
70: return chunk_empty;
71: }
72: hasher->destroy(hasher);
73: return hash;
74: }
75:
76: /**
77: * Login a user.
78: */
79: static void login(private_user_controller_t *this, fast_request_t *request)
80: {
81: if (request->get_query_data(request, "submit"))
82: {
83: char *login, *password;
84:
85: login = request->get_query_data(request, "login");
86: password = request->get_query_data(request, "password");
87:
88: if (login && password)
89: {
90: enumerator_t *query;
91: u_int id = 0;
92: chunk_t hash;
93:
94: hash = hash_password(login, password);
95: query = this->db->query(this->db,
96: "SELECT id FROM user WHERE login = ? AND password = ?",
97: DB_TEXT, login, DB_BLOB, hash, DB_UINT);
98: if (query)
99: {
100: query->enumerate(query, &id);
101: query->destroy(query);
102: }
103: free(hash.ptr);
104: if (id)
105: {
106: this->user->set_user(this->user, id);
107: return request->redirect(request, "peer/list");
108: }
109: }
110: request->setf(request, "error=Invalid username or password.");
111: }
112: request->render(request, "templates/user/login.cs");
113: }
114:
115: /**
116: * Logout a user.
117: */
118: static void logout(private_user_controller_t *this, fast_request_t *request)
119: {
120: request->redirect(request, "user/login");
121: request->close_session(request);
122: }
123:
124: /**
125: * verify a user entered username for validity
126: */
127: static bool verify_login(private_user_controller_t *this,
128: fast_request_t *request, char *login)
129: {
130: if (!login || *login == '\0')
131: {
132: request->setf(request, "error=Username is missing.");
133: return FALSE;
134: }
135: while (*login != '\0')
136: {
137: switch (*login)
138: {
139: case 'a' ... 'z':
140: case 'A' ... 'Z':
141: case '0' ... '9':
142: case '-':
143: case '_':
144: case '@':
145: case '.':
146: login++;
147: continue;
148: default:
149: request->setf(request, "error=Username invalid, "
150: "valid characters: A-Z a-z 0-9 - _ @ .");
151: }
152: }
153: return TRUE;
154: }
155:
156: /**
157: * verify a user entered password for validity
158: */
159: static bool verify_password(private_user_controller_t *this,
160: fast_request_t *request,
161: char *password, char *confirm)
162: {
163: if (!password || *password == '\0')
164: {
165: request->setf(request, "error=Password is missing.");
166: return FALSE;
167: }
168: if (strlen(password) < this->password_length)
169: {
170: request->setf(request, "error=Password requires at least %d characters.",
171: this->password_length);
172: return FALSE;
173: }
174: if (!confirm || !streq(password, confirm))
175: {
176: request->setf(request, "error=Password not confirmed.");
177: return FALSE;
178: }
179: return TRUE;
180: }
181:
182: /**
183: * Register a user.
184: */
185: static void add(private_user_controller_t *this, fast_request_t *request)
186: {
187: char *login = "";
188:
189: while (request->get_query_data(request, "register"))
190: {
191: char *password, *confirm;
192: chunk_t hash;
193: u_int id;
194:
195: login = request->get_query_data(request, "new_login");
196: password = request->get_query_data(request, "new_password");
197: confirm = request->get_query_data(request, "confirm_password");
198:
199: if (!verify_login(this, request, login) ||
200: !verify_password(this, request, password, confirm))
201: {
202: break;
203: }
204:
205: hash = hash_password(login, password);
206: if (!hash.ptr || this->db->execute(this->db, &id,
207: "INSERT INTO user (login, password) VALUES (?, ?)",
208: DB_TEXT, login, DB_BLOB, hash) < 0)
209: {
210: request->setf(request, "error=Username already exists.");
211: free(hash.ptr);
212: break;
213: }
214: free(hash.ptr);
215: this->user->set_user(this->user, id);
216: return request->redirect(request, "peer/list");
217: }
218: request->set(request, "new_login", login);
219: request->setf(request, "password_length=%d", this->password_length);
220: request->render(request, "templates/user/add.cs");
221: }
222:
223: /**
224: * Edit the logged in user
225: */
226: static void edit(private_user_controller_t *this, fast_request_t *request)
227: {
228: enumerator_t *query;
229: char *old_login;
230:
231: /* lookup old login */
232: query = this->db->query(this->db, "SELECT login FROM user WHERE id = ?",
233: DB_INT, this->user->get_user(this->user),
234: DB_TEXT);
235: if (!query || !query->enumerate(query, &old_login))
236: {
237: DESTROY_IF(query);
238: request->close_session(request);
239: return request->redirect(request, "user/login");
240: }
241: old_login = strdupa(old_login);
242: query->destroy(query);
243:
244: /* back pressed */
245: if (request->get_query_data(request, "back"))
246: {
247: return request->redirect(request, "peer/list");
248: }
249: /* delete pressed */
250: if (request->get_query_data(request, "delete"))
251: {
252: this->db->execute(this->db, NULL, "DELETE FROM user WHERE id = ?",
253: DB_UINT, this->user->get_user(this->user));
254: this->db->execute(this->db, NULL,
255: "DELETE FROM peer WHERE user = ?",
256: DB_UINT, this->user->get_user(this->user));
257: return logout(this, request);
258: }
259: /* save pressed */
260: while (request->get_query_data(request, "save"))
261: {
262: char *new_login, *old_pass, *new_pass, *confirm;
263: chunk_t old_hash, new_hash;
264:
265: new_login = request->get_query_data(request, "old_login");
266: old_pass = request->get_query_data(request, "old_password");
267: new_pass = request->get_query_data(request, "new_password");
268: confirm = request->get_query_data(request, "confirm_password");
269:
270: if (!verify_login(this, request, new_login) ||
271: !verify_password(this, request, new_pass, confirm))
272: {
273: old_login = new_login;
274: break;
275: }
276: old_hash = hash_password(old_login, old_pass);
277: new_hash = hash_password(new_login, new_pass);
278:
279: if (this->db->execute(this->db, NULL,
280: "UPDATE user SET login = ?, password = ? "
281: "WHERE id = ? AND password = ?",
282: DB_TEXT, new_login, DB_BLOB, new_hash,
283: DB_UINT, this->user->get_user(this->user), DB_BLOB, old_hash) <= 0)
284: {
285: free(new_hash.ptr);
286: free(old_hash.ptr);
287: old_login = new_login;
288: request->setf(request, "error=Password verification failed.");
289: break;
290: }
291: free(new_hash.ptr);
292: free(old_hash.ptr);
293: return request->redirect(request, "peer/list");
294: }
295: /* on error/template rendering */
296: request->set(request, "old_login", old_login);
297: request->setf(request, "password_length=%d", this->password_length);
298: request->render(request, "templates/user/edit.cs");
299: }
300:
301: METHOD(fast_controller_t, get_name, char*,
302: private_user_controller_t *this)
303: {
304: return "user";
305: }
306:
307: METHOD(fast_controller_t, handle, void,
308: private_user_controller_t *this, fast_request_t *request, char *action,
309: char *p2, char *p3, char *p4, char *p5)
310: {
311: if (action)
312: {
313: if (streq(action, "add"))
314: {
315: return add(this, request);
316: }
317: if (streq(action, "login"))
318: {
319: return login(this, request);
320: }
321: else if (streq(action, "logout"))
322: {
323: return logout(this, request);
324: }
325: else if (streq(action, "edit"))
326: {
327: return edit(this, request);
328: }
329: else if (streq(action, "help"))
330: {
331: return request->render(request, "templates/user/help.cs");
332: }
333: }
334: request->redirect(request, "user/login");
335: }
336:
337: METHOD(fast_controller_t, destroy, void,
338: private_user_controller_t *this)
339: {
340: free(this);
341: }
342:
343: /*
344: * see header file
345: */
346: fast_controller_t *user_controller_create(user_t *user, database_t *db)
347: {
348: private_user_controller_t *this;
349:
350: INIT(this,
351: .public = {
352: .controller = {
353: .get_name = _get_name,
354: .handle = _handle,
355: .destroy = _destroy,
356: },
357: },
358: .user = user,
359: .db = db,
360: .password_length = lib->settings->get_int(lib->settings,
361: "medsrv.password_length", 6),
362: );
363:
364: return &this->public.controller;
365: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>