key-data.[ch] (key_copydata): New function copies filtered key data.
[u/mdw/catacomb] / key-attr.c
CommitLineData
d11a0bf7 1/* -*-c-*-
2 *
12ed8a1f 3 * $Id$
d11a0bf7 4 *
5 * Key attribute manipulation
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
45c0fd36 10/*----- Licensing notice --------------------------------------------------*
d11a0bf7 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.
45c0fd36 18 *
d11a0bf7 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.
45c0fd36 23 *
d11a0bf7 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
d11a0bf7 30/*----- Header files ------------------------------------------------------*/
31
32#include <ctype.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <time.h>
37
052b36d0 38#include <mLib/dstr.h>
d11a0bf7 39#include <mLib/sym.h>
40
41#include "key.h"
42
43/*----- Main code ---------------------------------------------------------*/
44
45/* --- @key_chkident@ --- *
46 *
47 * Arguments: @const char *p@ = pointer to a type string
48 *
49 * Returns: Zero if OK, -1 on error.
50 *
51 * Use: Checks whether an identification component string is OK.
52 */
53
54int key_chkident(const char *p)
55{
981bf127 56 if (!p || !*p || strlen(p) > 255)
d11a0bf7 57 return (-1);
58 while (*p) {
59 if (*p == ':' || *p == '.' || isspace((unsigned char)*p))
60 return (-1);
61 p++;
62 }
63 return (0);
64}
65
66/* --- @key_chkcomment@ --- *
67 *
68 * Arguments: @const char *p@ = pointer to a comment string
69 *
70 * Returns: Zero if OK, -1 on error.
71 *
72 * Use: Checks whether a comment string is OK.
73 */
74
75int key_chkcomment(const char *p)
76{
77 if (!p)
78 return (0);
79 if (!*p)
80 return (-1);
81 while (*p) {
82 if (*p == '\n')
83 return (-1);
84 p++;
85 }
86 return (0);
87}
88
89/* --- @key_mkattriter@ --- *
90 *
91 * Arguments: @key_attriter *i@ = pointer to attribute iterator
92 * @key *k@ = pointer to key
93 *
94 * Returns: ---
95 *
96 * Use: Initializes an attribute iterator. The attributes are
97 * returned by @key_nextattr@.
98 */
99
100void key_mkattriter(key_attriter *i, key *k)
101{
102 sym_mkiter(&i->i, &k->a);
103}
104
105/* --- @key_nextattr@ --- *
106 *
107 * Arguments: @key_attriter *i@ = pointer to attribute iterator
108 * @const char **n, **v@ = pointers to name and value
109 *
110 * Returns: Zero if no attribute available, or nonzero if returned OK.
111 *
112 * Use: Returns the next attribute.
113 */
114
115int key_nextattr(key_attriter *i, const char **n, const char **v)
116{
117 key_attr *a = sym_next(&i->i);
118 if (!a)
119 return (0);
9c5a3dd8 120 if (n) *n = SYM_NAME(a);
121 if (v) *v = a->p;
d11a0bf7 122 return (1);
123}
124
125/* --- @key_getattr@ --- *
126 *
127 * Arguments: @key_file *f@ = pointer to file
128 * @key *k@ = pointer to key
129 * @const char *n@ = pointer to attribute name
130 *
131 * Returns: Pointer to attribute value, or null if not found.
132 *
133 * Use: Returns the value of a key attribute.
134 */
135
136const char *key_getattr(key_file *f, key *k, const char *n)
137{
138 key_attr *a;
139 if ((a = sym_find(&k->a, n, -1, 0, 0)) == 0)
140 return (0);
141 return (a->p);
142}
143
144/* --- @key_putattr@ --- *
145 *
146 * Arguments: @key_file *f@ = pointer to file
147 * @key *k@ = pointer to key
148 * @const char *n@ = pointer to attribute name
149 * @const char *v@ = pointer to attribute value or null
150 *
151 * Returns: Error code (one of the @KERR@ constants).
152 *
153 * Use: Inserts an attribute on a key. If an attribute with the same
154 * name already exists, it is deleted. Setting a null value
155 * removes the attribute.
156 */
157
158int key_putattr(key_file *f, key *k, const char *n, const char *v)
159{
160 key_attr *a;
161 unsigned found;
162
163 if (!(f->f & KF_WRITE))
164 return (KERR_READONLY);
981bf127 165 if (strlen(n) > 255)
166 return (KERR_BADATTR);
d11a0bf7 167
168 if (v) {
169 a = sym_find(&k->a, n, -1, sizeof(*a), &found);
170 if (found)
12ed8a1f 171 xfree(a->p);
d11a0bf7 172 a->p = xstrdup(v);
173 } else if ((a = sym_find(&k->a, n, -1, 0, 0)) != 0) {
12ed8a1f 174 xfree(a->p);
d11a0bf7 175 sym_remove(&k->a, a);
176 }
177
178 f->f |= KF_MODIFIED;
179 return (0);
180}
181
ef13e9a4 182/* --- @key_setkeydata@ --- *
183 *
184 * Arguments: @key_file *kf@ = pointer to key file
185 * @key *k@ = pointer to key
186 * @key_data *kd@ = new key data
187 *
188 * Returns: Zero on success, or a @KERR_@ error code on failure.
189 *
190 * Use: Sets the key data for a key.
191 */
192
193int key_setkeydata(key_file *kf, key *k, key_data *kd)
194{
195 if (!(kf->f & KF_WRITE))
196 return (KERR_READONLY);
ef13e9a4 197 key_incref(kd);
21dfa64d 198 key_drop(k->k);
ef13e9a4 199 k->k = kd;
200 kf->f |= KF_MODIFIED;
201 return (0);
202}
203
d11a0bf7 204/* --- @key_setcomment@ --- *
205 *
206 * Arguments: @key_file *f@ = pointer to key file block
207 * @key *k@ = pointer to key block
208 * @const char *c@ = pointer to comment to set, or zero
209 *
210 * Returns: Error code (one of the @KERR@ constants).
211 *
212 * Use: Replaces the key's current comment with a new one.
213 */
214
215int key_setcomment(key_file *f, key *k, const char *c)
216{
217 if (!(f->f & KF_WRITE))
218 return (KERR_READONLY);
219 if (key_chkcomment(c))
220 return (KERR_BADCOMMENT);
221 if (k->c)
12ed8a1f 222 xfree(k->c);
d11a0bf7 223 if (c)
224 k->c = xstrdup(c);
225 else
226 k->c = 0;
227 f->f |= KF_MODIFIED;
228 return (0);
229}
230
231/* --- @key_settag@ --- *
232 *
233 * Arguments: @key_file *f@ = pointer to key file block
234 * @key *k@ = pointer to key block
235 * @const char *tag@ = pointer to comment to set, or zero
236 *
237 * Returns: Error code (one of the @KERR@ constants).
238 *
239 * Use: Replaces the key's current tag with a new one.
240 */
241
242int key_settag(key_file *f, key *k, const char *tag)
243{
244 key_ref *kr;
245 unsigned found;
246
247 if (!(f->f & KF_WRITE))
248 return (KERR_READONLY);
249
250 /* --- Make sure the tag is OK --- */
251
252 if (tag && key_chkident(tag))
253 return (KERR_BADTAG);
254
255 /* --- See if the new tag is the same as the old one --- */
256
257 if ((!tag && !k->tag) ||
258 (tag && k->tag && strcmp(tag, k->tag) == 0))
259 return (0);
260
261 /* --- Allocate an entry for the new tag --- */
262
263 if (tag) {
264 kr = sym_find(&f->bytag, tag, -1, sizeof(*kr), &found);
8c0e800f 265 if (found && !KEY_EXPIRED(time(0), kr->k->del))
d11a0bf7 266 return (KERR_DUPTAG);
267 kr->k = k;
268 }
269
270 /* --- Remove any existing tag --- */
271
272 if (k->tag) {
273 kr = sym_find(&f->bytag, k->tag, -1, 0, 0);
274 assert(((void)"No bytag link", kr));
275 sym_remove(&f->bytag, kr);
12ed8a1f 276 xfree(k->tag);
d11a0bf7 277 }
278
279 /* --- Done --- */
280
281 f->f |= KF_MODIFIED;
282 if (tag)
283 k->tag = xstrdup(tag);
284 else
285 k->tag = 0;
286 return (0);
287}
288
289/* --- @key_fulltag@ --- *
290 *
291 * Arguments: @key *k@ = pointer to key
292 * @dstr *d@ = pointer to destination string
293 *
294 * Returns: ---
295 *
296 * Use: Emits the key's full tag, which has the form
297 * `ID:TYPE[:TAG]'. This is used in the textual file format,
298 * and to identify passphrases for locked keys.
299 */
300
301void key_fulltag(key *k, dstr *d)
302{
303 dstr_putf(d, "%08lx:%s", (unsigned long)k->id, k->type);
304 if (k->tag)
305 dstr_putf(d, ":%s", k->tag);
306}
307
308/*----- That's all, folks -------------------------------------------------*/