Commit 70c5edfde9d673fa8150542bbca6be7a1ed6730e

Authored by Georg Hopp
1 parent 19c59fd0

put most of the parts for simple signup/login in place...not tested now as it is…

… late. Hopefully tomorrow I find the time to setup a small testform and bring this whole thing finally to work. refs #36
... ... @@ -31,6 +31,7 @@
31 31 #include "auth/credential.h"
32 32 #include "storage.h"
33 33 #include "session.h"
  34 +#include "user.h"
34 35
35 36
36 37 struct randval {
... ... @@ -48,9 +49,11 @@ CLASS(Application) {
48 49 struct randval * val;
49 50
50 51 Storage users;
  52 + Storage passwords;
51 53 };
52 54
53 55 int applicationLogin(Application, Credential, Session);
  56 +int applicationSignup(Application, Credential, User, Session);
54 57
55 58 Session applicationSessionStart(Application);
56 59 Session applicationSessionGet(Application, const char *);
... ...
... ... @@ -25,6 +25,7 @@
25 25
26 26 #include "auth/auth.h"
27 27 #include "auth/ldap.h"
  28 +#include "auth/storage.h"
28 29 #include "auth/credential.h"
29 30 #include "auth/interface/auth.h"
30 31
... ...
  1 +/**
  2 + * \file
  3 + *
  4 + * \author Georg Hopp
  5 + *
  6 + * \copyright
  7 + * Copyright © 2012 Georg Hopp
  8 + *
  9 + * This program is free software: you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License as published by
  11 + * the Free Software Foundation, either version 3 of the License, or
  12 + * (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21 + */
  22 +
  23 +#ifndef __AUTH_STORAGE_H__
  24 +#define __AUTH_STORAGE_H__
  25 +
  26 +#include <sys/types.h>
  27 +
  28 +#include <openssl/sha.h>
  29 +
  30 +#include "class.h"
  31 +
  32 +
  33 +#define SALT_SIZE 32
  34 +#define HASH_SIZE SHA512_DIGEST_LENGTH
  35 +
  36 +
  37 +CLASS(AuthStorage) {
  38 + Storage store;
  39 +};
  40 +
  41 +/*
  42 + * @TODO In future this should use a more general purpose hash
  43 + * function, which then will be in utils/hash.c
  44 + */
  45 +int hash_pw(const char *, const size_t, unsigned char *, unsigned char **);
  46 +
  47 +#endif // __AUTH_STORAGE_H__
  48 +
  49 +// vim: set ts=4 sw=4:
... ...
... ... @@ -29,12 +29,21 @@
29 29 #include "class.h"
30 30
31 31
  32 +typedef enum e_StoragePutResults {
  33 + SPR_OK = 0,
  34 + SPR_READ_ONLY = 1,
  35 + SPR_EXISTS = 2,
  36 + SPR_UNKNOWN = -1
  37 +} StoragePutResult;
  38 +
  39 +
32 40 CLASS(Storage) {
33 41 GDBM_FILE gdbm;
34 42 char * db_name;
35 43 };
36 44
37   -void storagePut(Storage, char *, size_t, char *, size_t);
  45 +StoragePutResult storagePut(Storage, char *, size_t, char *, size_t);
  46 +StoragePutResult storageUpdate(Storage, char *, size_t, char *, size_t);
38 47 void storageGet(Storage, char *, size_t, char **, size_t *);
39 48
40 49 #endif // __STORAGE_H__
... ...
... ... @@ -35,6 +35,7 @@
35 35 #include "http/header.h"
36 36 #include "http/response.h"
37 37 #include "auth/credential.h"
  38 +#include "user.h"
38 39
39 40 #include "utils/memory.h"
40 41
... ... @@ -121,7 +122,6 @@ getSession(Queue sess_queue, const char * sid)
121 122 return sess;
122 123 }
123 124
124   -
125 125 static
126 126 void
127 127 loginAdapter(Application application, HttpWorker worker, Session session)
... ... @@ -159,6 +159,73 @@ loginAdapter(Application application, HttpWorker worker, Session session)
159 159 delete(credential);
160 160 }
161 161
  162 +static
  163 +void
  164 +signupAdapter(Application application, HttpWorker worker, Session session)
  165 +{
  166 + HashValue email;
  167 + HashValue password;
  168 + HashValue pwrepeat;
  169 + HashValue firstname;
  170 + HashValue surname;
  171 +
  172 + Credential credential;
  173 + User user;
  174 +
  175 + email = hashGet(
  176 + worker->current_request->post,
  177 + CSTRA("email"));
  178 + password = hashGet(
  179 + worker->current_request->post,
  180 + CSTRA("password"));
  181 + pwrepeat = hashGet(
  182 + worker->current_request->post,
  183 + CSTRA("pwrepeat"));
  184 + firstname = hashGet(
  185 + worker->current_request->post,
  186 + CSTRA("firstname"));
  187 + surname = hashGet(
  188 + worker->current_request->post,
  189 + CSTRA("surname"));
  190 +
  191 + if (
  192 + NULL == email ||
  193 + NULL == password ||
  194 + NULL == pwrepeat ||
  195 + NULL == firstname ||
  196 + NULL == surname) {
  197 + // maybe this is not a 500...have to check repsonse codes.
  198 + worker->current_response = httpResponse500();
  199 + return;
  200 + }
  201 +
  202 + if (password->nvalue != pwrepeat->nvalue ||
  203 + 0 != memcmp(password->value, pwrepeat->value, password->nvalue)) {
  204 + // maybe this is not a 500...have to check repsonse codes.
  205 + worker->current_response = httpResponse500();
  206 + return;
  207 + }
  208 +
  209 + credential = new(Credential,
  210 + CRED_PASSWORD,
  211 + (char *)(email->value), email->nvalue,
  212 + (char *)(password->value), password->nvalue);
  213 +
  214 + user = new(User,
  215 + (char *)(email->value), email->nvalue,
  216 + (char *)(firstname->value), firstname->nvalue,
  217 + (char *)(surname->value), surname->nvalue);
  218 +
  219 + if (! applicationSignup(application, credential, user, session)) {
  220 + worker->current_response = httpResonse500();
  221 + } else {
  222 + loginAdapter(application, worker, session);
  223 + }
  224 +
  225 + delete(credential);
  226 +}
  227 +
  228 +
