Force subkeys to be sorted in structured keys.
[u/mdw/catacomb] / key-attr.c
CommitLineData
d11a0bf7 1/* -*-c-*-
2 *
981bf127 3 * $Id: key-attr.c,v 1.4 2004/04/08 01:02:49 mdw Exp $
d11a0bf7 4 *
5 * Key attribute manipulation
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: key-attr.c,v $
981bf127 33 * Revision 1.4 2004/04/08 01:02:49 mdw
34 * key-binary.c
35 *
8c0e800f 36 * Revision 1.3 2001/06/22 19:39:43 mdw
37 * Allow tagging if the tag is owned by a deleted key.
38 *
052b36d0 39 * Revision 1.2 2000/02/12 18:21:02 mdw
40 * Overhaul of key management (again).
41 *
d11a0bf7 42 * Revision 1.1 1999/12/22 15:47:48 mdw
43 * Major key-management revision.
44 *
45 */
46
47/*----- Header files ------------------------------------------------------*/
48
49#include <ctype.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <time.h>
54
052b36d0 55#include <mLib/dstr.h>
d11a0bf7 56#include <mLib/sym.h>
57
58#include "key.h"
59
60/*----- Main code ---------------------------------------------------------*/
61
62/* --- @key_chkident@ --- *
63 *
64 * Arguments: @const char *p@ = pointer to a type string
65 *
66 * Returns: Zero if OK, -1 on error.
67 *
68 * Use: Checks whether an identification component string is OK.
69 */
70
71int key_chkident(const char *p)
72{
981bf127 73 if (!p || !*p || strlen(p) > 255)
d11a0bf7 74 return (-1);
75 while (*p) {
76 if (*p == ':' || *p == '.' || isspace((unsigned char)*p))
77 return (-1);
78 p++;
79 }
80 return (0);
81}
82
83/* --- @key_chkcomment@ --- *
84 *
85 * Arguments: @const char *p@ = pointer to a comment string
86 *
87 * Returns: Zero if OK, -1 on error.
88 *
89 * Use: Checks whether a comment string is OK.
90 */
91
92int key_chkcomment(const char *p)
93{
94 if (!p)
95 return (0);
96 if (!*p)
97 return (-1);
98 while (*p) {
99 if (*p == '\n')
100 return (-1);
101 p++;
102 }
103 return (0);
104}
105
106/* --- @key_mkattriter@ --- *
107 *
108 * Arguments: @key_attriter *i@ = pointer to attribute iterator
109 * @key *k@ = pointer to key
110 *
111 * Returns: ---
112 *
113 * Use: Initializes an attribute iterator. The attributes are
114 * returned by @key_nextattr@.
115 */
116
117void key_mkattriter(key_attriter *i, key *k)
118{
119 sym_mkiter(&i->i, &k->a);
120}
121
122/* --- @key_nextattr@ --- *
123 *
124 * Arguments: @key_attriter *i@ = pointer to attribute iterator
125 * @const char **n, **v@ = pointers to name and value
126 *
127 * Returns: Zero if no attribute available, or nonzero if returned OK.
128 *
129 * Use: Returns the next attribute.
130 */
131
132int key_nextattr(key_attriter *i, const char **n, const char **v)
133{
134 key_attr *a = sym_next(&i->i);
135 if (!a)
136 return (0);
137 *n = SYM_NAME(a);
138 *v = a->p;
139 return (1);
140}
141
142/* --- @key_getattr@ --- *
143 *
144 * Arguments: @key_file *f@ = pointer to file
145 * @key *k@ = pointer to key
146 * @const char *n@ = pointer to attribute name
147 *
148 * Returns: Pointer to attribute value, or null if not found.
149 *
150 * Use: Returns the value of a key attribute.
151 */
152
153const char *key_getattr(key_file *f, key *k, const char *n)
154{
155 key_attr *a;
156 if ((a = sym_find(&k->a, n, -1, 0, 0)) == 0)
157 return (0);
158 return (a->p);
159}
160
161/* --- @key_putattr@ --- *
162 *
163 * Arguments: @key_file *f@ = pointer to file
164 * @key *k@ = pointer to key
165 * @const char *n@ = pointer to attribute name
166 * @const char *v@ = pointer to attribute value or null
167 *
168 * Returns: Error code (one of the @KERR@ constants).
169 *
170 * Use: Inserts an attribute on a key. If an attribute with the same
171 * name already exists, it is deleted. Setting a null value
172 * removes the attribute.
173 */
174
175int key_putattr(key_file *f, key *k, const char *n, const char *v)
176{
177 key_attr *a;
178 unsigned found;
179
180 if (!(f->f & KF_WRITE))
181 return (KERR_READONLY);
981bf127 182 if (strlen(n) > 255)
183 return (KERR_BADATTR);
d11a0bf7 184
185 if (v) {
186 a = sym_find(&k->a, n, -1, sizeof(*a), &found);
187 if (found)
188 free(a->p);
189 a->p = xstrdup(v);
190 } else if ((a = sym_find(&k->a, n, -1, 0, 0)) != 0) {
191 free(a->p);
192 sym_remove(&k->a, a);
193 }
194
195 f->f |= KF_MODIFIED;
196 return (0);
197}
198
199/* --- @key_setcomment@ --- *
200 *
201 * Arguments: @key_file *f@ = pointer to key file block
202 * @key *k@ = pointer to key block
203 * @const char *c@ = pointer to comment to set, or zero
204 *
205 * Returns: Error code (one of the @KERR@ constants).
206 *
207 * Use: Replaces the key's current comment with a new one.
208 */
209
210int key_setcomment(key_file *f, key *k, const char *c)
211{
212 if (!(f->f & KF_WRITE))
213 return (KERR_READONLY);
214 if (key_chkcomment(c))
215 return (KERR_BADCOMMENT);
216 if (k->c)
217 free(k->c);
218 if (c)
219 k->c = xstrdup(c);
220 else
221 k->c = 0;
222 f->f |= KF_MODIFIED;
223 return (0);
224}
225
226/* --- @key_settag@ --- *
227 *
228 * Arguments: @key_file *f@ = pointer to key file block
229 * @key *k@ = pointer to key block
230 * @const char *tag@ = pointer to comment to set, or zero
231 *
232 * Returns: Error code (one of the @KERR@ constants).
233 *
234 * Use: Replaces the key's current tag with a new one.
235 */
236
237int key_settag(key_file *f, key *k, const char *tag)
238{
239 key_ref *kr;
240 unsigned found;
241
242 if (!(f->f & KF_WRITE))
243 return (KERR_READONLY);
244
245 /* --- Make sure the tag is OK --- */
246
247 if (tag && key_chkident(tag))
248 return (KERR_BADTAG);
249
250 /* --- See if the new tag is the same as the old one --- */
251
252 if ((!tag && !k->tag) ||
253 (tag && k->tag && strcmp(tag, k->tag) == 0))
254 return (0);
255
256 /* --- Allocate an entry for the new tag --- */
257
258 if (tag) {
259 kr = sym_find(&f->bytag, tag, -1, sizeof(*kr), &found);
8c0e800f 260 if (found && !KEY_EXPIRED(time(0), kr->k->del))
d11a0bf7 261 return (KERR_DUPTAG);
262 kr->k = k;
263 }
264
265 /* --- Remove any existing tag --- */
266
267 if (k->tag) {
268 kr = sym_find(&f->bytag, k->tag, -1, 0, 0);
269 assert(((void)"No bytag link", kr));
270 sym_remove(&f->bytag, kr);
271 free(k->tag);
272 }
273
274 /* --- Done --- */
275
276 f->f |= KF_MODIFIED;
277 if (tag)
278 k->tag = xstrdup(tag);
279 else
280 k->tag = 0;
281 return (0);
282}
283
284/* --- @key_fulltag@ --- *
285 *
286 * Arguments: @key *k@ = pointer to key
287 * @dstr *d@ = pointer to destination string
288 *
289 * Returns: ---
290 *
291 * Use: Emits the key's full tag, which has the form
292 * `ID:TYPE[:TAG]'. This is used in the textual file format,
293 * and to identify passphrases for locked keys.
294 */
295
296void key_fulltag(key *k, dstr *d)
297{
298 dstr_putf(d, "%08lx:%s", (unsigned long)k->id, k->type);
299 if (k->tag)
300 dstr_putf(d, ":%s", k->tag);
301}
302
303/*----- That's all, folks -------------------------------------------------*/