Mercurial > projects > libpws
annotate pws-file.c @ 11:96a507a110c8
Add support for format 0x030E
author | Guido Berhoerster <guido+libpws@berhoerster.name> |
---|---|
date | Fri, 02 Aug 2019 14:47:43 +0200 |
parents | ec5c1b653ee6 |
children |
rev | line source |
---|---|
0
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1 /* |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
2 * Copyright (C) 2015 Guido Berhoerster <guido+libpws@berhoerster.name> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
3 * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
4 * Permission is hereby granted, free of charge, to any person obtaining |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
5 * a copy of this software and associated documentation files (the |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
6 * "Software"), to deal in the Software without restriction, including |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
7 * without limitation the rights to use, copy, modify, merge, publish, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
8 * distribute, sublicense, and/or sell copies of the Software, and to |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
9 * permit persons to whom the Software is furnished to do so, subject to |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
10 * the following conditions: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
11 * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
12 * The above copyright notice and this permission notice shall be included |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
13 * in all copies or substantial portions of the Software. |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
14 * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
22 */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
23 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
24 #include "compat.h" |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
25 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
26 #include <stdlib.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
27 #include <unistd.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
28 #include <string.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
29 #include <stdarg.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
30 #include <errno.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
31 #ifdef HAVE_ENDIAN_H |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
32 #include <endian.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
33 #endif /* HAVE_ENDIAN_H */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
34 #ifdef HAVE_SYS_ENDIAN_H |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
35 #include <sys/endian.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
36 #endif /* HAVE_ENDIAN_H */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
37 #include <nettle/twofish.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
38 #include <nettle/cbc.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
39 #include <nettle/hmac.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
40 #include <nettle/sha.h> |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
41 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
42 #include "pws-internal.h" |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
43 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
44 #define MAX_ITER (1 << 22) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
45 #define DEFAULT_ITER 10000 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
46 #define KEY_SIZE 32UL |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
47 #define SALT_SIZE 32UL |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
48 #define METADATA_SIZE (sizeof (psafe3_tag) + SALT_SIZE + 4 +\ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
49 SHA256_DIGEST_SIZE + KEY_SIZE + KEY_SIZE + TWOFISH_BLOCK_SIZE) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
50 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
51 static const unsigned char psafe3_tag[] = { 'P', 'W', 'S', '3' }; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
52 static const unsigned char eof_marker[] = { 'P', 'W', 'S', '3', '-', 'E', 'O', |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
53 'F', 'P', 'W', 'S', '3', '-', 'E', 'O', 'F' }; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
54 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
55 RB_HEAD(empty_groups_tree, pws3_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
56 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
57 RB_HEAD(records_tree, pws3_record); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
58 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
59 struct pws3_file { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
60 struct pws3_field *fields[256]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
61 struct empty_groups_tree *empty_groups_tree; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
62 struct records_tree *records_tree; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
63 struct pws_file_error { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
64 enum pws_error_code code; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
65 int errnum; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
66 char *msg; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
67 } error; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
68 }; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
69 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
70 struct twofish_cbc_ctx CBC_CTX(struct twofish_ctx, TWOFISH_BLOCK_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
71 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
72 struct pws_file_ctx { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
73 FILE *fp; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
74 unsigned char *mem; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
75 size_t mem_size; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
76 size_t mem_pos; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
77 struct twofish_cbc_ctx cipher_ctx; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
78 struct hmac_sha256_ctx hmac_ctx; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
79 struct pws3_file *pws_file; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
80 uint32_t n_iter; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
81 }; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
82 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
83 static int empty_groups_cmp(struct pws3_field *, struct pws3_field *); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
84 static int record_cmp(struct pws3_record *, struct pws3_record *); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
85 RB_PROTOTYPE_STATIC(empty_groups_tree, pws3_field, tree_entry, empty_groups_cmp) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
86 RB_PROTOTYPE_STATIC(records_tree, pws3_record, tree_entry, record_cmp) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
87 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
88 RB_GENERATE_STATIC(empty_groups_tree, pws3_field, tree_entry, empty_groups_cmp) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
89 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
90 RB_GENERATE_STATIC(records_tree, pws3_record, tree_entry, record_cmp) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
91 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
92 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
93 empty_groups_cmp(struct pws3_field *field1, struct pws3_field *field2) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
94 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
95 PWS_ASSERT(pws3_field_is_header(field1) && |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
96 pws3_field_is_header(field2)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
97 PWS_ASSERT((pws3_field_get_type(field1) == |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
98 PWS3_HEADER_FIELD_EMPTY_GROUPS) && |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
99 (pws3_field_get_type(field2) == PWS3_HEADER_FIELD_EMPTY_GROUPS)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
100 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
101 return (strcmp(pws3_field_get_text(field1), |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
102 pws3_field_get_text(field2))); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
103 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
104 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
105 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
106 record_cmp(struct pws3_record *record1, struct pws3_record *record2) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
107 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
108 struct pws3_field *uuid_field1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
109 struct pws3_field *uuid_field2; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
110 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
111 uuid_field1 = pws3_record_get_field(record1, PWS3_RECORD_FIELD_UUID); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
112 uuid_field2 = pws3_record_get_field(record2, PWS3_RECORD_FIELD_UUID); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
113 PWS_ASSERT((uuid_field1 != NULL) && (uuid_field2 != NULL)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
114 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
115 return (memcmp(pws3_field_get_uuid(uuid_field1), |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
116 pws3_field_get_uuid(uuid_field2), PWS3_UUID_SIZE)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
117 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
118 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
119 static void |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
120 pws_set_system_error(struct pws3_file *pws_file, enum pws_error_code code, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
121 int errnum, const char *fmt, ...) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
122 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
123 char system_error_buf[4096] = ""; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
124 size_t system_error_len; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
125 int error_len; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
126 va_list args; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
127 va_list args2; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
128 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
129 pws_file->error.code = code; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
130 pws_file->error.errnum = errnum; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
131 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
132 strerror_r(errnum, system_error_buf, sizeof (system_error_buf) - 1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
133 system_error_len = strlen(system_error_buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
134 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
135 pws_free(pws_file->error.msg, (pws_file->error.msg != NULL) ? |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
136 strlen(pws_file->error.msg) + 1 : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
137 if (fmt != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
138 va_start(args, fmt); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
139 va_copy(args2, args); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
140 error_len = vsnprintf(NULL, 0, fmt, args); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
141 pws_file->error.msg = pws_alloc(error_len + 2 + |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
142 system_error_len + 1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
143 if (pws_file->error.msg == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
144 va_end(args2); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
145 va_end(args); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
146 return; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
147 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
148 vsnprintf(pws_file->error.msg, error_len + 1, fmt, args2); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
149 va_end(args2); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
150 va_end(args); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
151 strcpy(pws_file->error.msg + error_len, ": "); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
152 strcpy(pws_file->error.msg + error_len + 2, system_error_buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
153 } else { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
154 pws_file->error.msg = pws_alloc(system_error_len + 1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
155 snprintf(pws_file->error.msg, system_error_len + 1, "%s", |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
156 system_error_buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
157 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
158 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
159 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
160 static void |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
161 pws_set_error(struct pws3_file *pws_file, enum pws_error_code code, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
162 const char *fmt, ...) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
163 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
164 va_list args; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
165 va_list args2; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
166 int error_len; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
167 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
168 pws_file->error.code = code; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
169 pws_file->error.errnum = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
170 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
171 pws_free(pws_file->error.msg, (pws_file->error.msg != NULL) ? |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
172 strlen(pws_file->error.msg) + 1 : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
173 va_start(args, fmt); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
174 va_copy(args2, args); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
175 error_len = vsnprintf(NULL, 0, fmt, args); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
176 pws_file->error.msg = pws_alloc(error_len + 1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
177 if (pws_file->error.msg == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
178 va_end(args2); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
179 va_end(args); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
180 return; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
181 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
182 vsnprintf(pws_file->error.msg, error_len + 1, fmt, args2); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
183 va_end(args2); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
184 va_end(args); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
185 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
186 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
187 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
188 read_buf(struct pws_file_ctx *ctx, unsigned char *buf, size_t buf_size) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
189 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
190 if (ctx->fp != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
191 if (fread(buf, 1, buf_size, ctx->fp) != buf_size) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
192 if (ferror(ctx->fp) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
193 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
194 } else if (feof(ctx->fp) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
195 return (1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
196 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
197 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
198 } else { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
199 PWS_ASSERT(ctx->mem != NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
200 if (ctx->mem_size - ctx->mem_pos < buf_size) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
201 return (1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
202 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
203 memcpy(buf, &ctx->mem[ctx->mem_pos], buf_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
204 ctx->mem_pos += buf_size; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
205 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
206 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
207 return (0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
208 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
209 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
210 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
211 write_buf(struct pws_file_ctx *ctx, const unsigned char *buf, size_t buf_size) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
212 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
213 size_t remaining; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
214 unsigned char *tmp; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
215 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
216 if (ctx->fp != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
217 if (fwrite(buf, 1, buf_size, ctx->fp) != buf_size) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
218 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
219 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
220 if (fflush(ctx->fp) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
221 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
222 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
223 } else { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
224 remaining = ctx->mem_size - ctx->mem_pos; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
225 if (remaining < buf_size) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
226 tmp = pws_realloc(ctx->mem, ctx->mem_size + |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
227 (buf_size - remaining)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
228 if (tmp == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
229 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
230 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
231 ctx->mem = tmp; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
232 ctx->mem_size += (buf_size - remaining); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
233 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
234 memcpy(&ctx->mem[ctx->mem_pos], buf, buf_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
235 ctx->mem_pos += buf_size; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
236 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
237 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
238 return (0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
239 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
240 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
241 static void |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
242 pws_file_clear(struct pws3_file *pws_file) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
243 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
244 size_t i; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
245 struct pws3_field *empty_group_field; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
246 struct pws3_field *empty_group_field_tmp; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
247 struct pws3_record *record; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
248 struct pws3_record *record_tmp; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
249 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
250 for (i = 0x00; i <= 0xff; i++) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
251 pws3_field_destroy(pws_file->fields[i]); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
252 pws_file->fields[i] = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
253 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
254 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
255 RB_FOREACH_SAFE(empty_group_field, empty_groups_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
256 pws_file->empty_groups_tree, empty_group_field_tmp) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
257 pws3_field_destroy(RB_REMOVE(empty_groups_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
258 pws_file->empty_groups_tree, empty_group_field)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
259 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
260 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
261 RB_FOREACH_SAFE(record, records_tree, pws_file->records_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
262 record_tmp) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
263 pws3_record_destroy(RB_REMOVE(records_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
264 pws_file->records_tree, record)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
265 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
266 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
267 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
268 void |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
269 pws3_file_destroy(struct pws3_file *pws_file) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
270 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
271 if (pws_file == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
272 return; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
273 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
274 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
275 pws_free(pws_file->error.msg, (pws_file->error.msg != NULL) ? |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
276 strlen(pws_file->error.msg) + 1 : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
277 pws_file_clear(pws_file); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
278 pws_free(pws_file->empty_groups_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
279 sizeof (struct empty_groups_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
280 pws_free(pws_file->records_tree, sizeof (struct records_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
281 pws_free(pws_file, sizeof (struct pws3_file)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
282 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
283 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
284 struct pws3_file * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
285 pws3_file_create(void) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
286 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
287 struct pws3_field *version_field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
288 struct pws3_file *pws_file = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
289 size_t i; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
290 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
291 /* version field is mandatory */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
292 version_field = pws3_field_create(1, PWS3_HEADER_FIELD_VERSION); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
293 if (version_field == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
294 goto err; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
295 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
296 pws3_field_set_uint16(version_field, PWS3_VERSION); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
297 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
298 pws_file = pws_alloc(sizeof (struct pws3_file)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
299 if (pws_file == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
300 goto err; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
301 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
302 for (i = 0x00; i <= 0xff; i++) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
303 pws_file->fields[i] = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
304 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
305 pws_file->empty_groups_tree = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
306 pws_file->records_tree = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
307 pws_file->error.errnum = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
308 pws_file->error.code = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
309 pws_file->error.msg = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
310 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
311 pws_file->empty_groups_tree = |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
312 pws_alloc(sizeof (struct empty_groups_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
313 if (pws_file->empty_groups_tree == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
314 goto err; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
315 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
316 RB_INIT(pws_file->empty_groups_tree); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
317 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
318 pws_file->records_tree = pws_alloc(sizeof (struct records_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
319 if (pws_file->records_tree == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
320 goto err; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
321 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
322 RB_INIT(pws_file->records_tree); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
323 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
324 pws3_file_set_header_field(pws_file, version_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
325 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
326 return (pws_file); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
327 err: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
328 pws3_field_destroy(version_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
329 if (pws_file != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
330 pws_free(pws_file->records_tree, sizeof (struct records_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
331 pws_free(pws_file->empty_groups_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
332 sizeof (struct empty_groups_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
333 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
334 pws_free(pws_file, sizeof (struct pws3_file)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
335 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
336 return (NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
337 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
338 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
339 enum pws_error_code |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
340 pws3_file_get_error_code(struct pws3_file *pws_file) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
341 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
342 return (pws_file->error.code); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
343 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
344 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
345 const char * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
346 pws3_file_get_error_message(struct pws3_file *pws_file) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
347 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
348 return ((pws_file->error.msg != NULL) ? pws_file->error.msg : ""); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
349 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
350 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
351 static void |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
352 stretch_key(unsigned char *stretched_key, uint32_t n_iter, const char *key, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
353 size_t key_size, const unsigned char *salt, size_t salt_size) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
354 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
355 uint32_t i; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
356 struct sha256_ctx md_ctx; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
357 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
358 sha256_init(&md_ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
359 sha256_update(&md_ctx, key_size, (uint8_t *)key); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
360 sha256_update(&md_ctx, salt_size, salt); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
361 sha256_digest(&md_ctx, SHA256_DIGEST_SIZE, stretched_key); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
362 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
363 for (i = 0; i < n_iter; i++) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
364 sha256_update(&md_ctx, SHA256_DIGEST_SIZE, stretched_key); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
365 sha256_digest(&md_ctx, SHA256_DIGEST_SIZE, stretched_key); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
366 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
367 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
368 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
369 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
370 read_metadata(struct pws_file_ctx *ctx, const char *password) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
371 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
372 int retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
373 unsigned char buf[METADATA_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
374 unsigned char *p = buf; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
375 unsigned char *stretched_key = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
376 unsigned char *key_k = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
377 unsigned char *key_l = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
378 int read_retval; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
379 unsigned char salt[SALT_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
380 unsigned char key_digest[SHA256_DIGEST_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
381 struct sha256_ctx md_ctx; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
382 struct twofish_ctx cipher_ctx; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
383 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
384 stretched_key = pws_secure_alloc(SHA256_DIGEST_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
385 if (stretched_key == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
386 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
387 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
388 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
389 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
390 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
391 key_k = pws_secure_alloc(KEY_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
392 if (key_k == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
393 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
394 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
395 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
396 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
397 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
398 key_l = pws_secure_alloc(KEY_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
399 if (key_l == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
400 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
401 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
402 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
403 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
404 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
405 read_retval = read_buf(ctx, buf, sizeof (buf)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
406 if (read_retval == 1) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
407 pws_set_error(ctx->pws_file, PWS_ERR_TRUNCATED_FILE, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
408 "unexpected end of file"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
409 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
410 } else if (read_retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
411 pws_set_system_error(ctx->pws_file, PWS_ERR_IO_ERROR, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
412 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
413 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
414 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
415 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
416 /* check tag */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
417 if (memcmp(p, psafe3_tag, sizeof (psafe3_tag)) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
418 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
419 "unknown filetype"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
420 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
421 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
422 p += sizeof (psafe3_tag); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
423 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
424 /* salt */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
425 memcpy(salt, p, SALT_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
426 p += SALT_SIZE; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
427 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
428 /* iterations */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
429 memcpy(&ctx->n_iter, p, 4); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
430 ctx->n_iter = le32toh(ctx->n_iter); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
431 if ((ctx->n_iter < 1) || (ctx->n_iter > MAX_ITER)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
432 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
433 "invalid number of iterations: %d", ctx->n_iter); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
434 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
435 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
436 p += 4; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
437 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
438 /* verify password */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
439 stretch_key(stretched_key, ctx->n_iter, password, strlen(password), |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
440 salt, SALT_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
441 sha256_init(&md_ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
442 sha256_update(&md_ctx, SHA256_DIGEST_SIZE, stretched_key); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
443 sha256_digest(&md_ctx, SHA256_DIGEST_SIZE, key_digest); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
444 if (memcmp(key_digest, p, SHA256_DIGEST_SIZE) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
445 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
446 "wrong password"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
447 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
448 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
449 p += SHA256_DIGEST_SIZE; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
450 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
451 /* decrypt keys */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
452 twofish_set_key(&cipher_ctx, KEY_SIZE, stretched_key); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
453 twofish_decrypt(&cipher_ctx, KEY_SIZE, key_k, p); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
454 p += KEY_SIZE; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
455 twofish_decrypt(&cipher_ctx, KEY_SIZE, key_l, p); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
456 p += KEY_SIZE; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
457 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
458 /* set key for decryption */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
459 twofish_set_key(&ctx->cipher_ctx.ctx, KEY_SIZE, key_k); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
460 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
461 /* set IV */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
462 CBC_SET_IV(&ctx->cipher_ctx, p); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
463 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
464 /* set key for HMAC */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
465 HMAC_SET_KEY(&ctx->hmac_ctx, &nettle_sha256, KEY_SIZE, key_l); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
466 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
467 retval = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
468 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
469 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
470 pws_secure_free(stretched_key, (stretched_key != NULL) ? |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
471 SHA256_DIGEST_SIZE : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
472 pws_secure_free(key_l, (key_l != NULL) ? KEY_SIZE : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
473 pws_secure_free(key_k, (key_k != NULL) ? KEY_SIZE : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
474 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
475 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
476 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
477 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
478 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
479 read_block(struct pws_file_ctx *ctx, unsigned char *block) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
480 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
481 unsigned char buf[TWOFISH_BLOCK_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
482 int read_retval; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
483 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
484 read_retval = read_buf(ctx, buf, sizeof (buf)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
485 if (read_retval == 1) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
486 pws_set_error(ctx->pws_file, PWS_ERR_TRUNCATED_FILE, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
487 "unexpected end of file"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
488 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
489 } else if (read_retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
490 pws_set_system_error(ctx->pws_file, PWS_ERR_IO_ERROR, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
491 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
492 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
493 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
494 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
495 /* reached the EOF block marking the end of encrypted records */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
496 if (memcmp(buf, eof_marker, TWOFISH_BLOCK_SIZE) == 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
497 return (1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
498 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
499 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
500 CBC_DECRYPT(&ctx->cipher_ctx, twofish_decrypt, TWOFISH_BLOCK_SIZE, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
501 block, buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
502 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
503 return (0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
504 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
505 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
506 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
507 read_field(struct pws_file_ctx *ctx, struct pws3_field **fieldp, int is_header) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
508 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
509 int retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
510 enum pws_data_type data_type; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
511 struct pws3_field *field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
512 unsigned char *block_buf = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
513 unsigned char *p; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
514 int read_retval; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
515 unsigned char *field_buf = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
516 uint32_t field_size; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
517 size_t remaining; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
518 size_t field_buf_size = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
519 uint8_t field_type = 0xff; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
520 time_t data_time; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
521 uint32_t data_uint32; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
522 uint16_t data_uint16; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
523 uint8_t data_uint8; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
524 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
525 block_buf = pws_secure_alloc(TWOFISH_BLOCK_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
526 if (block_buf == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
527 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
528 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
529 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
530 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
531 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
532 next_field: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
533 p = block_buf; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
534 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
535 /* read first block */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
536 read_retval = read_block(ctx, block_buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
537 if (read_retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
538 retval = read_retval; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
539 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
540 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
541 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
542 /* determine field length */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
543 memcpy(&field_size, p, 4); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
544 remaining = field_buf_size = field_size = le32toh(field_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
545 p += 4; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
546 /* determine field type */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
547 memcpy(&field_type, p, 1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
548 p++; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
549 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
550 /* check for end of header fields or end of record */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
551 if ((is_header && (field_type == PWS3_HEADER_FIELD_END)) || |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
552 (!is_header && (field_type == PWS3_RECORD_FIELD_END))) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
553 retval = 1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
554 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
555 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
556 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
557 /* skip empty fields */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
558 if (field_size == 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
559 goto next_field; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
560 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
561 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
562 /* determine data type */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
563 data_type = pws3_field_get_data_type(&(struct pws3_field){ .is_header = |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
564 is_header, .field_type = field_type }); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
565 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
566 /* make room for a terminating \0 in text fields */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
567 if (data_type == PWS_DATA_TYPE_TEXT) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
568 field_buf_size++; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
569 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
570 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
571 /* validate field length */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
572 switch (data_type) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
573 case PWS_DATA_TYPE_UUID: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
574 if ((field_size != 0) && (field_size != PWS3_UUID_SIZE)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
575 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
576 "invalid field length"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
577 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
578 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
579 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
580 case PWS_DATA_TYPE_TIME: /* FALLTHROUGH */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
581 case PWS_DATA_TYPE_UINT32: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
582 if ((field_size != 0) && (field_size != 4)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
583 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
584 "invalid field length"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
585 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
586 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
587 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
588 case PWS_DATA_TYPE_UINT8: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
589 if ((field_size != 0) && (field_size != 1)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
590 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
591 "invalid field length"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
592 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
593 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
594 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
595 case PWS_DATA_TYPE_UINT16: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
596 if ((field_size != 0) && (field_size != 2)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
597 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
598 "invalid field length"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
599 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
600 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
601 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
602 default: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
603 /* text or bytes */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
604 if ((!is_header && |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
605 (field_type == PWS3_RECORD_FIELD_PASSWORD) && |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
606 (field_buf_size > PWS3_MAX_PASSWORD_LEN)) || |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
607 (field_buf_size > PWS3_MAX_FIELD_SIZE)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
608 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
609 "invalid field length"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
610 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
611 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
612 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
613 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
614 field = pws3_field_create(is_header, field_type); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
615 if (field == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
616 pws_set_system_error(ctx->pws_file, PWS_ERR_NO_MEMORY, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
617 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
618 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
619 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
620 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
621 /* create field */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
622 if (field_buf_size > 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
623 if (!is_header && (field_type == PWS3_RECORD_FIELD_PASSWORD)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
624 field_buf = pws_secure_alloc(field_buf_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
625 } else { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
626 field_buf = pws_alloc(field_buf_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
627 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
628 if (field_buf == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
629 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
630 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
631 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
632 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
633 memset(field_buf, 0, field_buf_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
634 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
635 memcpy(field_buf, p, MIN(remaining, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
636 (size_t)TWOFISH_BLOCK_SIZE - (p - block_buf))); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
637 remaining -= MIN(remaining, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
638 (size_t)TWOFISH_BLOCK_SIZE - (p - block_buf)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
639 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
640 while (remaining > 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
641 read_retval = read_block(ctx, block_buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
642 if (read_retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
643 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
644 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
645 memcpy(field_buf + (field_size - remaining), |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
646 block_buf, MIN(remaining, TWOFISH_BLOCK_SIZE)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
647 remaining -= MIN(remaining, TWOFISH_BLOCK_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
648 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
649 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
650 hmac_sha256_update(&ctx->hmac_ctx, field_size, field_buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
651 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
652 switch (data_type) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
653 case PWS_DATA_TYPE_UUID: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
654 retval = pws3_field_set_uuid(field, field_buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
655 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
656 case PWS_DATA_TYPE_TEXT: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
657 retval = pws3_field_set_text(field, (char *)field_buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
658 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
659 case PWS_DATA_TYPE_TIME: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
660 memcpy(&data_uint32, field_buf, 4); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
661 data_time = le32toh(data_uint32); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
662 retval = pws3_field_set_time(field, data_time); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
663 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
664 case PWS_DATA_TYPE_UINT8: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
665 memcpy(&data_uint8, field_buf, 1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
666 retval = pws3_field_set_uint8(field, data_uint8); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
667 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
668 case PWS_DATA_TYPE_UINT16: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
669 memcpy(&data_uint16, field_buf, 2); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
670 data_uint16 = le16toh(data_uint16); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
671 retval = pws3_field_set_uint16(field, data_uint16); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
672 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
673 case PWS_DATA_TYPE_UINT32: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
674 memcpy(&data_uint32, field_buf, 4); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
675 data_uint32 = le32toh(data_uint32); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
676 retval = pws3_field_set_uint32(field, data_uint32); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
677 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
678 case PWS_DATA_TYPE_BYTES: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
679 retval = pws3_field_set_bytes(field, field_buf, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
680 field_buf_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
681 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
682 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
683 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
684 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
685 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
686 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
687 retval = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
688 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
689 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
690 if (!is_header && (field_type == PWS3_RECORD_FIELD_PASSWORD)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
691 pws_secure_free(field_buf, field_buf_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
692 } else { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
693 pws_free(field_buf, field_buf_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
694 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
695 pws_secure_free(block_buf, (block_buf != NULL) ? |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
696 (size_t)TWOFISH_BLOCK_SIZE : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
697 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
698 if (retval == 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
699 *fieldp = field; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
700 } else { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
701 pws3_field_destroy(field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
702 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
703 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
704 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
705 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
706 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
707 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
708 read_header(struct pws_file_ctx *ctx) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
709 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
710 int retval; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
711 struct pws3_field *field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
712 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
713 /* the header must start with a version field */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
714 retval = read_field(ctx, &field, 1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
715 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
716 /* error or end of headers */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
717 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
718 "header does not start with a version field"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
719 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
720 } else if (field->field_type != PWS3_HEADER_FIELD_VERSION) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
721 /* header does not start with a version field */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
722 pws3_field_destroy(field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
723 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
724 "header does not start with a version field"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
725 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
726 } else if (field->value.uint16 > PWS3_VERSION) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
727 /* unsupported database version */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
728 pws3_field_destroy(field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
729 pws_set_error(ctx->pws_file, PWS_ERR_UNSUPPORTED_VERSION, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
730 "unsupported database version"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
731 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
732 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
733 pws3_file_set_header_field(ctx->pws_file, field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
734 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
735 for (;;) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
736 retval = read_field(ctx, &field, 1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
737 if (retval == 1) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
738 /* end of headers */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
739 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_HEADER, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
740 "unexpected end of headers"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
741 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
742 } else if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
743 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
744 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
745 pws3_file_set_header_field(ctx->pws_file, field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
746 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
747 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
748 return (0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
749 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
750 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
751 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
752 read_records(struct pws_file_ctx *ctx) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
753 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
754 int retval; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
755 struct pws3_record *record = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
756 struct pws3_field *field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
757 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
758 for (;;) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
759 /* |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
760 * a record must consist of at least three fields, instead of |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
761 * the first field there could also be an EOF marker |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
762 */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
763 retval = read_field(ctx, &field, 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
764 if (retval == 1) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
765 /* EOF marker */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
766 retval = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
767 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
768 } else if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
769 /* read error */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
770 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
771 } else if (field->field_type == PWS3_RECORD_FIELD_END) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
772 /* empty record */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
773 retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
774 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
775 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
776 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
777 record = pws3_record_create(); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
778 if (record == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
779 pws_set_system_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
780 errno, NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
781 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
782 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
783 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
784 pws3_record_set_field(record, field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
785 field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
786 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
787 /* read the remaining fileds */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
788 for (;;) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
789 retval = read_field(ctx, &field, 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
790 if (retval == 1) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
791 /* end of record */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
792 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
793 } else if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
794 /* read error */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
795 retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
796 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
797 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
798 pws3_record_set_field(record, field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
799 field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
800 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
801 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
802 /* check whether UUID is not empty */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
803 if (pws3_record_get_field(record, PWS3_RECORD_FIELD_UUID) == |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
804 NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
805 /* record is missing mandatory fields */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
806 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_RECORD, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
807 "record is missing mandatory fields"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
808 pws3_record_destroy(record); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
809 retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
810 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
811 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
812 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
813 pws3_file_insert_record(ctx->pws_file, record); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
814 record = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
815 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
816 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
817 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
818 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
819 pws3_field_destroy(field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
820 pws3_record_destroy(record); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
821 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
822 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
823 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
824 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
825 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
826 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
827 verify_checksum(struct pws_file_ctx *ctx) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
828 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
829 int retval; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
830 unsigned char hmac_file[SHA256_DIGEST_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
831 unsigned char hmac[SHA256_DIGEST_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
832 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
833 retval = read_buf(ctx, hmac_file, sizeof (hmac_file)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
834 if (retval == 1) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
835 pws_set_error(ctx->pws_file, PWS_ERR_TRUNCATED_FILE, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
836 "unexpected end of file"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
837 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
838 } else if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
839 pws_set_system_error(ctx->pws_file, PWS_ERR_IO_ERROR, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
840 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
841 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
842 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
843 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
844 hmac_sha256_digest(&ctx->hmac_ctx, sizeof (hmac), hmac); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
845 if (memcmp(hmac_file, hmac, sizeof (hmac_file)) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
846 /* inconsistent database */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
847 pws_set_error(ctx->pws_file, PWS_ERR_INVALID_CHECKSUM, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
848 "checksum failed"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
849 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
850 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
851 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
852 return (0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
853 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
854 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
855 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
856 pws3_file_read(struct pws3_file *pws_file, const char *password, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
857 unsigned char *s, size_t n, FILE *fp) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
858 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
859 int retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
860 struct pws_file_ctx ctx = { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
861 .fp = fp, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
862 .mem = s, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
863 .mem_size = n, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
864 .mem_pos = 0, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
865 .pws_file = pws_file, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
866 }; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
867 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
868 pws_file_clear(pws_file); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
869 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
870 retval = read_metadata(&ctx, password); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
871 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
872 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
873 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
874 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
875 retval = read_header(&ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
876 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
877 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
878 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
879 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
880 retval = read_records(&ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
881 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
882 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
883 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
884 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
885 retval = verify_checksum(&ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
886 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
887 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
888 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
889 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
890 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
891 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
892 pws_file_clear(ctx.pws_file); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
893 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
894 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
895 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
896 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
897 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
898 int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
899 pws3_file_read_mem(struct pws3_file *pws_file, const char *password, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
900 unsigned char *s, size_t n) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
901 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
902 return (pws3_file_read(pws_file, password, s, n, NULL)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
903 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
904 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
905 int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
906 pws3_file_read_stream(struct pws3_file *pws_file, const char *password, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
907 FILE *fp) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
908 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
909 return (pws3_file_read(pws_file, password, NULL, 0, fp)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
910 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
911 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
912 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
913 write_metadata(struct pws_file_ctx *ctx, const char *password) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
914 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
915 int retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
916 unsigned char *stretched_key = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
917 unsigned char *key_k = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
918 unsigned char *key_l = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
919 unsigned char metadata[METADATA_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
920 unsigned char *p = metadata; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
921 unsigned char *salt; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
922 uint32_t n_iter_le; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
923 struct sha256_ctx md_ctx; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
924 unsigned char *b1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
925 unsigned char *b3; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
926 unsigned char *iv; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
927 struct twofish_ctx cipher_ctx; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
928 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
929 stretched_key = pws_secure_alloc(SHA256_DIGEST_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
930 if (stretched_key == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
931 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
932 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
933 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
934 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
935 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
936 key_k = pws_secure_alloc(KEY_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
937 if (key_k == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
938 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
939 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
940 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
941 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
942 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
943 key_l = pws_secure_alloc(KEY_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
944 if (key_l == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
945 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
946 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
947 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
948 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
949 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
950 /* generate new keys */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
951 if (pws_random_bytes(key_k, KEY_SIZE) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
952 pws_set_error(ctx->pws_file, PWS_ERR_GENERIC_ERROR, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
953 "failed to generate key"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
954 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
955 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
956 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
957 if (pws_random_bytes(key_l, KEY_SIZE) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
958 pws_set_error(ctx->pws_file, PWS_ERR_GENERIC_ERROR, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
959 "failed to generate key"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
960 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
961 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
962 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
963 /* tag */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
964 memcpy(p, psafe3_tag, sizeof (psafe3_tag)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
965 p += sizeof (psafe3_tag); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
966 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
967 /* generate new salt */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
968 salt = p; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
969 if (pws_random_bytes(salt, SALT_SIZE) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
970 pws_set_error(ctx->pws_file, PWS_ERR_GENERIC_ERROR, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
971 "failed to generate salt"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
972 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
973 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
974 p += SALT_SIZE; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
975 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
976 /* number of iterations */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
977 n_iter_le = htole32(ctx->n_iter); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
978 memcpy(p, &n_iter_le, 4); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
979 p += 4; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
980 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
981 /* stretch, hash password */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
982 stretch_key(stretched_key, ctx->n_iter, password, strlen(password), |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
983 salt, SALT_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
984 sha256_init(&md_ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
985 sha256_update(&md_ctx, SHA256_DIGEST_SIZE, stretched_key); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
986 sha256_digest(&md_ctx, SHA256_DIGEST_SIZE, p); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
987 p += SHA256_DIGEST_SIZE; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
988 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
989 b1 = p; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
990 p += KEY_SIZE; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
991 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
992 b3 = p; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
993 p += KEY_SIZE; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
994 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
995 /* generate IV */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
996 iv = p; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
997 if (pws_random_bytes(iv, TWOFISH_BLOCK_SIZE) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
998 pws_set_error(ctx->pws_file, PWS_ERR_GENERIC_ERROR, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
999 "failed to generate IV"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1000 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1001 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1002 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1003 /* encrypt keys */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1004 twofish_set_key(&cipher_ctx, KEY_SIZE, stretched_key); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1005 twofish_encrypt(&cipher_ctx, KEY_SIZE, b1, key_k); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1006 twofish_encrypt(&cipher_ctx, KEY_SIZE, b3, key_l); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1007 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1008 /* set key for decryption */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1009 twofish_set_key(&ctx->cipher_ctx.ctx, KEY_SIZE, key_k); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1010 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1011 /* set IV */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1012 CBC_SET_IV(&ctx->cipher_ctx, p); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1013 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1014 /* set key for HMAC */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1015 hmac_sha256_set_key(&ctx->hmac_ctx, KEY_SIZE, key_l); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1016 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1017 /* write metadata */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1018 if (write_buf(ctx, metadata, sizeof (metadata)) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1019 pws_set_system_error(ctx->pws_file, PWS_ERR_IO_ERROR, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1020 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1021 retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1022 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1023 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1024 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1025 retval = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1026 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1027 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1028 pws_secure_free(key_k, (key_k != NULL) ? KEY_SIZE : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1029 pws_secure_free(key_l, (key_l != NULL) ? KEY_SIZE : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1030 pws_secure_free(stretched_key, (stretched_key != NULL) ? |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1031 SHA256_DIGEST_SIZE : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1032 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1033 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1034 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1035 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1036 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1037 write_block(struct pws_file_ctx *ctx, unsigned char *block) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1038 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1039 unsigned char buf[TWOFISH_BLOCK_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1040 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1041 CBC_ENCRYPT(&ctx->cipher_ctx, twofish_encrypt, sizeof (buf), buf, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1042 block); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1043 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1044 if (write_buf(ctx, buf, sizeof (buf)) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1045 pws_set_system_error(ctx->pws_file, PWS_ERR_IO_ERROR, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1046 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1047 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1048 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1049 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1050 return (0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1051 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1052 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1053 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1054 write_field(struct pws_file_ctx *ctx, struct pws3_field *field) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1055 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1056 int retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1057 unsigned char *buf = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1058 unsigned char *p; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1059 unsigned char *field_data; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1060 enum pws_data_type data_type; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1061 size_t blocks = (field->size + 4 + 1) / TWOFISH_BLOCK_SIZE + |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1062 ((field->size + 4 + 1) % TWOFISH_BLOCK_SIZE != 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1063 size_t i; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1064 size_t j; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1065 uint32_t len_le; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1066 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1067 buf = pws_secure_alloc(TWOFISH_BLOCK_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1068 if (buf == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1069 pws_set_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1070 "out of memory"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1071 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1072 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1073 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1074 data_type = pws3_field_get_data_type(field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1075 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1076 for (i = 0, j = 0; i < blocks; i++) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1077 p = field_data = buf; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1078 if (pws_random_bytes(buf, TWOFISH_BLOCK_SIZE) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1079 pws_set_error(ctx->pws_file, PWS_ERR_GENERIC_ERROR, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1080 "could not get random numbers"); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1081 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1082 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1083 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1084 /* the first block of the field contains the length and type */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1085 if (i == 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1086 len_le = htole32(field->size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1087 memcpy(p, &len_le, 4); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1088 p += 4; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1089 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1090 *p = field->field_type; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1091 p++; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1092 field_data = p; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1093 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1094 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1095 while ((j < field->size) && |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1096 (p - buf < (ptrdiff_t)TWOFISH_BLOCK_SIZE)) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1097 switch (data_type) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1098 case PWS_DATA_TYPE_UINT8: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1099 *p = field->value.uint8; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1100 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1101 case PWS_DATA_TYPE_UINT16: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1102 /* little endian */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1103 *p = (field->value.uint16 >> (8 * j)) & 0xff; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1104 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1105 case PWS_DATA_TYPE_TIME: /* FALLTHROUGH */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1106 case PWS_DATA_TYPE_UINT32: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1107 /* little endian */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1108 *p = (field->value.uint32 >> (8 * j)) & 0xff; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1109 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1110 case PWS_DATA_TYPE_TEXT: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1111 *p = field->value.text[j]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1112 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1113 case PWS_DATA_TYPE_UUID: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1114 *p = field->value.uuid[j]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1115 break; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1116 default: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1117 *p = field->value.bytes[j]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1118 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1119 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1120 p++; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1121 j++; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1122 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1123 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1124 hmac_sha256_update(&ctx->hmac_ctx, p - field_data, field_data); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1125 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1126 retval = write_block(ctx, buf); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1127 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1128 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1129 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1130 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1131 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1132 retval = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1133 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1134 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1135 pws_secure_free(buf, (buf != NULL) ? TWOFISH_BLOCK_SIZE : 0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1136 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1137 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1138 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1139 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1140 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1141 write_header(struct pws_file_ctx *ctx) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1142 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1143 int retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1144 size_t i; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1145 struct pws3_field *version_field; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1146 struct pws3_field *field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1147 struct pws3_field *end_field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1148 |
9
ec5c1b653ee6
Prevent NULL pointer dereference
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
0
diff
changeset
|
1149 end_field = pws3_field_create(1, PWS3_HEADER_FIELD_END); |
ec5c1b653ee6
Prevent NULL pointer dereference
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
0
diff
changeset
|
1150 if (end_field == NULL) { |
ec5c1b653ee6
Prevent NULL pointer dereference
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
0
diff
changeset
|
1151 pws_set_system_error(ctx->pws_file, PWS_ERR_NO_MEMORY, errno, |
ec5c1b653ee6
Prevent NULL pointer dereference
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
0
diff
changeset
|
1152 NULL); |
ec5c1b653ee6
Prevent NULL pointer dereference
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
0
diff
changeset
|
1153 goto out; |
ec5c1b653ee6
Prevent NULL pointer dereference
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
0
diff
changeset
|
1154 } |
ec5c1b653ee6
Prevent NULL pointer dereference
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
0
diff
changeset
|
1155 |
0
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1156 version_field = pws3_file_get_header_field(ctx->pws_file, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1157 PWS3_HEADER_FIELD_VERSION); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1158 if (version_field == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1159 /* add mandatory version header version_field if necessary */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1160 version_field = pws3_field_create(1, PWS3_HEADER_FIELD_VERSION); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1161 if (version_field == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1162 pws_set_system_error(ctx->pws_file, PWS_ERR_NO_MEMORY, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1163 errno, NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1164 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1165 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1166 pws3_field_set_uint16(version_field, PWS3_VERSION); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1167 pws3_file_set_header_field(ctx->pws_file, version_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1168 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1169 retval = write_field(ctx, version_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1170 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1171 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1172 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1173 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1174 for (i = 0x01; i < 0xff; i++) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1175 if (ctx->pws_file->fields[i] != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1176 retval = write_field(ctx, ctx->pws_file->fields[i]); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1177 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1178 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1179 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1180 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1181 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1182 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1183 RB_FOREACH(field, empty_groups_tree, ctx->pws_file->empty_groups_tree) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1184 retval = write_field(ctx, field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1185 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1186 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1187 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1188 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1189 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1190 retval = write_field(ctx, end_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1191 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1192 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1193 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1194 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1195 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1196 pws3_field_destroy(end_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1197 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1198 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1199 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1200 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1201 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1202 write_records(struct pws_file_ctx *ctx) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1203 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1204 int retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1205 struct pws3_field *end_field = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1206 size_t i; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1207 struct pws3_record *record; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1208 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1209 end_field = pws3_field_create(0, PWS3_RECORD_FIELD_END); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1210 if (end_field == NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1211 pws_set_system_error(ctx->pws_file, PWS_ERR_NO_MEMORY, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1212 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1213 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1214 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1215 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1216 RB_FOREACH(record, records_tree, ctx->pws_file->records_tree) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1217 /* record fields */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1218 for (i = 0x01; i < 0xff; i++) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1219 if (record->fields[i] != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1220 retval = write_field(ctx, record->fields[i]); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1221 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1222 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1223 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1224 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1225 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1226 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1227 /* end of entry marker */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1228 retval = write_field(ctx, end_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1229 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1230 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1231 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1232 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1233 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1234 /* end of file marker */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1235 if (write_buf(ctx, eof_marker, sizeof (eof_marker)) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1236 pws_set_system_error(ctx->pws_file, PWS_ERR_IO_ERROR, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1237 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1238 retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1239 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1240 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1241 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1242 retval = 0; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1243 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1244 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1245 pws3_field_destroy(end_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1246 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1247 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1248 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1249 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1250 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1251 write_checksum(struct pws_file_ctx *ctx) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1252 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1253 unsigned char hmac[SHA256_DIGEST_SIZE]; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1254 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1255 hmac_sha256_digest(&ctx->hmac_ctx, sizeof (hmac), hmac); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1256 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1257 if (write_buf(ctx, hmac, sizeof (hmac)) != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1258 pws_set_system_error(ctx->pws_file, PWS_ERR_IO_ERROR, errno, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1259 NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1260 return (-1); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1261 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1262 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1263 return (0); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1264 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1265 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1266 static int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1267 pws3_file_write(struct pws3_file *pws_file, const char *password, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1268 uint32_t n_iter, unsigned char **memp, size_t *mem_sizep, FILE *fp) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1269 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1270 int retval = -1; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1271 struct pws_file_ctx ctx = { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1272 .fp = fp, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1273 .pws_file = pws_file, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1274 .n_iter = n_iter |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1275 }; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1276 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1277 retval = write_metadata(&ctx, password); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1278 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1279 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1280 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1281 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1282 retval = write_header(&ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1283 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1284 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1285 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1286 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1287 retval = write_records(&ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1288 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1289 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1290 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1291 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1292 retval = write_checksum(&ctx); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1293 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1294 goto out; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1295 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1296 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1297 if (memp != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1298 *memp = ctx.mem; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1299 *mem_sizep = ctx.mem_size; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1300 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1301 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1302 out: |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1303 if (retval != 0) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1304 pws_free(ctx.mem, ctx.mem_size); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1305 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1306 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1307 return (retval); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1308 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1309 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1310 int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1311 pws3_file_write_mem(struct pws3_file *pws_file, const char *password, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1312 uint32_t n_iter, unsigned char **memp, size_t *mem_sizep) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1313 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1314 PWS_ASSERT(memp != NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1315 PWS_ASSERT(mem_sizep != NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1316 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1317 return (pws3_file_write(pws_file, password, n_iter, memp, mem_sizep, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1318 NULL)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1319 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1320 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1321 int |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1322 pws3_file_write_stream(struct pws3_file *pws_file, const char *password, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1323 uint32_t n_iter, FILE *fp) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1324 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1325 PWS_ASSERT(fp != NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1326 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1327 return (pws3_file_write(pws_file, password, n_iter, NULL, NULL, fp)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1328 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1329 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1330 void |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1331 pws3_file_set_header_field(struct pws3_file *pws_file, struct pws3_field *field) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1332 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1333 PWS_ASSERT(pws3_field_is_header(field)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1334 PWS_ASSERT((pws3_field_get_data_type(field) != PWS_DATA_TYPE_TEXT) || |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1335 (field->value.text != NULL)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1336 PWS_ASSERT((pws3_field_get_data_type(field) != PWS_DATA_TYPE_BYTES) || |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1337 (field->value.bytes != NULL)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1338 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1339 if (field->field_type == PWS3_HEADER_FIELD_EMPTY_GROUPS) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1340 pws3_file_insert_empty_group(pws_file, field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1341 return; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1342 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1343 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1344 pws3_field_destroy(pws3_file_remove_header_field(pws_file, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1345 field->field_type)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1346 pws_file->fields[field->field_type] = field; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1347 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1348 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1349 struct pws3_field * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1350 pws3_file_get_header_field(struct pws3_file *pws_file, uint8_t field_type) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1351 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1352 if (field_type == PWS3_HEADER_FIELD_EMPTY_GROUPS) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1353 return (pws3_file_first_empty_group(pws_file)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1354 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1355 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1356 return (pws_file->fields[field_type]); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1357 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1358 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1359 struct pws3_field * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1360 pws3_file_remove_header_field(struct pws3_file *pws_file, uint8_t field_type) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1361 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1362 struct pws3_field *field; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1363 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1364 if (field_type == PWS3_HEADER_FIELD_EMPTY_GROUPS) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1365 return (NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1366 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1367 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1368 field = pws3_file_get_header_field(pws_file, field_type); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1369 pws_file->fields[field_type] = NULL; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1370 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1371 return (field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1372 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1373 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1374 void |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1375 pws3_file_insert_empty_group(struct pws3_file *pws_file, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1376 struct pws3_field *field) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1377 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1378 const char *group_name; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1379 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1380 PWS_ASSERT(pws3_field_is_header(field)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1381 PWS_ASSERT(pws3_field_get_type(field) == |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1382 PWS3_HEADER_FIELD_EMPTY_GROUPS); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1383 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1384 group_name = pws3_field_get_text(field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1385 pws3_field_destroy(pws3_file_remove_empty_group(pws_file, group_name)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1386 RB_INSERT(empty_groups_tree, pws_file->empty_groups_tree, field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1387 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1388 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1389 struct pws3_field * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1390 pws3_file_get_empty_group(struct pws3_file *pws_file, const char *group_name) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1391 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1392 return (RB_FIND(empty_groups_tree, pws_file->empty_groups_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1393 (&(struct pws3_field){ .is_header = 1, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1394 .field_type = PWS3_HEADER_FIELD_EMPTY_GROUPS, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1395 .value.text = (char *)group_name }))); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1396 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1397 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1398 struct pws3_field * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1399 pws3_file_remove_empty_group(struct pws3_file *pws_file, const char *group_name) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1400 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1401 struct pws3_field *field; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1402 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1403 field = RB_FIND(empty_groups_tree, pws_file->empty_groups_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1404 (&(struct pws3_field){ .is_header = 1, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1405 .field_type = PWS3_HEADER_FIELD_EMPTY_GROUPS, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1406 .value.text = (char *)group_name })); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1407 if (field != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1408 RB_REMOVE(empty_groups_tree, pws_file->empty_groups_tree, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1409 field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1410 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1411 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1412 return (field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1413 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1414 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1415 struct pws3_field * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1416 pws3_file_first_empty_group(struct pws3_file *pws_file) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1417 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1418 return (RB_MIN(empty_groups_tree, pws_file->empty_groups_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1419 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1420 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1421 struct pws3_field * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1422 pws3_file_last_empty_group(struct pws3_file *pws_file) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1423 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1424 return (RB_MAX(empty_groups_tree, pws_file->empty_groups_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1425 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1426 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1427 struct pws3_field * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1428 pws3_file_next_empty_group(struct pws3_file *pws_file, struct pws3_field *field) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1429 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1430 return (RB_NEXT(empty_groups_tree, pws_file->empty_groups_tree, field)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1431 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1432 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1433 struct pws3_field * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1434 pws3_file_prev_empty_group(struct pws3_file *pws_file, struct pws3_field *field) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1435 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1436 return (RB_PREV(empty_groups_tree, pws_file->empty_groups_tree, field)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1437 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1438 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1439 void |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1440 pws3_file_insert_record(struct pws3_file *pws_file, struct pws3_record *record) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1441 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1442 struct pws3_field *uuid_field; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1443 const unsigned char *uuid; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1444 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1445 uuid_field = pws3_record_get_field(record, PWS3_RECORD_FIELD_UUID); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1446 PWS_ASSERT(uuid_field != NULL); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1447 uuid = pws3_field_get_uuid(uuid_field); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1448 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1449 /* replace existing record */ |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1450 pws3_record_destroy(pws3_file_remove_record(pws_file, uuid)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1451 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1452 RB_INSERT(records_tree, pws_file->records_tree, record); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1453 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1454 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1455 struct pws3_record * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1456 pws3_file_get_record(struct pws3_file *pws_file, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1457 const unsigned char uuid[static PWS3_UUID_SIZE]) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1458 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1459 struct pws3_field uuid_field = { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1460 .is_header = 0, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1461 .field_type = PWS3_RECORD_FIELD_UUID |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1462 }; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1463 struct pws3_record search_record = { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1464 .fields[PWS3_RECORD_FIELD_UUID] = &uuid_field |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1465 }; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1466 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1467 memcpy(uuid_field.value.uuid, uuid, PWS3_UUID_SIZE); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1468 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1469 return (RB_FIND(records_tree, pws_file->records_tree, &search_record)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1470 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1471 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1472 struct pws3_record * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1473 pws3_file_remove_record(struct pws3_file *pws_file, |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1474 const unsigned char uuid[static PWS3_UUID_SIZE]) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1475 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1476 struct pws3_record *record; |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1477 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1478 record = pws3_file_get_record(pws_file, uuid); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1479 if (record != NULL) { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1480 RB_REMOVE(records_tree, pws_file->records_tree, record); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1481 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1482 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1483 return (record); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1484 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1485 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1486 struct pws3_record * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1487 pws3_file_first_record(struct pws3_file *pws_file) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1488 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1489 return (RB_MIN(records_tree, pws_file->records_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1490 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1491 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1492 struct pws3_record * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1493 pws3_file_last_record(struct pws3_file *pws_file) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1494 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1495 return (RB_MAX(records_tree, pws_file->records_tree)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1496 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1497 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1498 struct pws3_record * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1499 pws3_file_next_record(struct pws3_file *pws_file, struct pws3_record *record) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1500 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1501 return (RB_NEXT(records_tree, pws_file->records_tree, record)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1502 } |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1503 |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1504 struct pws3_record * |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1505 pws3_file_prev_record(struct pws3_file *pws_file, struct pws3_record *record) |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1506 { |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1507 return (RB_PREV(records_tree, pws_file->records_tree, record)); |
d541e748cfd8
Initial revision
Guido Berhoerster <guido+libpws@berhoerster.name>
parents:
diff
changeset
|
1508 } |