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