Mercurial > projects > libpws
view pws-field.c @ 6:1c0e7f79e737
Fix incorrect field size for text fields
The field size should be the string length excluding the terminating null byte
which is there for convenience only when using the C API and not part of the
on-disk format.
author | Guido Berhoerster <guido+libpws@berhoerster.name> |
---|---|
date | Thu, 10 Jan 2019 09:35:16 +0100 |
parents | d541e748cfd8 |
children | 96a507a110c8 |
line wrap: on
line source
/* * Copyright (C) 2015 Guido Berhoerster <guido+libpws@berhoerster.name> * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "compat.h" #include <stdlib.h> #include <string.h> #include <limits.h> #include "pws-internal.h" static const enum pws_data_type header_data_types[256] = { [PWS3_HEADER_FIELD_VERSION] = PWS_DATA_TYPE_UINT16, [PWS3_HEADER_FIELD_UUID] = PWS_DATA_TYPE_UUID, [PWS3_HEADER_FIELD_NON_DEFAULT_PREFERENCES] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_TREE_DISPLAY_STATUS] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_SAVE_TIMESTAMP] = PWS_DATA_TYPE_TIME, [PWS3_HEADER_FIELD_SAVE_USER_HOST] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_SAVE_APPLICATION] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_SAVE_USER] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_SAVE_HOST] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_DATABASE_NAME] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_DATABASE_DESCRIPTION] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_DATABASE_FILTERS] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_RESERVED_1] = PWS_DATA_TYPE_BYTES, [PWS3_HEADER_FIELD_RESERVED_2] = PWS_DATA_TYPE_BYTES, [PWS3_HEADER_FIELD_RESERVED_3] = PWS_DATA_TYPE_BYTES, [PWS3_HEADER_FIELD_RECENTLY_USED_ENTRIES] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_NAMED_PASSWORD_POLICIES] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_EMPTY_GROUPS] = PWS_DATA_TYPE_TEXT, [PWS3_HEADER_FIELD_YUBICO] = PWS_DATA_TYPE_TEXT }; static const enum pws_data_type record_data_types[256] = { [PWS3_RECORD_FIELD_UUID] = PWS_DATA_TYPE_UUID, [PWS3_RECORD_FIELD_GROUP] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_TITLE] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_USERNAME] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_NOTES] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_PASSWORD] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_CREATION_TIME] = PWS_DATA_TYPE_TIME, [PWS3_RECORD_FIELD_PASSWORD_MODIFICATION_TIME] = PWS_DATA_TYPE_TIME, [PWS3_RECORD_FIELD_ACCESS_TIME] = PWS_DATA_TYPE_TIME, [PWS3_RECORD_FIELD_PASSWORD_EXPIRY_TIME] = PWS_DATA_TYPE_TIME, [PWS3_RECORD_FIELD_RESERVED_1] = PWS_DATA_TYPE_BYTES, [PWS3_RECORD_FIELD_MODIFICATION_TIME] = PWS_DATA_TYPE_TIME, [PWS3_RECORD_FIELD_URL] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_AUTOTYPE] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_PASSWORD_HISTORY] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_PASSWORD_POLICY] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_PASSWORD_EXPIRY_INTERVAL] = PWS_DATA_TYPE_UINT32, [PWS3_RECORD_FIELD_RUN_COMMAND] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_DOUBLE_CLICK_ACTION] = PWS_DATA_TYPE_BYTES, [PWS3_RECORD_FIELD_EMAIL_ADDRESS] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_PROTECTED] = PWS_DATA_TYPE_UINT8, [PWS3_RECORD_FIELD_ALLOWED_PASSWORD_SYMBOLS] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_SHIFT_DOUBLE_CLICK_ACTION] = PWS_DATA_TYPE_BYTES, [PWS3_RECORD_FIELD_PASSWORD_POLICY_NAME] = PWS_DATA_TYPE_TEXT, [PWS3_RECORD_FIELD_KEYBOARD_SHORTCUT] = PWS_DATA_TYPE_BYTES }; struct pws3_field * pws3_field_create(int is_header, uint8_t field_type) { struct pws3_field *field; field = pws_alloc(sizeof (struct pws3_field)); if (field == NULL) { return (NULL); } field->is_header = is_header; field->field_type = field_type; field->size = 0; switch (pws3_field_get_data_type(field)) { case PWS_DATA_TYPE_BYTES: field->value.bytes = NULL; break; case PWS_DATA_TYPE_UUID: memset(field->value.uuid, 0, PWS3_UUID_SIZE); break; case PWS_DATA_TYPE_TEXT: field->value.text = NULL; break; case PWS_DATA_TYPE_UINT8: field->value.uint8 = 0; break; case PWS_DATA_TYPE_UINT16: field->value.uint16 = 0; break; case PWS_DATA_TYPE_TIME: /* FALLTHROUGH */ case PWS_DATA_TYPE_UINT32: field->value.uint32 = 0; } return (field); } void pws3_field_destroy(struct pws3_field *field) { if (field == NULL) { return; } switch (pws3_field_get_data_type(field)) { case PWS_DATA_TYPE_BYTES: pws_free(field->value.bytes, field->size); break; case PWS_DATA_TYPE_TEXT: if (!field->is_header && (field->field_type == PWS3_RECORD_FIELD_PASSWORD)) { pws_secure_free(field->value.text, field->size + 1); } else { pws_free(field->value.text, field->size + 1); } break; default: break; } pws_free(field, sizeof (struct pws3_field)); } int pws3_field_is_header(struct pws3_field *field) { return (field->is_header); } uint8_t pws3_field_get_type(struct pws3_field *field) { return (field->field_type); } enum pws_data_type pws3_field_get_data_type(struct pws3_field *field) { return (field->is_header ? header_data_types[field->field_type] : record_data_types[field->field_type]); } int pws3_field_set_uuid(struct pws3_field *field, const unsigned char s[static PWS3_UUID_SIZE]) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UUID); field->size = PWS3_UUID_SIZE; memcpy(field->value.uuid, s, PWS3_UUID_SIZE); return (0); } int pws3_field_set_text(struct pws3_field *field, const char s[static 1]) { size_t len; char *t; PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_TEXT); len = strlen(s); if (len > PWS3_MAX_FIELD_SIZE) { return (-1); } if (!field->is_header && (field->field_type == PWS3_RECORD_FIELD_PASSWORD)) { if (len > PWS3_MAX_PASSWORD_LEN) { return (-1); } t = pws_secure_realloc(field->value.text, len + 1); } else { t = pws_realloc(field->value.text, len + 1); } if (t == NULL) { return (-1); } field->value.text = t; field->size = len; memcpy(field->value.text, s, len + 1); return (0); } int pws3_field_set_time(struct pws3_field *field, time_t time) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_TIME); field->size = 4; field->value.uint32 = CLAMP(time, 0, UINT32_MAX); return (0); } int pws3_field_set_uint8(struct pws3_field *field, uint8_t u8) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT8); field->size = 1; field->value.uint8 = u8; return (0); } int pws3_field_set_uint16(struct pws3_field *field, uint16_t u16) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT16); field->size = 2; field->value.uint16 = u16; return (0); } int pws3_field_set_uint32(struct pws3_field *field, uint32_t u32) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT32); field->size = 4; field->value.uint32 = u32; return (0); } int pws3_field_set_bytes(struct pws3_field *field, const unsigned char s[static 1], size_t n) { unsigned char *t; PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_BYTES); if (n > PWS3_MAX_FIELD_SIZE) { return (-1); } t = pws_realloc(field->value.bytes, n); if (t == NULL) { return (-1); } field->size = n; field->value.bytes = t; memcpy(t, s, n); return (0); } const unsigned char * pws3_field_get_uuid(struct pws3_field *field) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UUID); return (field->value.uuid); } const char * pws3_field_get_text(struct pws3_field *field) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_TEXT); return (field->value.text); } time_t pws3_field_get_time(struct pws3_field *field) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_TIME); /* assume time_t can hold at least a INT32_MAX */ return ((time_t)CLAMP(field->value.uint32, 0, INT32_MAX)); } uint8_t pws3_field_get_uint8(struct pws3_field *field) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT8); return (field->value.uint8); } uint16_t pws3_field_get_uint16(struct pws3_field *field) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT16); return (field->value.uint16); } uint32_t pws3_field_get_uint32(struct pws3_field *field) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT32); return (field->value.uint32); } void pws3_field_get_bytes(struct pws3_field *field, const unsigned char **sp, size_t *np) { PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_BYTES); *sp = field->value.bytes; *np = field->size; }