Browse Source

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

release0.1.5
Georg Hopp 12 years ago
parent
commit
70c5edfde9
  1. 3
      include/application/application.h
  2. 1
      include/auth.h
  3. 49
      include/auth/storage.h
  4. 11
      include/storage.h
  5. 74
      src/application/adapter/http/update.c
  6. 12
      src/application/application.c
  7. 78
      src/application/signup.c
  8. 103
      src/auth/storage/hash_pw.c
  9. 53
      src/auth/storage/signup.c
  10. 95
      src/auth/storage/storage.c
  11. 23
      src/storage/put.c
  12. 50
      src/storage/update.c
  13. 5
      src/user/save.c
  14. 19
      src/utils/hash.c

3
include/application/application.h

@ -31,6 +31,7 @@
#include "auth/credential.h"
#include "storage.h"
#include "session.h"
#include "user.h"
struct randval {
@ -48,9 +49,11 @@ CLASS(Application) {
struct randval * val;
Storage users;
Storage passwords;
};
int applicationLogin(Application, Credential, Session);
int applicationSignup(Application, Credential, User, Session);
Session applicationSessionStart(Application);
Session applicationSessionGet(Application, const char *);

1
include/auth.h

@ -25,6 +25,7 @@
#include "auth/auth.h"
#include "auth/ldap.h"
#include "auth/storage.h"
#include "auth/credential.h"
#include "auth/interface/auth.h"

49
include/auth/storage.h

@ -0,0 +1,49 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AUTH_STORAGE_H__
#define __AUTH_STORAGE_H__
#include <sys/types.h>
#include <openssl/sha.h>
#include "class.h"
#define SALT_SIZE 32
#define HASH_SIZE SHA512_DIGEST_LENGTH
CLASS(AuthStorage) {
Storage store;
};
/*
* @TODO In future this should use a more general purpose hash
* function, which then will be in utils/hash.c
*/
int hash_pw(const char *, const size_t, unsigned char *, unsigned char **);
#endif // __AUTH_STORAGE_H__
// vim: set ts=4 sw=4:

11
include/storage.h

@ -29,12 +29,21 @@
#include "class.h"
typedef enum e_StoragePutResults {
SPR_OK = 0,
SPR_READ_ONLY = 1,
SPR_EXISTS = 2,
SPR_UNKNOWN = -1
} StoragePutResult;
CLASS(Storage) {
GDBM_FILE gdbm;
char * db_name;
};
void storagePut(Storage, char *, size_t, char *, size_t);
StoragePutResult storagePut(Storage, char *, size_t, char *, size_t);
StoragePutResult storageUpdate(Storage, char *, size_t, char *, size_t);
void storageGet(Storage, char *, size_t, char **, size_t *);
#endif // __STORAGE_H__

74
src/application/adapter/http/update.c

@ -35,6 +35,7 @@
#include "http/header.h"
#include "http/response.h"
#include "auth/credential.h"
#include "user.h"
#include "utils/memory.h"
@ -121,7 +122,6 @@ getSession(Queue sess_queue, const char * sid)
return sess;
}
static
void
loginAdapter(Application application, HttpWorker worker, Session session)
@ -159,6 +159,73 @@ loginAdapter(Application application, HttpWorker worker, Session session)
delete(credential);
}
static
void
signupAdapter(Application application, HttpWorker worker, Session session)
{
HashValue email;
HashValue password;
HashValue pwrepeat;
HashValue firstname;
HashValue surname;
Credential credential;
User user;
email = hashGet(
worker->current_request->post,
CSTRA("email"));
password = hashGet(
worker->current_request->post,
CSTRA("password"));
pwrepeat = hashGet(
worker->current_request->post,
CSTRA("pwrepeat"));
firstname = hashGet(
worker->current_request->post,
CSTRA("firstname"));
surname = hashGet(
worker->current_request->post,
CSTRA("surname"));
if (
NULL == email ||
NULL == password ||
NULL == pwrepeat ||
NULL == firstname ||
NULL == surname) {
// maybe this is not a 500...have to check repsonse codes.
worker->current_response = httpResponse500();
return;
}
if (password->nvalue != pwrepeat->nvalue ||
0 != memcmp(password->value, pwrepeat->value, password->nvalue)) {
// maybe this is not a 500...have to check repsonse codes.
worker->current_response = httpResponse500();
return;
}
credential = new(Credential,
CRED_PASSWORD,
(char *)(email->value), email->nvalue,
(char *)(password->value), password->nvalue);
user = new(User,
(char *)(email->value), email->nvalue,
(char *)(firstname->value), firstname->nvalue,
(char *)(surname->value), surname->nvalue);
if (! applicationSignup(application, credential, user, session)) {
worker->current_response = httpResonse500();
} else {
loginAdapter(application, worker, session);
}
delete(credential);
}
void
applicationAdapterHttpUpdate(void * _this, void * subject)
{
@ -190,6 +257,11 @@ applicationAdapterHttpUpdate(void * _this, void * subject)
loginAdapter(this->application, worker, session);
return;
}
if (0 == strcmp("/signup/", worker->current_request->path)) {
signupAdapter(this->application, worker, session);
return;
}
}
if (0 == strcmp("GET", worker->current_request->method)) {

12
src/application/application.c

@ -49,7 +49,15 @@ applicationCtor(void * _this, va_list * params)
this->active_sessions = new(Queue);
this->users = new(Storage, "./run/users.db");
/*
* @TODO for both of these...each user should be identified
* by a number...that way I could use that number in the
* passwords db and no direct association between email and
* password could be made when someone get the hands on the
* password database.
*/
this->users = new(Storage, "./run/users.db");
this->passwords = new(Storage, "./run/passwords.db")
return 0;
}
@ -61,6 +69,8 @@ applicationDtor(void * _this)
Application this = _this;
size_t i;
delete(this->passwords);
delete(this->users);
delete(this->active_sessions);
for (i=0; i<this->nauth; i++) {

78
src/application/signup.c

@ -0,0 +1,78 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "class.h"
#include "auth.h"
#include "user.h"
#include "application/application.h"
#include "utils/memory.h"
int
applicationSignup(
Application this,
Credential credential,
User user,
Session session)
{
unsigned char hash[SALT_SIZE+HASH_SIZE];
if (NULL != userLoad(user, this->users)) {
/*
* if any user is found with this email return false
* as on signup equal email adresses are not allowed
* at all.
*/
return 0;
}
userSave(user, this->users);
if (FALSE == hash_pw(
CRED_PWD(cred).pass,
CRED_PWD(cred).npass,
&hash,
&(hash+SALT_SIZE))) {
/*
* @TODO if we come here we have to delete the previously saved
* user again...
*/
return 0;
}
storagePut(
this->passwords,
CRED_PWD(cred).user,
CRED_PWD(cred).nuser,
hash,
SALT_SIZE + HASH_SIZE);
return 0;
}
// vim: set ts=4 sw=4:

103
src/auth/storage/hash_pw.c

@ -0,0 +1,103 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include "class.h"
#include "storage.h"
#include "utils/memory.h"
/*
* I have to hash the passwords, maybe this will move in
* a separate class in future, but now everything is done
* here
*/
#define PBKDF2_ITERATIONS 2048
/*
* base64 decode via openssl...
* I do not need this i think, but I keep it...maybe I have
* use for it later.
*
#include <openssl/bio.h>
#include <openssl/evp.h>
#define B64_SALT "q36MilkD6Ezlt6+G394aPYWrSwAdEhdnK8k="
BIO_METHOD * BIO_f_base64(void);
void
base64decode(char * data) {
BIO * bio,
* b64;
FILE * b64_salt = fmemopen(B64_SALT, sizeof(B64_SALT)-1, "r");
b64 = BIO_new(BIO_f_base64());
bio = BIO_new_fp(b64_salt, BIO_NOCLOSE);
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
if (SALT_SIZE != BIO_read(bio, data, SALT_SIZE)) {
return -1;
}
BIO_free_all(bio);
fclose(b64_salt);
}
*/
int
hash_pw(
const char * password,
const size_t npassword,
unsigned char * hash,
unsigned char ** salt)
{
if (NULL == *salt) {
*salt = memMalloc(SALT_SIZE * sizeof(unsigned char));
if (0 > RAND_pseudo_bytes(unsigned char *buf, int num)) {
MEM_FREE(*salt);
return FALSE;
}
}
if (0 == PKCS5_PBKDF2_HMAC(
password,
npassword,
*salt,
SALT_SIZE,
PBKDF2_ITERATIONS,
EVP_sha512(),
HASH_SIZE,
hash)) {
MEM_FREE(*salt);
return FALSE;
}
return TRUE;
}
// vim: set ts=4 sw=4:

53
src/auth/storage/signup.c

@ -0,0 +1,53 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include "class.h"
#include "storage.h"
#include "auth/storage.h"
#include "auth/credential.h"
int
authStorageSignup(AuthStorage this, Credential cred)
{
unsigned char hash[SALT_SIZE+HASH_SIZE];
if (FALSE == hash_pw(
CRED_PWD(cred).pass,
CRED_PWD(cred).npass,
&hash,
&(hash+SALT_SIZE))) {
return 0;
}
storagePut(
this->store,
CRED_PWD(cred).user,
CRED_PWD(cred).nuser,
hash,
SALT_SIZE + HASH_SIZE);
return 1;
}
// vim: set ts=4 sw=4:

95
src/auth/storage/storage.c

@ -0,0 +1,95 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "class.h"
#include "storage.h"
#include "auth/storage.h"
#include "auth/credential.h"
#include "commons.h"
static
int
authStorageCtor(void * _this, va_list * params)
{
AuthStorage this = _this;
this->store = va_arg(*params, Storage);
return 0;
}
static
void
authStorageDtor(void * _this)
{
}
static
int
authStorageAuthenticate(void * _this, Credential cred)
{
AuthStorage this = _this;
unsigned char current_hash[HASH_SIZE];
unsigned char * found_hash = NULL;
size_t nfound_hash = 0;
if (CRED_PASSWORD != cred->type) {
return FALSE;
}
storageGet(
this->store,
CRED_PWD(cred).user,
CRED_PWD(cred).nuser,
&found_hash,
&nfound_hash);
if (NULL == found_hash || (SALT_SIZE + HASH_SIZE) != nfound_hash) {
/* user not found or found hash is invalid */
return FALSE;
}
/* found_hash <=> salt+hash */
if (FALSE == hash_pw(
CRED_PWD(cred).pass,
CRED_PWD(cred).npass,
current_hash,
&found_hash)) {
MEM_FREE(found_hash);
return FALSE;
}
if (0 != memcmp(current_hash, found_hash+SALT_SIZE, HASH_SIZE)) {
MEM_FREE(found_hash);
return FALSE;
}
MEM_FREE(found_hash);
return TRUE;
}
INIT_IFACE(Class, authStorageCtor, authStorageDtor, NULL);
INIT_IFACE(Auth, authStorageAuthenticate);
CREATE_CLASS(AuthLdap, NULL, IFACE(Class), IFACE(Auth));
// vim: set ts=4 sw=4:

23
src/storage/put.c

@ -29,13 +29,32 @@
#include "utils/memory.h"
void
typedef enum e_StoragePutResults {
SPR_OK = 0,
SPR_READ_ONLY = 1,
SPR_EXISTS = 2,
SPR_UNKNOWN = -1
} StoragePutResult;
StoragePutResult
storagePut(Storage this, char * _key, size_t nkey, char * data, size_t ndata)
{
datum key = {_key, nkey};
datum value = {data, ndata};
gdbm_store(this->gdbm, key, value, GDBM_REPLACE);
switch (gdbm_store(this->gdbm, key, value, GDBM_INSERT)) {
case 0:
return SPR_OK;
case 1:
return SPR_EXISTS;
case -1:
return SPR_READ_ONLY;
default:
return SPR_UNKNOWN;
}
return SPR_UNKNOWN;
}
// vim: set ts=4 sw=4:

50
src/storage/update.c

@ -0,0 +1,50 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gdbm.h>
#include <string.h>
#include <sys/types.h>
#include "storage.h"
#include "class.h"
#include "utils/memory.h"
StoragePutResult
storagePut(Storage this, char * _key, size_t nkey, char * data, size_t ndata)
{
datum key = {_key, nkey};
datum value = {data, ndata};
switch (gdbm_store(this->gdbm, key, value, GDBM_REPLACE)) {
case 0:
return SPR_OK;
case -1:
return SPR_READ_ONLY;
default:
return SPR_UNKNOWN;
}
return SPR_UNKNOWN;
}
// vim: set ts=4 sw=4:

5
src/user/save.c

@ -39,7 +39,10 @@ userSave(User this, Storage storage)
*this->nsurname + 1 +
3 * sizeof(size_t);
storagePut(
/*
* @TODO user return value for error handling
*/
storageUpdate(
storage,
this->email, *this->nemail,
this->email, storage_size);

19
src/utils/hash.c

@ -24,6 +24,8 @@
#include <ctype.h>
#include <sys/types.h>
#include <openssl/rand.h>
#include "utils/hash.h"
/**
@ -50,4 +52,21 @@ sdbm(const unsigned char * str, size_t len)
return hash;
}
/*
* this will use openssl to hash a given password with a given salt.
* If salt is NULL a random salt is generated and returned in salt.
* The memory for this is allocated via memMalloc and has to be freed
* by the caller via MEM_FREE.
* The size of the salt is always SALT_SIZE and that of hash is always
* hash size. Both are defined in auth/storage.h
*/
int
hash_pw(
const char * password,
const size_t npassword,
unsigned char * pw_hash,
unsigned char ** salt)
{
}
// vim: set ts=4 sw=4:
Loading…
Cancel
Save