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