Mercurial > projects > libpws
comparison pws-field.c @ 0:d541e748cfd8
Initial revision
author | Guido Berhoerster <guido+libpws@berhoerster.name> |
---|---|
date | Tue, 10 Feb 2015 11:29:54 +0100 |
parents | |
children | 1c0e7f79e737 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d541e748cfd8 |
---|---|
1 /* | |
2 * Copyright (C) 2015 Guido Berhoerster <guido+libpws@berhoerster.name> | |
3 * | |
4 * Permission is hereby granted, free of charge, to any person obtaining | |
5 * a copy of this software and associated documentation files (the | |
6 * "Software"), to deal in the Software without restriction, including | |
7 * without limitation the rights to use, copy, modify, merge, publish, | |
8 * distribute, sublicense, and/or sell copies of the Software, and to | |
9 * permit persons to whom the Software is furnished to do so, subject to | |
10 * the following conditions: | |
11 * | |
12 * The above copyright notice and this permission notice shall be included | |
13 * in all copies or substantial portions of the Software. | |
14 * | |
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
22 */ | |
23 | |
24 #include "compat.h" | |
25 | |
26 #include <stdlib.h> | |
27 #include <string.h> | |
28 #include <limits.h> | |
29 | |
30 #include "pws-internal.h" | |
31 | |
32 static const enum pws_data_type header_data_types[256] = { | |
33 [PWS3_HEADER_FIELD_VERSION] = PWS_DATA_TYPE_UINT16, | |
34 [PWS3_HEADER_FIELD_UUID] = PWS_DATA_TYPE_UUID, | |
35 [PWS3_HEADER_FIELD_NON_DEFAULT_PREFERENCES] = PWS_DATA_TYPE_TEXT, | |
36 [PWS3_HEADER_FIELD_TREE_DISPLAY_STATUS] = PWS_DATA_TYPE_TEXT, | |
37 [PWS3_HEADER_FIELD_SAVE_TIMESTAMP] = PWS_DATA_TYPE_TIME, | |
38 [PWS3_HEADER_FIELD_SAVE_USER_HOST] = PWS_DATA_TYPE_TEXT, | |
39 [PWS3_HEADER_FIELD_SAVE_APPLICATION] = PWS_DATA_TYPE_TEXT, | |
40 [PWS3_HEADER_FIELD_SAVE_USER] = PWS_DATA_TYPE_TEXT, | |
41 [PWS3_HEADER_FIELD_SAVE_HOST] = PWS_DATA_TYPE_TEXT, | |
42 [PWS3_HEADER_FIELD_DATABASE_NAME] = PWS_DATA_TYPE_TEXT, | |
43 [PWS3_HEADER_FIELD_DATABASE_DESCRIPTION] = PWS_DATA_TYPE_TEXT, | |
44 [PWS3_HEADER_FIELD_DATABASE_FILTERS] = PWS_DATA_TYPE_TEXT, | |
45 [PWS3_HEADER_FIELD_RESERVED_1] = PWS_DATA_TYPE_BYTES, | |
46 [PWS3_HEADER_FIELD_RESERVED_2] = PWS_DATA_TYPE_BYTES, | |
47 [PWS3_HEADER_FIELD_RESERVED_3] = PWS_DATA_TYPE_BYTES, | |
48 [PWS3_HEADER_FIELD_RECENTLY_USED_ENTRIES] = PWS_DATA_TYPE_TEXT, | |
49 [PWS3_HEADER_FIELD_NAMED_PASSWORD_POLICIES] = PWS_DATA_TYPE_TEXT, | |
50 [PWS3_HEADER_FIELD_EMPTY_GROUPS] = PWS_DATA_TYPE_TEXT, | |
51 [PWS3_HEADER_FIELD_YUBICO] = PWS_DATA_TYPE_TEXT | |
52 }; | |
53 | |
54 static const enum pws_data_type record_data_types[256] = { | |
55 [PWS3_RECORD_FIELD_UUID] = PWS_DATA_TYPE_UUID, | |
56 [PWS3_RECORD_FIELD_GROUP] = PWS_DATA_TYPE_TEXT, | |
57 [PWS3_RECORD_FIELD_TITLE] = PWS_DATA_TYPE_TEXT, | |
58 [PWS3_RECORD_FIELD_USERNAME] = PWS_DATA_TYPE_TEXT, | |
59 [PWS3_RECORD_FIELD_NOTES] = PWS_DATA_TYPE_TEXT, | |
60 [PWS3_RECORD_FIELD_PASSWORD] = PWS_DATA_TYPE_TEXT, | |
61 [PWS3_RECORD_FIELD_CREATION_TIME] = PWS_DATA_TYPE_TIME, | |
62 [PWS3_RECORD_FIELD_PASSWORD_MODIFICATION_TIME] = PWS_DATA_TYPE_TIME, | |
63 [PWS3_RECORD_FIELD_ACCESS_TIME] = PWS_DATA_TYPE_TIME, | |
64 [PWS3_RECORD_FIELD_PASSWORD_EXPIRY_TIME] = PWS_DATA_TYPE_TIME, | |
65 [PWS3_RECORD_FIELD_RESERVED_1] = PWS_DATA_TYPE_BYTES, | |
66 [PWS3_RECORD_FIELD_MODIFICATION_TIME] = PWS_DATA_TYPE_TIME, | |
67 [PWS3_RECORD_FIELD_URL] = PWS_DATA_TYPE_TEXT, | |
68 [PWS3_RECORD_FIELD_AUTOTYPE] = PWS_DATA_TYPE_TEXT, | |
69 [PWS3_RECORD_FIELD_PASSWORD_HISTORY] = PWS_DATA_TYPE_TEXT, | |
70 [PWS3_RECORD_FIELD_PASSWORD_POLICY] = PWS_DATA_TYPE_TEXT, | |
71 [PWS3_RECORD_FIELD_PASSWORD_EXPIRY_INTERVAL] = PWS_DATA_TYPE_UINT32, | |
72 [PWS3_RECORD_FIELD_RUN_COMMAND] = PWS_DATA_TYPE_TEXT, | |
73 [PWS3_RECORD_FIELD_DOUBLE_CLICK_ACTION] = PWS_DATA_TYPE_BYTES, | |
74 [PWS3_RECORD_FIELD_EMAIL_ADDRESS] = PWS_DATA_TYPE_TEXT, | |
75 [PWS3_RECORD_FIELD_PROTECTED] = PWS_DATA_TYPE_UINT8, | |
76 [PWS3_RECORD_FIELD_ALLOWED_PASSWORD_SYMBOLS] = PWS_DATA_TYPE_TEXT, | |
77 [PWS3_RECORD_FIELD_SHIFT_DOUBLE_CLICK_ACTION] = PWS_DATA_TYPE_BYTES, | |
78 [PWS3_RECORD_FIELD_PASSWORD_POLICY_NAME] = PWS_DATA_TYPE_TEXT, | |
79 [PWS3_RECORD_FIELD_KEYBOARD_SHORTCUT] = PWS_DATA_TYPE_BYTES | |
80 }; | |
81 | |
82 struct pws3_field * | |
83 pws3_field_create(int is_header, uint8_t field_type) | |
84 { | |
85 struct pws3_field *field; | |
86 | |
87 field = pws_alloc(sizeof (struct pws3_field)); | |
88 if (field == NULL) { | |
89 return (NULL); | |
90 } | |
91 | |
92 field->is_header = is_header; | |
93 field->field_type = field_type; | |
94 field->size = 0; | |
95 switch (pws3_field_get_data_type(field)) { | |
96 case PWS_DATA_TYPE_BYTES: | |
97 field->value.bytes = NULL; | |
98 break; | |
99 case PWS_DATA_TYPE_UUID: | |
100 memset(field->value.uuid, 0, PWS3_UUID_SIZE); | |
101 break; | |
102 case PWS_DATA_TYPE_TEXT: | |
103 field->value.text = NULL; | |
104 break; | |
105 case PWS_DATA_TYPE_UINT8: | |
106 field->value.uint8 = 0; | |
107 break; | |
108 case PWS_DATA_TYPE_UINT16: | |
109 field->value.uint16 = 0; | |
110 break; | |
111 case PWS_DATA_TYPE_TIME: /* FALLTHROUGH */ | |
112 case PWS_DATA_TYPE_UINT32: | |
113 field->value.uint32 = 0; | |
114 } | |
115 | |
116 return (field); | |
117 } | |
118 | |
119 void | |
120 pws3_field_destroy(struct pws3_field *field) | |
121 { | |
122 if (field == NULL) { | |
123 return; | |
124 } | |
125 | |
126 switch (pws3_field_get_data_type(field)) { | |
127 case PWS_DATA_TYPE_BYTES: | |
128 pws_free(field->value.bytes, field->size); | |
129 break; | |
130 case PWS_DATA_TYPE_TEXT: | |
131 if (!field->is_header && | |
132 (field->field_type == PWS3_RECORD_FIELD_PASSWORD)) { | |
133 pws_secure_free(field->value.text, field->size + 1); | |
134 } else { | |
135 pws_free(field->value.text, field->size + 1); | |
136 } | |
137 break; | |
138 default: | |
139 break; | |
140 } | |
141 | |
142 pws_free(field, sizeof (struct pws3_field)); | |
143 } | |
144 | |
145 int | |
146 pws3_field_is_header(struct pws3_field *field) | |
147 { | |
148 return (field->is_header); | |
149 } | |
150 | |
151 uint8_t | |
152 pws3_field_get_type(struct pws3_field *field) | |
153 { | |
154 return (field->field_type); | |
155 } | |
156 | |
157 enum pws_data_type | |
158 pws3_field_get_data_type(struct pws3_field *field) | |
159 { | |
160 return (field->is_header ? header_data_types[field->field_type] : | |
161 record_data_types[field->field_type]); | |
162 } | |
163 | |
164 int | |
165 pws3_field_set_uuid(struct pws3_field *field, | |
166 const unsigned char s[static PWS3_UUID_SIZE]) | |
167 { | |
168 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UUID); | |
169 | |
170 field->size = PWS3_UUID_SIZE; | |
171 memcpy(field->value.uuid, s, PWS3_UUID_SIZE); | |
172 | |
173 return (0); | |
174 } | |
175 | |
176 int | |
177 pws3_field_set_text(struct pws3_field *field, const char s[static 1]) | |
178 { | |
179 size_t len; | |
180 char *t; | |
181 | |
182 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_TEXT); | |
183 | |
184 len = strlen(s); | |
185 if (len > PWS3_MAX_FIELD_SIZE) { | |
186 return (-1); | |
187 } | |
188 | |
189 if (!field->is_header && | |
190 (field->field_type == PWS3_RECORD_FIELD_PASSWORD)) { | |
191 if (len > PWS3_MAX_PASSWORD_LEN) { | |
192 return (-1); | |
193 } | |
194 t = pws_secure_realloc(field->value.text, len + 1); | |
195 } else { | |
196 t = pws_realloc(field->value.text, len + 1); | |
197 } | |
198 if (t == NULL) { | |
199 return (-1); | |
200 } | |
201 field->value.text = t; | |
202 field->size = len + 1; | |
203 memcpy(field->value.text, s, field->size); | |
204 | |
205 return (0); | |
206 } | |
207 | |
208 int | |
209 pws3_field_set_time(struct pws3_field *field, time_t time) | |
210 { | |
211 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_TIME); | |
212 | |
213 field->size = 4; | |
214 field->value.uint32 = CLAMP(time, 0, UINT32_MAX); | |
215 | |
216 return (0); | |
217 } | |
218 | |
219 int | |
220 pws3_field_set_uint8(struct pws3_field *field, uint8_t u8) | |
221 { | |
222 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT8); | |
223 | |
224 field->size = 1; | |
225 field->value.uint8 = u8; | |
226 | |
227 return (0); | |
228 } | |
229 | |
230 int | |
231 pws3_field_set_uint16(struct pws3_field *field, uint16_t u16) | |
232 { | |
233 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT16); | |
234 | |
235 field->size = 2; | |
236 field->value.uint16 = u16; | |
237 | |
238 return (0); | |
239 } | |
240 | |
241 int | |
242 pws3_field_set_uint32(struct pws3_field *field, uint32_t u32) | |
243 { | |
244 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT32); | |
245 | |
246 field->size = 4; | |
247 field->value.uint32 = u32; | |
248 | |
249 return (0); | |
250 } | |
251 | |
252 int | |
253 pws3_field_set_bytes(struct pws3_field *field, const unsigned char s[static 1], | |
254 size_t n) | |
255 { | |
256 unsigned char *t; | |
257 | |
258 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_BYTES); | |
259 | |
260 if (n > PWS3_MAX_FIELD_SIZE) { | |
261 return (-1); | |
262 } | |
263 | |
264 t = pws_realloc(field->value.bytes, n); | |
265 if (t == NULL) { | |
266 return (-1); | |
267 } | |
268 field->size = n; | |
269 field->value.bytes = t; | |
270 memcpy(t, s, n); | |
271 | |
272 return (0); | |
273 } | |
274 | |
275 const unsigned char * | |
276 pws3_field_get_uuid(struct pws3_field *field) | |
277 { | |
278 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UUID); | |
279 | |
280 return (field->value.uuid); | |
281 } | |
282 | |
283 const char * | |
284 pws3_field_get_text(struct pws3_field *field) | |
285 { | |
286 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_TEXT); | |
287 | |
288 return (field->value.text); | |
289 } | |
290 | |
291 time_t | |
292 pws3_field_get_time(struct pws3_field *field) | |
293 { | |
294 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_TIME); | |
295 | |
296 /* assume time_t can hold at least a INT32_MAX */ | |
297 return ((time_t)CLAMP(field->value.uint32, 0, INT32_MAX)); | |
298 } | |
299 | |
300 uint8_t | |
301 pws3_field_get_uint8(struct pws3_field *field) | |
302 { | |
303 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT8); | |
304 | |
305 return (field->value.uint8); | |
306 } | |
307 | |
308 uint16_t | |
309 pws3_field_get_uint16(struct pws3_field *field) | |
310 { | |
311 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT16); | |
312 | |
313 return (field->value.uint16); | |
314 } | |
315 | |
316 uint32_t | |
317 pws3_field_get_uint32(struct pws3_field *field) | |
318 { | |
319 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_UINT32); | |
320 | |
321 return (field->value.uint32); | |
322 } | |
323 | |
324 void | |
325 pws3_field_get_bytes(struct pws3_field *field, const unsigned char **sp, | |
326 size_t *np) | |
327 { | |
328 PWS_ASSERT(pws3_field_get_data_type(field) == PWS_DATA_TYPE_BYTES); | |
329 | |
330 *sp = field->value.bytes; | |
331 *np = field->size; | |
332 } |