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>