2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2008 Philip Boetschi, Adrian Doerig
4 * Hochschule fuer Technik Rapperswil
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>.
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
20 #include "user_controller.h"
24 typedef struct private_user_controller_t private_user_controller_t
;
27 * private data of the user_controller
29 struct private_user_controller_t
{
34 user_controller_t
public;
47 * minimum required password length
49 u_int password_length
;
53 * hash the password for database storage
55 static chunk_t
hash_password(char *login
, char *password
)
60 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
65 data
= chunk_cata("cc", chunk_create(login
, strlen(login
)),
66 chunk_create(password
, strlen(password
)));
67 if (!hasher
->allocate_hash(hasher
, data
, &hash
))
69 hasher
->destroy(hasher
);
72 hasher
->destroy(hasher
);
79 static void login(private_user_controller_t
*this, request_t
*request
)
81 if (request
->get_query_data(request
, "submit"))
83 char *login
, *password
;
85 login
= request
->get_query_data(request
, "login");
86 password
= request
->get_query_data(request
, "password");
88 if (login
&& password
)
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
);
100 query
->enumerate(query
, &id
);
101 query
->destroy(query
);
106 this->user
->set_user(this->user
, id
);
107 return request
->redirect(request
, "peer/list");
110 request
->setf(request
, "error=Invalid username or password.");
112 request
->render(request
, "templates/user/login.cs");
118 static void logout(private_user_controller_t
*this, request_t
*request
)
120 request
->redirect(request
, "user/login");
121 request
->close_session(request
);
125 * verify a user entered username for validity
127 static bool verify_login(private_user_controller_t
*this, request_t
*request
,
130 if (!login
|| *login
== '\0')
132 request
->setf(request
, "error=Username is missing.");
135 while (*login
!= '\0')
149 request
->setf(request
, "error=Username invalid, "
150 "valid characters: A-Z a-z 0-9 - _ @ .");
157 * verify a user entered password for validity
159 static bool verify_password(private_user_controller_t
*this, request_t
*request
,
160 char *password
, char *confirm
)
162 if (!password
|| *password
== '\0')
164 request
->setf(request
, "error=Password is missing.");
167 if (strlen(password
) < this->password_length
)
169 request
->setf(request
, "error=Password requires at least %d characters.",
170 this->password_length
);
173 if (!confirm
|| !streq(password
, confirm
))
175 request
->setf(request
, "error=Password not confirmed.");
184 static void add(private_user_controller_t
*this, request_t
*request
)
188 while (request
->get_query_data(request
, "register"))
190 char *password
, *confirm
;
194 login
= request
->get_query_data(request
, "new_login");
195 password
= request
->get_query_data(request
, "new_password");
196 confirm
= request
->get_query_data(request
, "confirm_password");
198 if (!verify_login(this, request
, login
) ||
199 !verify_password(this, request
, password
, confirm
))
204 hash
= hash_password(login
, password
);
205 if (!hash
.ptr
|| this->db
->execute(this->db
, &id
,
206 "INSERT INTO user (login, password) VALUES (?, ?)",
207 DB_TEXT
, login
, DB_BLOB
, hash
) < 0)
209 request
->setf(request
, "error=Username already exists.");
214 this->user
->set_user(this->user
, id
);
215 return request
->redirect(request
, "peer/list");
217 request
->set(request
, "new_login", login
);
218 request
->setf(request
, "password_length=%d", this->password_length
);
219 request
->render(request
, "templates/user/add.cs");
223 * Edit the logged in user
225 static void edit(private_user_controller_t
*this, request_t
*request
)
230 /* lookup old login */
231 query
= this->db
->query(this->db
, "SELECT login FROM user WHERE id = ?",
232 DB_INT
, this->user
->get_user(this->user
),
234 if (!query
|| !query
->enumerate(query
, &old_login
))
237 request
->close_session(request
);
238 return request
->redirect(request
, "user/login");
240 old_login
= strdupa(old_login
);
241 query
->destroy(query
);
244 if (request
->get_query_data(request
, "back"))
246 return request
->redirect(request
, "peer/list");
249 if (request
->get_query_data(request
, "delete"))
251 this->db
->execute(this->db
, NULL
, "DELETE FROM user WHERE id = ?",
252 DB_UINT
, this->user
->get_user(this->user
));
253 this->db
->execute(this->db
, NULL
,
254 "DELETE FROM peer WHERE user = ?",
255 DB_UINT
, this->user
->get_user(this->user
));
256 return logout(this, request
);
259 while (request
->get_query_data(request
, "save"))
261 char *new_login
, *old_pass
, *new_pass
, *confirm
;
262 chunk_t old_hash
, new_hash
;
264 new_login
= request
->get_query_data(request
, "old_login");
265 old_pass
= request
->get_query_data(request
, "old_password");
266 new_pass
= request
->get_query_data(request
, "new_password");
267 confirm
= request
->get_query_data(request
, "confirm_password");
269 if (!verify_login(this, request
, new_login
) ||
270 !verify_password(this, request
, new_pass
, confirm
))
272 old_login
= new_login
;
275 old_hash
= hash_password(old_login
, old_pass
);
276 new_hash
= hash_password(new_login
, new_pass
);
278 if (this->db
->execute(this->db
, NULL
,
279 "UPDATE user SET login = ?, password = ? "
280 "WHERE id = ? AND password = ?",
281 DB_TEXT
, new_login
, DB_BLOB
, new_hash
,
282 DB_UINT
, this->user
->get_user(this->user
), DB_BLOB
, old_hash
) <= 0)
286 old_login
= new_login
;
287 request
->setf(request
, "error=Password verification failed.");
292 return request
->redirect(request
, "peer/list");
294 /* on error/template rendering */
295 request
->set(request
, "old_login", old_login
);
296 request
->setf(request
, "password_length=%d", this->password_length
);
297 request
->render(request
, "templates/user/edit.cs");
300 METHOD(controller_t
, get_name
, char*,
301 private_user_controller_t
*this)
306 METHOD(controller_t
, handle
, void,
307 private_user_controller_t
*this, request_t
*request
, char *action
,
308 char *p2
, char *p3
, char *p4
, char *p5
)
312 if (streq(action
, "add"))
314 return add(this, request
);
316 if (streq(action
, "login"))
318 return login(this, request
);
320 else if (streq(action
, "logout"))
322 return logout(this, request
);
324 else if (streq(action
, "edit"))
326 return edit(this, request
);
328 else if (streq(action
, "help"))
330 return request
->render(request
, "templates/user/help.cs");
333 request
->redirect(request
, "user/login");
336 METHOD(controller_t
, destroy
, void,
337 private_user_controller_t
*this)
345 controller_t
*user_controller_create(user_t
*user
, database_t
*db
)
347 private_user_controller_t
*this;
352 .get_name
= _get_name
,
359 .password_length
= lib
->settings
->get_int(lib
->settings
,
360 "medsrv.password_length", 6),
363 return &this->public.controller
;