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 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <openssl/sha.h>
34 #if defined(__sun) && defined(__SunOS_5_10)
35 #include <sha2.h>
36 #define SHA256_Init SHA256Init
37 #define SHA256_Update SHA256Update
38 #define SHA256_Final SHA256Final
39 #endif
40
41 #include "../util/atomic.h"
42 #include "../util/util.h"
43
44 #include <cx/hash_map.h>
45
46 #include "keyfile_auth.h"
47
48 Keyfile* keyfile_new(CxAllocator *a) {
49 Keyfile *keyfile = cxCalloc(a,
1,
sizeof(Keyfile));
50 if(!keyfile) {
51 return NULL;
52 }
53 keyfile->authdb.get_user = keyfile_get_user;
54 keyfile->authdb.use_cache =
0;
55 keyfile->users = cxHashMapCreate(a,
CX_STORE_POINTERS,
16);
56 return keyfile;
57 }
58
59 int keyfile_add_user(
60 Keyfile *keyfile,
61 cxmutstr name,
62 enum KeyfileHashType hash_type,
63 cxmutstr hash,
64 cxmutstr *groups,
65 size_t ngroups)
66 {
67 const CxAllocator *a = keyfile->users->allocator;
68
69 if(hash.length <
12) {
70
71
72 return -
1;
73 }
74
75 KeyfileUser *user = cxMalloc(a,
sizeof(KeyfileUser));
76 user->user.name = cx_strdup_a(a, cx_strcast(name)).ptr;
77 user->user.uid = -
1;
78 user->user.gid = -
1;
79 user->user.verify_password = keyfile_user_verify_password;
80 user->user.check_group = keyfile_user_check_group;
81 user->user.free = keyfile_user_free;
82
83 user->hash_type = hash_type;
84 user->hash = cxMalloc(a, hash.length +
1);
85
86 if(!user->user.name || !user->hash) {
87 return -
1;
88 }
89
90 user->hashlen = util_base64decode(hash.ptr, hash.length, user->hash);
91
92 if(ngroups >
0) {
93 user->groups = cxCalloc(a, ngroups,
sizeof(cxmutstr));
94 if(!user->groups) {
95 return -
1;
96 }
97 for(
int i=
0;i<ngroups;i++) {
98 user->groups[i] = cx_strdup_a(a, cx_strcast(groups[i]));
99 }
100
101 }
else {
102 user->groups =
NULL;
103 }
104
105
106 return cxMapPut(keyfile->users, cx_hash_key(name.ptr, name.length), user);
107 }
108
109
110
111 User* keyfile_get_user(AuthDB *db, Session *sn, Request *rq,
const char *user) {
112 Keyfile *keyfile = (Keyfile*)db;
113 return cxMapGet(keyfile->users, cx_hash_key_str(user));
114 }
115
116 int keyfile_user_verify_password(User *user,
const char *password) {
117 KeyfileUser *usr = (KeyfileUser*)user;
118 return ssha_verify(usr, password);
119 }
120
121 int keyfile_user_check_group(User *user,
const char *group) {
122 KeyfileUser *usr = (KeyfileUser*)user;
123 cxstring grp = cx_str(group);
124 for(
int i=
0;i<usr->numgroups;i++) {
125 if(!cx_strcmp(cx_strcast(usr->groups[i]), grp)) {
126 return 1;
127 }
128 }
129 return 0;
130 }
131
132 void keyfile_user_free(User *user) {
133
134 }
135
136
137 int ssha_verify(KeyfileUser *user,
const char *password) {
138
139
140
141
142
143 size_t hlen;
144 switch(user->hash_type) {
145 case KEYFILE_SSHA: hlen =
20;
break;
146 case KEYFILE_SSHA256: hlen =
32;
break;
147 case KEYFILE_SSHA512: hlen =
64;
break;
148 }
149
150 char *salt = user->hash + hlen;
151 size_t saltlen = user->hashlen - hlen;
152
153 size_t pwlen = strlen(password);
154
155 unsigned char pwhash[
64];
156 switch(user->hash_type) {
157 case KEYFILE_SSHA: {
158 SHA_CTX ctx;
159 SHA1_Init(&ctx);
160 SHA1_Update(&ctx, password, pwlen);
161 SHA1_Update(&ctx, salt, saltlen);
162 SHA1_Final(pwhash, &ctx);
163 break;
164 }
165 case KEYFILE_SSHA256: {
166 SHA256_CTX ctx;
167 SHA256_Init(&ctx);
168 SHA256_Update(&ctx, password, pwlen);
169 SHA256_Update(&ctx, salt, saltlen);
170 SHA256_Final(pwhash, &ctx);
171 break;
172 }
173 case KEYFILE_SSHA512: {
174 SHA512_CTX ctx;
175 SHA512_Init(&ctx);
176 SHA512_Update(&ctx, password, pwlen);
177 SHA512_Update(&ctx, salt, saltlen);
178 SHA512_Final(pwhash, &ctx);
179 break;
180 }
181 }
182
183 if(!memcmp(user->hash, pwhash, hlen)) {
184 return 1;
185 }
else {
186 return 0;
187 }
188 }
189
190