162 229 void
163 230 applicationAdapterHttpUpdate(void * _this, void * subject)
164 231 {
... ... @@ -190,6 +257,11 @@ applicationAdapterHttpUpdate(void * _this, void * subject)
190 257 loginAdapter(this->application, worker, session);
191 258 return;
192 259 }
  260 +
  261 + if (0 == strcmp("/signup/", worker->current_request->path)) {
  262 + signupAdapter(this->application, worker, session);
  263 + return;
  264 + }
193 265 }
194 266
195 267 if (0 == strcmp("GET", worker->current_request->method)) {
... ...
... ... @@ -49,7 +49,15 @@ applicationCtor(void * _this, va_list * params)
49 49
50 50 this->active_sessions = new(Queue);
51 51
52   - this->users = new(Storage, "./run/users.db");
  52 + /*
  53 + * @TODO for both of these...each user should be identified
  54 + * by a number...that way I could use that number in the
  55 + * passwords db and no direct association between email and
  56 + * password could be made when someone get the hands on the
  57 + * password database.
  58 + */
  59 + this->users = new(Storage, "./run/users.db");
  60 + this->passwords = new(Storage, "./run/passwords.db")
53 61
54 62 return 0;
55 63 }
... ... @@ -61,6 +69,8 @@ applicationDtor(void * _this)
61 69 Application this = _this;
62 70 size_t i;
63 71
  72 + delete(this->passwords);
  73 + delete(this->users);
