1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bcrypt.h"
#define USER_DATABASE "./user.db"
#define SECURITY_LEVEL 12
#define SEP '|'
#define MAX_LINE_LENGTH 256
static bool
valid_char(int chr)
{
return isalnum(chr) || chr == '_' || chr == '-' || chr == '.';
}
/**
* Create a new user/password
*
* \param[in] username
* \param[in] password
*
* \return true on success (user was created) or false on error
*/
bool
create_user(const char *username, const char *password) // NOLINT
{
// check for invalid characters in username
for ( const char *ptr = username; *ptr; ++ptr ) {
if ( !valid_char(*ptr) ) {
return false;
}
}
FILE *database = fopen(USER_DATABASE, "at");
if ( database == NULL ) {
return false;
}
char hash[_PASSWORD_LEN + 1] = { 0 };
if ( bcrypt_newhash(password, SECURITY_LEVEL, hash, _PASSWORD_LEN) != 0 ) {
return false;
}
(void) fprintf(database, "%s%c%s\n", username, SEP, hash);
(void) fclose(database);
return true;
}
/**
* Check is a valid username/password exists in the user-database
*
* username A username
* password A strong password
*
* @return true, if the user was successfully authenticated, otherwise false
*/
bool
check_user(const char *const username, const char *const password) // NOLINT
{
FILE *database = fopen(USER_DATABASE, "rt");
if ( database == NULL ) {
return false;
}
const size_t username_length = strlen(username);
char line[MAX_LINE_LENGTH];
bool user_authenticated = false;
while ( !user_authenticated && fgets(line, sizeof line, database) != NULL ) {
line[strcspn(line, "\r\n")] = '\0'; // remove newline (if exists)
if ( strncmp(line, username, username_length) != 0 ) {
continue;
}
if ( line[username_length] != SEP ) {
continue;
}
if ( bcrypt_checkpass(password, &line[username_length + 1]) != 0 ) {
continue;
}
user_authenticated = true;
}
(void) fclose(database);
return user_authenticated;
}
/**
* Check if a valid username already exists in the user-database
*
* \param[in] username to be checked
*
* \return true, if the user was successfully authenticated, otherwise false
*/
bool
check_user_if_exists(const char *username)
{
FILE *database = fopen(USER_DATABASE, "rt");
if ( database == NULL ) {
return false;
}
const size_t username_length = strlen(username);
char line[MAX_LINE_LENGTH];
bool user_found = false;
while ( !user_found && fgets(line, sizeof line, database) != NULL ) {
line[strcspn(line, "\r\n")] = '\0'; // remove newline (if exists)
if ( strncmp(line, username, username_length) != 0 ) {
continue;
}
if ( line[username_length] != SEP ) {
continue;
}
user_found = true;
}
(void) fclose(database);
return user_found;
}
int
main(void)
{
if ( check_user("Thomas", "Passwort") ) {
puts("Benutzer erfolgreich überprüft!");
}
return EXIT_SUCCESS;
}
|