Annotation of embedaddon/strongswan/src/medsrv/controller/user_controller.c, revision 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>