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