portal_user/src/portal_user.c

382 lines
10 KiB
C

#include <kore/kore.h>
#include <kore/http.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sqlite3.h>
#include <unistd.h>
#include "assets.h"
#include "sessions.h"
#include "sqlite_utils.h"
#include <pwd.h>
#define SESSION_LEN 30
#define DB_NAME "portal_user.db"
#if defined(__linux__)
#include <kore/seccomp.h>
#include <crypt.h>
KORE_SECCOMP_FILTER("sqlite3",
KORE_SYSCALL_ALLOW(newfstatat),
KORE_SYSCALL_ALLOW(pread64),
KORE_SYSCALL_ALLOW(pwrite64),
KORE_SYSCALL_ALLOW(fdatasync),
KORE_SYSCALL_ALLOW_ARG(write, 0, STDOUT_FILENO)
);
#endif
int init(int state);
int portal_user_load(struct http_request *);
int v_password_func(struct http_request *, char *);
int create_user(struct http_request *);
int v_session_validate(struct http_request *, char *);
int v_session_remove(struct http_request *);
int private_portal(struct http_request *);
hashtable_t *hashtable = NULL;
int
init(int state)
{
hashtable = ht_create( 65536 );
int err=0;
if( hashtable == NULL )
{
kore_log(LOG_ERR, "Can't create hastable sessions");
err = 1;
}
if ( access( DB_NAME, F_OK ) == 0 && err == 0 )
{ kore_log(LOG_NOTICE, "Execute check_db()");
err = check_db(DB_NAME);}
else
{
kore_log(LOG_NOTICE, "Create Sqlite Base");
err = init_db(DB_NAME);
}
if (err)
return (KORE_RESULT_ERROR);
else
return (KORE_RESULT_OK);
}
int
create_user(struct http_request *req)
{
struct kore_buf *b = NULL;
u_int8_t *d = NULL;
size_t len = 0;
char *salt = NULL, *cryptpwd = NULL;
char *zErrMsg = NULL;
char *user = NULL, *pwd = NULL, name[50];
sqlite3 *db = NULL;
char sql[512];
if (req->method == HTTP_METHOD_GET)
http_populate_get(req);
else if (req->method == HTTP_METHOD_POST)
http_populate_post(req);
b = kore_buf_alloc(asset_len_signup_html);
kore_buf_append(b, asset_signup_html, asset_len_signup_html);
if (req->method == HTTP_METHOD_GET) {
kore_buf_replace_string(b, "$msg$", "GO", 4);
http_response_header(req, "content-type", "text/html");
d = kore_buf_release(b, &len);
http_response(req, 200, d, len);
kore_free(d);
return (KORE_RESULT_OK);
}
if (req->method == HTTP_METHOD_POST)
{
int rc = sqlite3_open(DB_NAME, &db);
if (rc != SQLITE_OK) {
kore_log(LOG_ERR, "Cannot open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return (KORE_RESULT_ERROR);
}
#if defined(__linux__)
salt = crypt_gensalt("$2b$", 15, NULL, 0); //-> linux
#elif defined(__OpenBSD__)
salt = bcrypt_gensalt(15);
#endif
if (salt == NULL) {
kore_log(LOG_ERR, "crypt_gensalt");
exit(EXIT_FAILURE);
}
kore_log(LOG_NOTICE, "bcrypt_salt réussi");
(void)snprintf(name, sizeof(name), "login");
http_argument_get_string(req, name, &user);
(void)snprintf(name, sizeof(name), "password");
http_argument_get_string(req, name, &pwd);
cryptpwd = crypt(pwd, salt);
if (cryptpwd == NULL) {
kore_log(LOG_PERROR, "Can't encrypt password");
exit(EXIT_FAILURE);
}
kore_log(LOG_NOTICE, "Encrypted called %s", cryptpwd );
(void)sprintf(sql,
"INSERT INTO Users (Email, Password, Active) VALUES(\"%s\",\"%s\",\"yes\");",
user, cryptpwd);
printf ( "%s",sql);
rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
if( rc != SQLITE_OK ){
kore_log(LOG_ERR, "SQL error: %s", zErrMsg);
sqlite3_free(zErrMsg);
} else {
kore_log(LOG_NOTICE, "Database successfully created !");
}
sqlite3_close(db);
http_response_header(req, "location", "/");
http_response_header(req, "content-type", "text/html");
d = kore_buf_release(b, &len);
http_response(req, HTTP_STATUS_FOUND, NULL, 0);
kore_free(d);
return (KORE_RESULT_OK);
}
return (KORE_RESULT_ERROR);
}
int
portal_user_load(struct http_request *req)
{
struct kore_buf *b = NULL;
u_int8_t *d = NULL;
size_t len = 0;
char *login = NULL, *pwd = NULL, name[70];
char *err_msg = 0;
char salt[29], *cryptpwd = NULL;
int rc = 0;
sqlite3_stmt *res= NULL;
sqlite3 *db = NULL;
char *cookie_session = NULL;
char *cookie_samesite = NULL;
char *cookie = NULL;
char *session_id = NULL;
if (req->method == HTTP_METHOD_GET)
http_populate_get(req);
else if (req->method == HTTP_METHOD_POST)
http_populate_post(req);
b = kore_buf_alloc(asset_len_index_html);
kore_buf_append(b, asset_index_html, asset_len_index_html);
if (req->method == HTTP_METHOD_GET) {
kore_buf_replace_string(b, "$login$", NULL, 0);
kore_buf_replace_string(b, "$password$", NULL, 0);
kore_buf_replace_string(b, "$msg$", "Toto", 4);
http_response_header(req, "content-type", "text/html");
d = kore_buf_release(b, &len);
http_response(req, 200, d, len);
kore_free(d);
return (KORE_RESULT_OK);
}
if (req->method == HTTP_METHOD_POST)
{
rc = sqlite3_open(DB_NAME, &db);
if (rc != SQLITE_OK)
{
kore_log(LOG_ERR, "Cannot open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return (KORE_RESULT_ERROR);
}
char *sql = "SELECT Email, Password FROM Users WHERE Email = ?";
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
if (rc == SQLITE_OK)
{
(void)snprintf(name, sizeof(name), "login");
http_argument_get_string(req, name, &login);
sqlite3_bind_text(res, 1, login , -1, NULL);
}
else
{
kore_log(LOG_ERR, "Failed to execute statement: %s\n", sqlite3_errmsg(db));
}
sqlite3_step(res);
if (rc != SQLITE_OK ) {
kore_log(LOG_ERR, "SQL error: %s\n", err_msg);
sqlite3_finalize(res);
sqlite3_free(err_msg);
sqlite3_close(db);
return (KORE_RESULT_ERROR);
}
(void)snprintf(name, sizeof(name), "password");
http_argument_get_string(req, name, &pwd);
strncpy (salt,(const char *)sqlite3_column_text(res, 1),29);
cryptpwd = crypt(pwd, salt);
if (cryptpwd == NULL) {
kore_log(LOG_PERROR, "Can't encrypt password");
exit(EXIT_FAILURE);
}
if ( strcmp( (const char *)sqlite3_column_text(res, 1), cryptpwd) )
{
kore_buf_replace_string(b, "$msg$", "Erreur de login ou mot de passe ", 17);
}
else
{
kore_log(LOG_NOTICE, "on va faire le set cookie");
session_id = gen_session_id(SESSION_LEN);
ht_set(hashtable, session_id, login);
kore_log(LOG_NOTICE, "on a ajouté le sessions dans la hastable");
cookie_session = set_cookie_header("session_id", '=', session_id);
cookie_samesite = set_cookie_header("SameSite", '=', "Strict");
cookie = set_cookie_header(cookie_session, ';', cookie_samesite);
kore_log(LOG_NOTICE, "on a set le cookie dans les headers");
kore_buf_replace_string(b, "$msg$", "BRAVO !!!", 13);
free(session_id);
free(cookie_session);
free(cookie_samesite);
kore_log(LOG_NOTICE, "set cookie OK");
}
sqlite3_finalize(res);
sqlite3_close(db);
http_response_header(req, "content-type", "text/html");
if (cookie != NULL)
{
http_response_header(req, "set-cookie", cookie);
free(cookie);
}
d = kore_buf_release(b, &len);
http_response_header(req, "location", "/portal/bienvenue");
http_response(req, HTTP_STATUS_FOUND, NULL, 0);
kore_free(d);
return (KORE_RESULT_OK);
}
return (KORE_RESULT_ERROR);
}
int
v_password_func(struct http_request *req, char *data)
{
kore_log(LOG_NOTICE, "v_password_func called %s", data);
if ( strlen(data) < 128 )
return (KORE_RESULT_OK);
return (KORE_RESULT_ERROR);
}
int
v_session_remove (struct http_request *req)
{
char *buffer;
http_populate_cookies(req);
if (http_request_cookie(req, "session_id", &buffer))
kore_log(LOG_DEBUG, "Got session_id: %s", buffer);
if (ht_get(hashtable, buffer) != NULL)
ht_delete(hashtable, buffer);
http_response_header(req, "location", "/");
http_response_header(req, "content-type", "text/html");
http_response_header(req, "set-cookie", "session_id=""");
http_response(req, HTTP_STATUS_FOUND, NULL, 0);
return (KORE_RESULT_OK);
}
int
v_session_validate(struct http_request *req, char *data)
{
kore_log(LOG_NOTICE, "v_session_validate: %s", data);
if ( ht_get(hashtable, data) != NULL )
return (KORE_RESULT_OK);
else
{
kore_log(LOG_NOTICE, "Session Inexistante");
}
return (KORE_RESULT_ERROR);
}
int
private_portal(struct http_request *req)
{
struct kore_buf *b = NULL;
u_int8_t *d = NULL;
size_t len = 0;
char *buffer =NULL ;
session_t *account = NULL;
if (req->method == HTTP_METHOD_GET)
http_populate_get(req);
http_populate_cookies(req);
if (http_request_cookie(req, "session_id", &buffer))
kore_log(LOG_DEBUG, "Got session_id: %s", buffer);
b = kore_buf_alloc(asset_len_signup_html);
kore_buf_append(b, asset_private_html, asset_len_private_html);
account = ht_get(hashtable, buffer);
if (req->method == HTTP_METHOD_GET) {
kore_buf_replace_string(b, "$msg$", "GO", 4);
if (account != NULL)
{
kore_log(LOG_NOTICE, "account trouvé: %s", account->user);
kore_buf_replace_string(b, "$login$", account->user, sizeof(account->user)+1);
}
http_response_header(req, "content-type", "text/html");
d = kore_buf_release(b, &len);
http_response(req, 200, d, len);
kore_free(d);
}
return (KORE_RESULT_OK);
}