52 ucx_buffer_free(buf); |
52 ucx_buffer_free(buf); |
53 return NULL; |
53 return NULL; |
54 } |
54 } |
55 |
55 |
56 PwdStore *p = malloc(sizeof(PwdStore)); |
56 PwdStore *p = malloc(sizeof(PwdStore)); |
57 p->pwds = ucx_map_new(16); |
57 p->ids = ucx_map_new(16); |
|
58 p->locations = NULL; |
58 p->content = buf; |
59 p->content = buf; |
59 p->key = NULL; |
60 p->key = NULL; |
|
61 p->encoffset = PWDS_HEADER_SIZE; |
60 p->isdecrypted = 0; |
62 p->isdecrypted = 0; |
|
63 |
|
64 if(pwdstore_getindex(p)) { |
|
65 pwdstore_free(p); |
|
66 return NULL; |
|
67 } |
61 |
68 |
62 return p; |
69 return p; |
63 } |
70 } |
64 |
71 |
65 PwdStore* pwdstore_new(void) { |
72 PwdStore* pwdstore_new(void) { |
66 PwdStore *p = calloc(1, sizeof(PwdStore)); |
73 PwdStore *p = calloc(1, sizeof(PwdStore)); |
67 p->pwds = ucx_map_new(16); |
74 p->ids = ucx_map_new(16); |
68 p->content = ucx_buffer_new(NULL, PWDS_HEADER_SIZE, UCX_BUFFER_AUTOEXTEND); |
75 p->content = ucx_buffer_new(NULL, PWDS_HEADER_SIZE, UCX_BUFFER_AUTOEXTEND); |
69 PWDS_MAGIC(p) = PWDS_MAGIC_CHAR; |
76 PWDS_MAGIC(p) = PWDS_MAGIC_CHAR; |
70 PWDS_VERSION(p) = 1; |
77 PWDS_VERSION(p) = 1; |
71 PWDS_ENC(p) = DAV_KEY_AES256; |
78 PWDS_ENC(p) = DAV_KEY_AES256; |
72 PWDS_PWFUNC(p) = DAV_PWFUNC_PBKDF2_SHA256; |
79 PWDS_PWFUNC(p) = DAV_PWFUNC_PBKDF2_SHA256; |
73 dav_rand_bytes(p->content->space+4, 16); |
80 dav_rand_bytes(p->content->space+4, 16); |
74 return p; |
81 return p; |
75 } |
82 } |
76 |
83 |
77 static int read_pwdentry(PwdStore *p, UcxBuffer *in) { |
84 static int readval(UcxBuffer *in, char **val, int allowzero) { |
|
85 *val = NULL; |
|
86 uint32_t length = 0; |
|
87 if(ucx_buffer_read(&length, 1, sizeof(uint32_t), in) != sizeof(uint32_t)) { |
|
88 return 0; |
|
89 } |
|
90 length = ntohl(length); |
|
91 if((length == 0 && !allowzero) || length > PWDSTORE_MAX_LEN) { |
|
92 return 0; |
|
93 } |
|
94 |
|
95 char *value = malloc(length + 1); |
|
96 value[length] = 0; |
|
97 if(ucx_buffer_read(value, 1, length, in) != length) { |
|
98 free(value); |
|
99 return 0; |
|
100 } |
|
101 |
|
102 *val = value; |
|
103 return 1; |
|
104 } |
|
105 |
|
106 static int read_pwdentry(PwdStore *p, UcxBuffer *in, int index) { |
78 int type = ucx_buffer_getc(in); |
107 int type = ucx_buffer_getc(in); |
79 if(type == EOF || type != 0) { |
108 if(type == EOF || type != 0) { |
80 // only type 0 supported yet |
109 // only type 0 supported yet |
81 return 0; |
110 return 0; |
82 } |
111 } |
83 |
112 |
84 uint32_t ulen = 0; |
113 char *id = NULL; |
85 uint32_t plen = 0; |
114 char *location = NULL; |
86 |
115 char *user = NULL; |
87 if(ucx_buffer_read(&ulen, 1, sizeof(uint32_t), in) != sizeof(uint32_t)) { |
116 char *password = NULL; |
88 return 0; |
117 |
89 } |
118 int res = 0; |
90 ulen = ntohl(ulen); |
119 if((res += readval(in, &id, FALSE)) == 1) { |
91 if(ulen == 0 || ulen > PWDSTORE_MAX_LEN) { |
120 if((res += readval(in, &location, TRUE)) == 2) { |
92 return 0; |
121 if((res += readval(in, &user, FALSE)) == 3) { |
93 } |
122 res += readval(in, &password, FALSE); |
94 |
123 } |
95 char *user = malloc(ulen+1); |
124 } |
96 user[ulen] = 0; |
125 } |
97 if(ucx_buffer_read(user, 1, ulen, in) != ulen) { |
126 |
98 free(user); |
127 int ret = 0; |
99 return 0; |
128 if((!index && res == 4) || (index && res == 2)) { |
100 } |
129 pwdstore_put(p, id, location, user, password); |
101 |
130 ret = 1; |
102 if(ucx_buffer_read(&plen, 1, sizeof(uint32_t), in) != sizeof(uint32_t)) { |
131 } |
103 return 0; |
132 |
104 } |
133 if(id) free(id); |
105 plen = ntohl(plen); |
134 if(location) free(location); |
106 if(plen == 0 || plen > PWDSTORE_MAX_LEN) { |
135 if(user) free(user); |
107 return 0; |
136 if(password) free(password); |
108 } |
137 |
109 char *password = malloc(plen+1); |
138 return ret; |
110 password[plen] = 0; |
139 |
111 if(ucx_buffer_read(password, 1, plen, in) != plen) { |
140 } |
112 free(user); |
141 |
113 free(password); |
142 int pwdstore_getindex(PwdStore *s) { |
114 return 0; |
143 uint32_t netindexlen; |
115 } |
144 s->content->pos = PWDS_HEADER_SIZE - sizeof(uint32_t); |
116 |
145 if(ucx_buffer_read(&netindexlen, 1, sizeof(uint32_t), s->content) != sizeof(uint32_t)) { |
117 pwdstore_put(p, user, password); |
146 return 1; |
118 free(user); |
147 } |
119 free(password); |
148 uint32_t indexlen = ntohl(netindexlen); |
120 return 1; |
149 if(UINT32_MAX - PWDS_HEADER_SIZE < indexlen) { |
121 |
150 return 1; |
|
151 } |
|
152 if(s->content->size < PWDS_HEADER_SIZE + indexlen) { |
|
153 return 1; |
|
154 } |
|
155 s->encoffset += indexlen; |
|
156 |
|
157 UcxBuffer *index = ucx_buffer_new(s->content->space+PWDS_HEADER_SIZE, indexlen, 0); |
|
158 index->size = indexlen; |
|
159 while(read_pwdentry(s, index, 1)) {} |
|
160 |
|
161 ucx_buffer_free(index); |
|
162 |
|
163 return 0; |
122 } |
164 } |
123 |
165 |
124 int pwdstore_decrypt(PwdStore *p) { |
166 int pwdstore_decrypt(PwdStore *p) { |
125 if(!p->key) { |
167 if(!p->key) { |
126 return 1; |
168 return 1; |
127 } |
169 } |
128 |
170 |
129 // decrypt contet |
171 // decrypt contet |
130 size_t encsz = p->content->size - PWDS_HEADER_SIZE; |
172 size_t encsz = p->content->size - p->encoffset; |
131 UcxBuffer *enc = ucx_buffer_new(p->content->space + PWDS_HEADER_SIZE, encsz, 0); |
173 UcxBuffer *enc = ucx_buffer_new(p->content->space + p->encoffset, encsz, 0); |
132 enc->size = encsz; |
174 enc->size = encsz; |
133 enc->size = p->content->size - PWDS_HEADER_SIZE; |
175 enc->size = p->content->size - p->encoffset; |
134 UcxBuffer *content = aes_decrypt_buffer(enc, p->key); |
176 UcxBuffer *content = aes_decrypt_buffer(enc, p->key); |
135 ucx_buffer_free(enc); |
177 ucx_buffer_free(enc); |
136 if(!content) { |
178 if(!content) { |
137 return 1; |
179 return 1; |
138 } |
180 } |
139 |
181 |
140 while(read_pwdentry(p, content)) {} |
182 while(read_pwdentry(p, content, 0)) {} |
141 |
183 |
142 ucx_buffer_free(content); |
184 ucx_buffer_free(content); |
143 |
185 |
144 return 0; |
186 return 0; |
145 } |
187 } |
163 PWDS_ENC(p) = enc; |
205 PWDS_ENC(p) = enc; |
164 PWDS_PWFUNC(p) = pwfunc; |
206 PWDS_PWFUNC(p) = pwfunc; |
165 } |
207 } |
166 |
208 |
167 static void free_entry(PwdEntry *e) { |
209 static void free_entry(PwdEntry *e) { |
168 free(e->user); |
210 if(e->id) free(e->id); |
169 free(e->password); |
211 if(e->location) free(e->location); |
|
212 if(e->user) free(e->user); |
|
213 if(e->password) free(e->password); |
170 free(e); |
214 free(e); |
171 } |
215 } |
172 |
216 |
173 void pwdstore_free(PwdStore* p) { |
217 void pwdstore_free(PwdStore* p) { |
174 ucx_map_free_content(p->pwds, (ucx_destructor)free_entry); |
218 ucx_map_free_content(p->ids, (ucx_destructor)free_entry); |
175 ucx_map_free(p->pwds); |
219 ucx_map_free(p->ids); |
|
220 |
|
221 ucx_list_free(p->locations); |
176 |
222 |
177 if(p->content) { |
223 if(p->content) { |
178 ucx_buffer_free(p->content); |
224 ucx_buffer_free(p->content); |
179 } |
225 } |
180 |
226 |
181 free(p); |
227 free(p); |
182 } |
228 } |
183 |
229 |
184 PwdEntry* pwdstore_get(PwdStore *p, const char *username) { |
230 int pwdstore_has_id(PwdStore *s, const char *id) { |
185 return ucx_map_cstr_get(p->pwds, username); |
231 return ucx_map_cstr_get(s->ids, id) ? 1 : 0; |
186 } |
232 } |
187 |
233 |
188 void pwdstore_put(PwdStore *p, const char *username, const char *password) { |
234 int pwdstore_has_location(PwdStore *s, const char *location) { |
|
235 return 0; |
|
236 } |
|
237 |
|
238 PwdEntry* pwdstore_get(PwdStore *p, const char *id) { |
|
239 PwdEntry *e = ucx_map_cstr_get(p->ids, id); |
|
240 if(e->user && e->password) { |
|
241 return e; |
|
242 } else { |
|
243 return NULL; |
|
244 } |
|
245 } |
|
246 |
|
247 void pwdstore_put(PwdStore *p, const char *id, const char *location, const char *username, const char *password) { |
189 PwdEntry *entry = malloc(sizeof(PwdEntry)); |
248 PwdEntry *entry = malloc(sizeof(PwdEntry)); |
190 entry->user = strdup(username); |
249 entry->id = strdup(id); |
191 entry->password = strdup(password); |
250 entry->location = location ? strdup(location) : NULL; |
192 ucx_map_cstr_put(p->pwds, entry->user, entry); |
251 entry->user = username ? strdup(username) : NULL; |
|
252 entry->password = password ? strdup(password) : NULL; |
|
253 ucx_map_cstr_put(p->ids, id, entry); |
|
254 |
|
255 if(location) { |
|
256 p->locations = ucx_list_append(p->locations, entry); |
|
257 } |
193 } |
258 } |
194 |
259 |
195 int pwdstore_store(PwdStore *p, const char *file) { |
260 int pwdstore_store(PwdStore *p, const char *file) { |
196 if(!p->key) { |
261 if(!p->key) { |
197 return 1; |
262 return 1; |
198 } |
263 } |
199 |
264 |
|
265 UcxBuffer *index = ucx_buffer_new(NULL, 2048, UCX_BUFFER_AUTOEXTEND); |
200 UcxBuffer *content = ucx_buffer_new(NULL, 2048, UCX_BUFFER_AUTOEXTEND); |
266 UcxBuffer *content = ucx_buffer_new(NULL, 2048, UCX_BUFFER_AUTOEXTEND); |
201 |
267 |
202 UcxMapIterator i = ucx_map_iterator(p->pwds); |
268 UcxMapIterator i = ucx_map_iterator(p->ids); |
203 PwdEntry *value; |
269 PwdEntry *value; |
204 UCX_MAP_FOREACH(key, value, i) { |
270 UCX_MAP_FOREACH(key, value, i) { |
205 ucx_buffer_putc(content, 0); // type |
271 uint32_t idlen = strlen(value->id); |
|
272 uint32_t locationlen = value->location ? strlen(value->location) : 0; |
206 uint32_t ulen = strlen(value->user); |
273 uint32_t ulen = strlen(value->user); |
207 uint32_t plen = strlen(value->password); |
274 uint32_t plen = strlen(value->password); |
|
275 uint32_t netidlen = htonl(idlen); |
|
276 uint32_t netlocationlen = htonl(locationlen); |
208 uint32_t netulen = htonl(ulen); |
277 uint32_t netulen = htonl(ulen); |
209 uint32_t netplen = htonl(plen); |
278 uint32_t netplen = htonl(plen); |
|
279 |
|
280 // index buffer |
|
281 ucx_buffer_putc(index, 0); // type |
|
282 |
|
283 ucx_buffer_write(&netidlen, 1, sizeof(uint32_t), index); |
|
284 ucx_buffer_write(value->id, 1, idlen, index); |
|
285 ucx_buffer_write(&netlocationlen, 1, sizeof(uint32_t), index); |
|
286 if(value->location) { |
|
287 ucx_buffer_write(value->location, 1, locationlen, index); |
|
288 } |
|
289 |
|
290 // content buffer |
|
291 ucx_buffer_putc(content, 0); // type |
|
292 |
|
293 ucx_buffer_write(&netidlen, 1, sizeof(uint32_t), content); |
|
294 ucx_buffer_write(value->id, 1, idlen, content); |
|
295 ucx_buffer_write(&netlocationlen, 1, sizeof(uint32_t), content); |
|
296 if(value->location) { |
|
297 ucx_buffer_write(value->location, 1, locationlen, content); |
|
298 } |
210 ucx_buffer_write(&netulen, 1, sizeof(uint32_t), content); |
299 ucx_buffer_write(&netulen, 1, sizeof(uint32_t), content); |
211 ucx_buffer_write(value->user, 1, ulen, content); |
300 ucx_buffer_write(value->user, 1, ulen, content); |
212 ucx_buffer_write(&netplen, 1, sizeof(uint32_t), content); |
301 ucx_buffer_write(&netplen, 1, sizeof(uint32_t), content); |
213 ucx_buffer_write(value->password, 1, plen, content); |
302 ucx_buffer_write(value->password, 1, plen, content); |
214 } |
303 } |
215 |
304 |
216 content->pos = 0; |
305 content->pos = 0; |
217 UcxBuffer *enc = aes_encrypt_buffer(content, p->key); |
306 UcxBuffer *enc = aes_encrypt_buffer(content, p->key); |
218 |
307 |
219 p->content->pos = PWDS_HEADER_SIZE; |
308 p->content->pos = PWDS_HEADER_SIZE - sizeof(uint32_t); |
220 p->content->size = PWDS_HEADER_SIZE; |
309 p->content->size = PWDS_HEADER_SIZE; |
|
310 |
|
311 // add index after header |
|
312 uint32_t netindexlen = htonl((uint32_t)index->size); |
|
313 ucx_buffer_write(&netindexlen, 1, sizeof(uint32_t), p->content); |
|
314 ucx_buffer_write(index->space, 1, index->size, p->content); |
|
315 |
|
316 // add encrypted buffer |
221 ucx_buffer_write(enc->space, 1, enc->size, p->content); |
317 ucx_buffer_write(enc->space, 1, enc->size, p->content); |
222 |
318 |
223 ucx_buffer_free(enc); |
319 ucx_buffer_free(enc); |
224 |
320 |
225 FILE *out = fopen(file, "w"); |
321 FILE *out = fopen(file, "w"); |