64 74 delete(this->active_sessions);
65 75
66 76 for (i=0; i<this->nauth; i++) {
... ...
  1 +/**
  2 + * \file
  3 + *
  4 + * \author Georg Hopp
  5 + *
  6 + * \copyright
  7 + * Copyright © 2012 Georg Hopp
  8 + *
  9 + * This program is free software: you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License as published by
  11 + * the Free Software Foundation, either version 3 of the License, or
  12 + * (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21 + */
  22 +
  23 +#define _GNU_SOURCE
  24 +
  25 +#include <stdio.h>
  26 +#include <stdlib.h>
  27 +#include <sys/types.h>
  28 +
  29 +#include "class.h"
  30 +#include "auth.h"
  31 +#include "user.h"
  32 +#include "application/application.h"
  33 +
  34 +#include "utils/memory.h"
  35 +
  36 +int
  37 +applicationSignup(
  38 + Application this,
  39 + Credential credential,
  40 + User user,
  41 + Session session)
  42 +{
  43 + unsigned char hash[SALT_SIZE+HASH_SIZE];
  44 +
  45 + if (NULL != userLoad(user, this->users)) {
  46 + /*
  47 + * if any user is found with this email return false
  48 + * as on signup equal email adresses are not allowed
  49 + * at all.
  50 + */
  51 + return 0;
  52 + }
  53 +
  54 + userSave(user, this->users);
  55 +
  56 + if (FALSE == hash_pw(
  57 + CRED_PWD(cred).pass,
  58 + CRED_PWD(cred).npass,
  59 + &hash,
  60 + &(hash+SALT_SIZE))) {
  61 + /*
  62 + * @TODO if we come here we have to delete the previously saved
  63 + * user again...
  64 + */
  65 + return 0;
  66 + }
  67 +
  68 + storagePut(
  69 + this->passwords,
  70 + CRED_PWD(cred).user,
  71 + CRED_PWD(cred).nuser,
  72 + hash,
  73 + SALT_SIZE + HASH_SIZE);
  74 +
  75 + return 0;
  76 +}
  77 +
  78 +// vim: set ts=4 sw=4:
... ...
  1 +/**
  2 + * \file
  3 + *
  4 + * \author Georg Hopp
  5 + *
  6 + * \copyright
  7 + * Copyright © 2012 Georg Hopp
  8 + *
  9 + * This program is free software: you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License as published by
  11 + * the Free Software Foundation, either version 3 of the License, or
  12 + * (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21 + */
  22 +
  23 +#include <sys/types.h>
  24 +
  25 +#include <openssl/evp.h>
  26 +#include <openssl/rand.h>
  27 +
  28 +#include "class.h"
  29 +#include "storage.h"
  30 +#include "utils/memory.h"
  31 +
  32 +/*
  33 + * I have to hash the passwords, maybe this will move in
  34 + * a separate class in future, but now everything is done
  35 + * here
  36 + */
  37 +#define PBKDF2_ITERATIONS 2048
  38 +
  39 +/*
  40 + * base64 decode via openssl...
  41 + * I do not need this i think, but I keep it...maybe I have
  42 + * use for it later.
  43 + *
  44 +#include <openssl/bio.h>
  45 +#include <openssl/evp.h>
  46 +
  47 +#define B64_SALT "q36MilkD6Ezlt6+G394aPYWrSwAdEhdnK8k="
  48 +
  49 +BIO_METHOD * BIO_f_base64(void);
  50 +
  51 +void
  52 +base64decode(char * data) {
  53 + BIO * bio,
  54 + * b64;
  55 + FILE * b64_salt = fmemopen(B64_SALT, sizeof(B64_SALT)-1, "r");
  56 +
  57 + b64 = BIO_new(BIO_f_base64());
  58 + bio = BIO_new_fp(b64_salt, BIO_NOCLOSE);
  59 + bio = BIO_push(b64, bio);
  60 +
  61 + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
  62 +
  63 + if (SALT_SIZE != BIO_read(bio, data, SALT_SIZE)) {
  64 + return -1;
  65 + }
  66 +
  67 + BIO_free_all(bio);
  68 + fclose(b64_salt);
  69 +}
  70 +*/
  71 +
  72 +int
  73 +hash_pw(
  74 + const char * password,
  75 + const size_t npassword,
  76 + unsigned char * hash,
  77 + unsigned char ** salt)
  78 +{
  79 + if (NULL == *salt) {
  80 + *salt = memMalloc(SALT_SIZE * sizeof(unsigned char));
  81 + if (0 > RAND_pseudo_bytes(unsigned char *buf, int num)) {
  82 + MEM_FREE(*salt);
  83 + return FALSE;
  84 + }
  85 + }
  86 +
  87 + if (0 == PKCS5_PBKDF2_HMAC(
  88 + password,
  89 + npassword,
  90 + *salt,
  91 + SALT_SIZE,
  92 + PBKDF2_ITERATIONS,
  93 + EVP_sha512(),
  94 + HASH_SIZE,
  95 + hash)) {
  96 + MEM_FREE(*salt);
  97 + return FALSE;
  98 + }
  99 +
  100 + return TRUE;
  101 +}
  102 +
  103 +// vim: set ts=4 sw=4:
... ...
  1 +/**
  2 + * \file
  3 + *
  4 + * \author Georg Hopp
  5 + *
  6 + * \copyright
  7 + * Copyright © 2012 Georg Hopp
  8 + *
  9 + * This program is free software: you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License as published by
  11 + * the Free Software Foundation, either version 3 of the License, or
  12 + * (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21 + */
  22 +
  23 +#include <sys/types.h>
  24 +
  25 +#include "class.h"
  26 +#include "storage.h"
  27 +#include "auth/storage.h"
  28 +#include "auth/credential.h"
  29 +
  30 +int
  31 +authStorageSignup(AuthStorage this, Credential cred)
  32 +{
  33 + unsigned char hash[SALT_SIZE+HASH_SIZE];
  34 +
  35 + if (FALSE == hash_pw(
  36 + CRED_PWD(cred).pass,
  37 + CRED_PWD(cred).npass,
  38 + &hash,
  39 + &(hash+SALT_SIZE))) {
  40 + return 0;
  41 + }
  42 +
  43 + storagePut(
  44 + this->store,
  45 + CRED_PWD(cred).user,
  46 + CRED_PWD(cred).nuser,
  47 + hash,
  48 + SALT_SIZE + HASH_SIZE);
  49 +
  50 + return 1;
  51 +}
  52 +
  53 +// vim: set ts=4 sw=4:
... ...
  1 +/**
  2 + * \file
  3 + *
  4 + * \author Georg Hopp
  5 + *
  6 + * \copyright
  7 + * Copyright © 2012 Georg Hopp
  8 + *
  9 + * This program is free software: you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License as published by
  11 + * the Free Software Foundation, either version 3 of the License, or
  12 + * (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21 + */
  22 +
  23 +#include "class.h"
  24 +#include "storage.h"
  25 +#include "auth/storage.h"
  26 +#include "auth/credential.h"
  27 +#include "commons.h"
  28 +
  29 +static
  30 +int
  31 +authStorageCtor(void * _this, va_list * params)
  32 +{
  33 + AuthStorage this = _this;
  34 +
  35 + this->store = va_arg(*params, Storage);
  36 +
  37 + return 0;
  38 +}
  39 +
  40 +static
  41 +void
  42 +authStorageDtor(void * _this)
  43 +{
  44 +}
  45 +
  46 +static
  47 +int
  48 +authStorageAuthenticate(void * _this, Credential cred)
  49 +{
  50 + AuthStorage this = _this;
  51 +
  52 + unsigned char current_hash[HASH_SIZE];
  53 + unsigned char * found_hash = NULL;
  54 + size_t nfound_hash = 0;
  55 +
  56 + if (CRED_PASSWORD != cred->type) {
  57 + return FALSE;
  58 + }
  59 +
  60 + storageGet(
  61 + this->store,
  62 + CRED_PWD(cred).user,
  63 + CRED_PWD(cred).nuser,
  64 + &found_hash,
  65 + &nfound_hash);
  66 +
  67 + if (NULL == found_hash || (SALT_SIZE + HASH_SIZE) != nfound_hash) {
  68 + /* user not found or found hash is invalid */
  69 + return FALSE;
  70 + }
  71 +
  72 + /* found_hash <=> salt+hash */
  73 + if (FALSE == hash_pw(
  74 + CRED_PWD(cred).pass,
  75 + CRED_PWD(cred).npass,
  76 + current_hash,
  77 + &found_hash)) {
  78 + MEM_FREE(found_hash);
  79 + return FALSE;
  80 + }
  81 +
  82 + if (0 != memcmp(current_hash, found_hash+SALT_SIZE, HASH_SIZE)) {
  83 + MEM_FREE(found_hash);
  84 + return FALSE;
  85 + }
  86 +
  87 + MEM_FREE(found_hash);
  88 + return TRUE;
  89 +}
  90 +
  91 +INIT_IFACE(Class, authStorageCtor, authStorageDtor, NULL);
  92 +INIT_IFACE(Auth, authStorageAuthenticate);
  93 +CREATE_CLASS(AuthLdap, NULL, IFACE(Class), IFACE(Auth));
  94 +
  95 +// vim: set ts=4 sw=4:
... ...
... ... @@ -29,13 +29,32 @@
29 29
30 30 #include "utils/memory.h"
31 31
32   -void
  32 +typedef enum e_StoragePutResults {
  33 + SPR_OK = 0,
  34 + SPR_READ_ONLY = 1,
  35 + SPR_EXISTS = 2,
  36 + SPR_UNKNOWN = -1
  37 +} StoragePutResult;
  38 +
  39 +
  40 +StoragePutResult
33 41 storagePut(Storage this, char * _key, size_t nkey, char * data, size_t ndata)
34 42 {
35 43 datum key = {_key, nkey};
36 44 datum value = {data, ndata};
37 45
38   - gdbm_store(this->gdbm, key, value, GDBM_REPLACE);
  46 + switch (gdbm_store(this->gdbm, key, value, GDBM_INSERT)) {
  47 + case 0:
  48 + return SPR_OK;
  49 + case 1:
  50 + return SPR_EXISTS;
  51 + case -1:
  52 + return SPR_READ_ONLY;
  53 + default:
  54 + return SPR_UNKNOWN;
  55 + }
  56 +
  57 + return SPR_UNKNOWN;
39 58 }
40 59
41 60 // vim: set ts=4 sw=4:
... ...
  1 +/**
  2 + * \file
  3 + *
  4 + * \author Georg Hopp
  5 + *
  6 + * \copyright
  7 + * Copyright © 2012 Georg Hopp
  8 + *
  9 + * This program is free software: you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License as published by
  11 + * the Free Software Foundation, either version 3 of the License, or
  12 + * (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21 + */
  22 +
  23 +#include <gdbm.h>
  24 +#include <string.h>
  25 +#include <sys/types.h>
  26 +
  27 +#include "storage.h"
  28 +#include "class.h"
  29 +
  30 +#include "utils/memory.h"
  31 +
  32 +StoragePutResult
  33 +storagePut(Storage this, char * _key, size_t nkey, char * data, size_t ndata)
  34 +{
  35 + datum key = {_key, nkey};
  36 + datum value = {data, ndata};
  37 +
  38 + switch (gdbm_store(this->gdbm, key, value, GDBM_REPLACE)) {
  39 + case 0:
  40 + return SPR_OK;
  41 + case -1:
  42 + return SPR_READ_ONLY;
  43 + default:
  44 + return SPR_UNKNOWN;
  45 + }
  46 +
  47 + return SPR_UNKNOWN;
  48 +}
  49 +
  50 +// vim: set ts=4 sw=4:
... ...
... ... @@ -39,7 +39,10 @@ userSave(User this, Storage storage)
39 39 *this->nsurname + 1 +
40 40 3 * sizeof(size_t);
41 41
42   - storagePut(
  42 + /*
  43 + * @TODO user return value for error handling
  44 + */
  45 + storageUpdate(
43 46 storage,
44 47 this->email, *this->nemail,
45 48 this->email, storage_size);
... ...
... ... @@ -24,6 +24,8 @@
24 24 #include <ctype.h>
25 25 #include <sys/types.h>
26 26
  27 +#include <openssl/rand.h>
  28 +
27 29 #include "utils/hash.h"
28 30
29 31 /**
... ... @@ -50,4 +52,21 @@ sdbm(const unsigned char * str, size_t len)
50 52 return hash;
51 53 }
52 54
  55 +
  56 +/*
  57 + * this will use openssl to hash a given password with a given salt.
  58 + * If salt is NULL a random salt is generated and returned in salt.
  59 + * The memory for this is allocated via memMalloc and has to be freed
  60 + * by the caller via MEM_FREE.
  61 + * The size of the salt is always SALT_SIZE and that of hash is always
  62 + * hash size. Both are defined in auth/storage.h
  63 + */
  64 +int
  65 +hash_pw(
  66 + const char * password,
  67 + const size_t npassword,
  68 + unsigned char * pw_hash,
  69 + unsigned char ** salt)
  70 +{
  71 +}
53 72 // vim: set ts=4 sw=4:
... ...
Please register or login to post a comment