diff -r d8e883bd1fd8 -r 08d2d1263429 dav/pwd.c --- a/dav/pwd.c Sat Sep 15 11:58:17 2018 +0200 +++ b/dav/pwd.c Thu Sep 20 13:07:38 2018 +0200 @@ -54,17 +54,24 @@ } PwdStore *p = malloc(sizeof(PwdStore)); - p->pwds = ucx_map_new(16); + p->ids = ucx_map_new(16); + p->locations = NULL; p->content = buf; p->key = NULL; + p->encoffset = PWDS_HEADER_SIZE; p->isdecrypted = 0; + if(pwdstore_getindex(p)) { + pwdstore_free(p); + return NULL; + } + return p; } PwdStore* pwdstore_new(void) { PwdStore *p = calloc(1, sizeof(PwdStore)); - p->pwds = ucx_map_new(16); + p->ids = ucx_map_new(16); p->content = ucx_buffer_new(NULL, PWDS_HEADER_SIZE, UCX_BUFFER_AUTOEXTEND); PWDS_MAGIC(p) = PWDS_MAGIC_CHAR; PWDS_VERSION(p) = 1; @@ -74,51 +81,86 @@ return p; } -static int read_pwdentry(PwdStore *p, UcxBuffer *in) { +static int readval(UcxBuffer *in, char **val, int allowzero) { + *val = NULL; + uint32_t length = 0; + if(ucx_buffer_read(&length, 1, sizeof(uint32_t), in) != sizeof(uint32_t)) { + return 0; + } + length = ntohl(length); + if((length == 0 && !allowzero) || length > PWDSTORE_MAX_LEN) { + return 0; + } + + char *value = malloc(length + 1); + value[length] = 0; + if(ucx_buffer_read(value, 1, length, in) != length) { + free(value); + return 0; + } + + *val = value; + return 1; +} + +static int read_pwdentry(PwdStore *p, UcxBuffer *in, int index) { int type = ucx_buffer_getc(in); if(type == EOF || type != 0) { // only type 0 supported yet return 0; } - uint32_t ulen = 0; - uint32_t plen = 0; + char *id = NULL; + char *location = NULL; + char *user = NULL; + char *password = NULL; - if(ucx_buffer_read(&ulen, 1, sizeof(uint32_t), in) != sizeof(uint32_t)) { - return 0; - } - ulen = ntohl(ulen); - if(ulen == 0 || ulen > PWDSTORE_MAX_LEN) { - return 0; + int res = 0; + if((res += readval(in, &id, FALSE)) == 1) { + if((res += readval(in, &location, TRUE)) == 2) { + if((res += readval(in, &user, FALSE)) == 3) { + res += readval(in, &password, FALSE); + } + } } - char *user = malloc(ulen+1); - user[ulen] = 0; - if(ucx_buffer_read(user, 1, ulen, in) != ulen) { - free(user); - return 0; + int ret = 0; + if((!index && res == 4) || (index && res == 2)) { + pwdstore_put(p, id, location, user, password); + ret = 1; } - if(ucx_buffer_read(&plen, 1, sizeof(uint32_t), in) != sizeof(uint32_t)) { - return 0; - } - plen = ntohl(plen); - if(plen == 0 || plen > PWDSTORE_MAX_LEN) { - return 0; + if(id) free(id); + if(location) free(location); + if(user) free(user); + if(password) free(password); + + return ret; + +} + +int pwdstore_getindex(PwdStore *s) { + uint32_t netindexlen; + s->content->pos = PWDS_HEADER_SIZE - sizeof(uint32_t); + if(ucx_buffer_read(&netindexlen, 1, sizeof(uint32_t), s->content) != sizeof(uint32_t)) { + return 1; } - char *password = malloc(plen+1); - password[plen] = 0; - if(ucx_buffer_read(password, 1, plen, in) != plen) { - free(user); - free(password); - return 0; + uint32_t indexlen = ntohl(netindexlen); + if(UINT32_MAX - PWDS_HEADER_SIZE < indexlen) { + return 1; + } + if(s->content->size < PWDS_HEADER_SIZE + indexlen) { + return 1; } + s->encoffset += indexlen; - pwdstore_put(p, user, password); - free(user); - free(password); - return 1; + UcxBuffer *index = ucx_buffer_new(s->content->space+PWDS_HEADER_SIZE, indexlen, 0); + index->size = indexlen; + while(read_pwdentry(s, index, 1)) {} + ucx_buffer_free(index); + + return 0; } int pwdstore_decrypt(PwdStore *p) { @@ -127,17 +169,17 @@ } // decrypt contet - size_t encsz = p->content->size - PWDS_HEADER_SIZE; - UcxBuffer *enc = ucx_buffer_new(p->content->space + PWDS_HEADER_SIZE, encsz, 0); + size_t encsz = p->content->size - p->encoffset; + UcxBuffer *enc = ucx_buffer_new(p->content->space + p->encoffset, encsz, 0); enc->size = encsz; - enc->size = p->content->size - PWDS_HEADER_SIZE; + enc->size = p->content->size - p->encoffset; UcxBuffer *content = aes_decrypt_buffer(enc, p->key); ucx_buffer_free(enc); if(!content) { return 1; } - while(read_pwdentry(p, content)) {} + while(read_pwdentry(p, content, 0)) {} ucx_buffer_free(content); @@ -165,14 +207,18 @@ } static void free_entry(PwdEntry *e) { - free(e->user); - free(e->password); + if(e->id) free(e->id); + if(e->location) free(e->location); + if(e->user) free(e->user); + if(e->password) free(e->password); free(e); } void pwdstore_free(PwdStore* p) { - ucx_map_free_content(p->pwds, (ucx_destructor)free_entry); - ucx_map_free(p->pwds); + ucx_map_free_content(p->ids, (ucx_destructor)free_entry); + ucx_map_free(p->ids); + + ucx_list_free(p->locations); if(p->content) { ucx_buffer_free(p->content); @@ -181,15 +227,34 @@ free(p); } -PwdEntry* pwdstore_get(PwdStore *p, const char *username) { - return ucx_map_cstr_get(p->pwds, username); +int pwdstore_has_id(PwdStore *s, const char *id) { + return ucx_map_cstr_get(s->ids, id) ? 1 : 0; +} + +int pwdstore_has_location(PwdStore *s, const char *location) { + return 0; } -void pwdstore_put(PwdStore *p, const char *username, const char *password) { +PwdEntry* pwdstore_get(PwdStore *p, const char *id) { + PwdEntry *e = ucx_map_cstr_get(p->ids, id); + if(e->user && e->password) { + return e; + } else { + return NULL; + } +} + +void pwdstore_put(PwdStore *p, const char *id, const char *location, const char *username, const char *password) { PwdEntry *entry = malloc(sizeof(PwdEntry)); - entry->user = strdup(username); - entry->password = strdup(password); - ucx_map_cstr_put(p->pwds, entry->user, entry); + entry->id = strdup(id); + entry->location = location ? strdup(location) : NULL; + entry->user = username ? strdup(username) : NULL; + entry->password = password ? strdup(password) : NULL; + ucx_map_cstr_put(p->ids, id, entry); + + if(location) { + p->locations = ucx_list_append(p->locations, entry); + } } int pwdstore_store(PwdStore *p, const char *file) { @@ -197,27 +262,58 @@ return 1; } + UcxBuffer *index = ucx_buffer_new(NULL, 2048, UCX_BUFFER_AUTOEXTEND); UcxBuffer *content = ucx_buffer_new(NULL, 2048, UCX_BUFFER_AUTOEXTEND); - UcxMapIterator i = ucx_map_iterator(p->pwds); + UcxMapIterator i = ucx_map_iterator(p->ids); PwdEntry *value; UCX_MAP_FOREACH(key, value, i) { - ucx_buffer_putc(content, 0); // type + uint32_t idlen = strlen(value->id); + uint32_t locationlen = value->location ? strlen(value->location) : 0; uint32_t ulen = strlen(value->user); uint32_t plen = strlen(value->password); + uint32_t netidlen = htonl(idlen); + uint32_t netlocationlen = htonl(locationlen); uint32_t netulen = htonl(ulen); uint32_t netplen = htonl(plen); + + // index buffer + ucx_buffer_putc(index, 0); // type + + ucx_buffer_write(&netidlen, 1, sizeof(uint32_t), index); + ucx_buffer_write(value->id, 1, idlen, index); + ucx_buffer_write(&netlocationlen, 1, sizeof(uint32_t), index); + if(value->location) { + ucx_buffer_write(value->location, 1, locationlen, index); + } + + // content buffer + ucx_buffer_putc(content, 0); // type + + ucx_buffer_write(&netidlen, 1, sizeof(uint32_t), content); + ucx_buffer_write(value->id, 1, idlen, content); + ucx_buffer_write(&netlocationlen, 1, sizeof(uint32_t), content); + if(value->location) { + ucx_buffer_write(value->location, 1, locationlen, content); + } ucx_buffer_write(&netulen, 1, sizeof(uint32_t), content); ucx_buffer_write(value->user, 1, ulen, content); ucx_buffer_write(&netplen, 1, sizeof(uint32_t), content); ucx_buffer_write(value->password, 1, plen, content); } - + content->pos = 0; UcxBuffer *enc = aes_encrypt_buffer(content, p->key); - p->content->pos = PWDS_HEADER_SIZE; + p->content->pos = PWDS_HEADER_SIZE - sizeof(uint32_t); p->content->size = PWDS_HEADER_SIZE; + + // add index after header + uint32_t netindexlen = htonl((uint32_t)index->size); + ucx_buffer_write(&netindexlen, 1, sizeof(uint32_t), p->content); + ucx_buffer_write(index->space, 1, index->size, p->content); + + // add encrypted buffer ucx_buffer_write(enc->space, 1, enc->size, p->content); ucx_buffer_free(enc);