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 lenght
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 hasher
->allocate_hash(hasher
, data
, &hash
);
68 hasher
->destroy(hasher
);
75 static void login(private_user_controller_t
*this, request_t
*request
)
77 if (request
->get_query_data(request
, "submit"))
79 char *login
, *password
;
81 login
= request
->get_query_data(request
, "login");
82 password
= request
->get_query_data(request
, "password");
84 if (login
&& password
)
90 hash
= hash_password(login
, password
);
91 query
= this->db
->query(this->db
,
92 "SELECT id FROM user WHERE login = ? AND password = ?",
93 DB_TEXT
, login
, DB_BLOB
, hash
, DB_UINT
);
96 query
->enumerate(query
, &id
);
97 query
->destroy(query
);
102 this->user
->set_user(this->user
, id
);
103 return request
->redirect(request
, "peer/list");
106 request
->setf(request
, "error=Invalid username or password.");
108 request
->render(request
, "templates/user/login.cs");
114 static void logout(private_user_controller_t
*this, request_t
*request
)
116 request
->redirect(request
, "user/login");
117 request
->close_session(request
);
121 * verify a user entered username for validity
123 static bool verify_login(private_user_controller_t
*this, request_t
*request
,
126 if (!login
|| *login
== '\0')
128 request
->setf(request
, "error=Username is missing.");
131 while (*login
!= '\0')
145 request
->setf(request
, "error=Username invalid, "
146 "valid characters: A-Z a-z 0-9 - _ @ .");
153 * verify a user entered password for validity
155 static bool verify_password(private_user_controller_t
*this, request_t
*request
,
156 char *password
, char *confirm
)
158 if (!password
|| *password
== '\0')
160 request
->setf(request
, "error=Password is missing.");
163 if (strlen(password
) < this->password_length
)
165 request
->setf(request
, "error=Password requires at least %d characters.",
166 this->password_length
);
169 if (!confirm
|| !streq(password
, confirm
))
171 request
->setf(request
, "error=Password not confirmed.");
180 static void add(private_user_controller_t
*this, request_t
*request
)
184 while (request
->get_query_data(request
, "register"))
186 char *password
, *confirm
;
190 login
= request
->get_query_data(request
, "new_login");
191 password
= request
->get_query_data(request
, "new_password");
192 confirm
= request
->get_query_data(request
, "confirm_password");
194 if (!verify_login(this, request
, login
) ||
195 !verify_password(this, request
, password
, confirm
))
200 hash
= hash_password(login
, password
);
201 if (!hash
.ptr
|| this->db
->execute(this->db
, &id
,
202 "INSERT INTO user (login, password) VALUES (?, ?)",
203 DB_TEXT
, login
, DB_BLOB
, hash
) < 0)
205 request
->setf(request
, "error=Username already exists.");
210 this->user
->set_user(this->user
, id
);
211 return request
->redirect(request
, "peer/list");
213 request
->set(request
, "new_login", login
);
214 request
->setf(request
, "password_length=%d", this->password_length
);
215 request
->render(request
, "templates/user/add.cs");
219 * Edit the logged in user
221 static void edit(private_user_controller_t
*this, request_t
*request
)
226 /* lookup old login */
227 query
= this->db
->query(this->db
, "SELECT login FROM user WHERE id = ?",
228 DB_INT
, this->user
->get_user(this->user
),
230 if (!query
|| !query
->enumerate(query
, &old_login
))
233 request
->close_session(request
);
234 return request
->redirect(request
, "user/login");
236 old_login
= strdupa(old_login
);
237 query
->destroy(query
);
240 if (request
->get_query_data(request
, "back"))
242 return request
->redirect(request
, "peer/list");
245 if (request
->get_query_data(request
, "delete"))
247 this->db
->execute(this->db
, NULL
, "DELETE FROM user WHERE id = ?",
248 DB_UINT
, this->user
->get_user(this->user
));
249 this->db
->execute(this->db
, NULL
,
250 "DELETE FROM peer WHERE user = ?",
251 DB_UINT
, this->user
->get_user(this->user
));
252 return logout(this, request
);
255 while (request
->get_query_data(request
, "save"))
257 char *new_login
, *old_pass
, *new_pass
, *confirm
;
258 chunk_t old_hash
, new_hash
;
260 new_login
= request
->get_query_data(request
, "old_login");
261 old_pass
= request
->get_query_data(request
, "old_password");
262 new_pass
= request
->get_query_data(request
, "new_password");
263 confirm
= request
->get_query_data(request
, "confirm_password");
265 if (!verify_login(this, request
, new_login
) ||
266 !verify_password(this, request
, new_pass
, confirm
))
268 old_login
= new_login
;
271 old_hash
= hash_password(old_login
, old_pass
);
272 new_hash
= hash_password(new_login
, new_pass
);
274 if (this->db
->execute(this->db
, NULL
,
275 "UPDATE user SET login = ?, password = ? "
276 "WHERE id = ? AND password = ?",
277 DB_TEXT
, new_login
, DB_BLOB
, new_hash
,
278 DB_UINT
, this->user
->get_user(this->user
), DB_BLOB
, old_hash
) <= 0)
282 old_login
= new_login
;
283 request
->setf(request
, "error=Password verification failed.");
288 return request
->redirect(request
, "peer/list");
290 /* on error/template rendering */
291 request
->set(request
, "old_login", old_login
);
292 request
->setf(request
, "password_length=%d", this->password_length
);
293 request
->render(request
, "templates/user/edit.cs");
297 * Implementation of controller_t.get_name
299 static char* get_name(private_user_controller_t
*this)
305 * Implementation of controller_t.handle
307 static void handle(private_user_controller_t
*this, request_t
*request
, char *action
)
311 if (streq(action
, "add"))
313 return add(this, request
);
315 if (streq(action
, "login"))
317 return login(this, request
);
319 else if (streq(action
, "logout"))
321 return logout(this, request
);
323 else if (streq(action
, "edit"))
325 return edit(this, request
);
327 else if (streq(action
, "help"))
329 return request
->render(request
, "templates/user/help.cs");
332 request
->redirect(request
, "user/login");
336 * Implementation of controller_t.destroy
338 static void destroy(private_user_controller_t
*this)
346 controller_t
*user_controller_create(user_t
*user
, database_t
*db
)
348 private_user_controller_t
*this= malloc_thing(private_user_controller_t
);
350 this->public.controller
.get_name
= (char*(*)(controller_t
*))get_name
;
351 this->public.controller
.handle
= (void(*)(controller_t
*, request_t
*, char*, char*, char*, char*, char*))handle
;
352 this->public.controller
.destroy
= (void(*)(controller_t
*))destroy
;
356 this->password_length
= lib
->settings
->get_int(lib
->settings
,
357 "medsrv.password_length", 6);
359 return &this->public.controller
;