3 * $Id: key-misc.c,v 1.4 2004/04/08 01:02:49 mdw Exp $
5 * Simple key management
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
32 * $Log: key-misc.c,v $
33 * Revision 1.4 2004/04/08 01:02:49 mdw
36 * Revision 1.3 2001/06/22 19:39:12 mdw
37 * New interface to find out whether a key has expired. Also, a bug fix
38 * to @key_bytag@ so that it finds expired keys correctly.
40 * Revision 1.2 2000/02/12 18:21:02 mdw
41 * Overhaul of key management (again).
43 * Revision 1.1 1999/12/22 15:47:48 mdw
44 * Major key-management revision.
48 /*----- Header files ------------------------------------------------------*/
55 #include <mLib/bits.h>
56 #include <mLib/hash.h>
62 /*----- Useful macros -----------------------------------------------------*/
64 #define KEY_WRITE(f) do { \
65 if (!(f)->f & KF_WRITE) \
66 return (KERR_READONLY); \
69 #define KEY_MODIFY(f) do { (f)->f |= KF_MODIFIED; } while (0)
71 #define KEY_LOAD(n) ((n) * 2)
73 /*----- Iteration and iterators -------------------------------------------*/
75 /* --- @key_mkiter@ --- *
77 * Arguments: @key_iter *i@ = pointer to iterator object
78 * @key_file *f@ = pointer to file structure
82 * Use: Initializes a key iterator. The keys are returned by
86 void key_mkiter(key_iter
*i
, key_file
*f
)
88 HASH_MKITER(&i
->i
, &f
->byid
);
92 /* --- @key_next@ --- *
94 * Arguments: @key_iter *i@ = pointer to iterator object
96 * Returns: Pointer to next key, or null.
98 * Use: Returns the next key in some arbitrary sequence.
101 key
*key_next(key_iter
*i
)
108 } while (k
&& KEY_EXPIRED(i
->t
, k
->exp
) && KEY_EXPIRED(i
->t
, k
->del
));
112 /*----- Lookup ------------------------------------------------------------*/
114 /* --- @key_bytype@ --- *
116 * Arguments: @key_file *f@ = key file we want a key from
117 * @const char *type@ = type string for desired key
119 * Returns: Pointer to the best key to use, or null.
121 * Use: Looks up a key by its type. Returns the key with the latest
122 * expiry time. This function will not return an expired key.
125 key
*key_bytype(key_file
*f
, const char *type
)
127 time_t now
= time(0);
131 if ((kr
= sym_find(&f
->bytype
, type
, -1, 0, 0)) == 0)
133 for (k
= kr
->k
; k
&& KEY_EXPIRED(now
, k
->exp
); k
= k
->next
)
138 /* --- @key_byid@ --- *
140 * Arguments: @key_file *f@ = key file to find a key from
141 * @uint32 id@ = id to look for
143 * Returns: Key with matching id.
145 * Use: Returns a key given its id. This function will return an
146 * expired key, but not a deleted one.
149 key
*key_byid(key_file
*f
, uint32 id
)
154 bin
= HASH_BIN(&f
->byid
, id
);
155 for (b
= *bin
; b
; b
= b
->next
) {
158 if (KEY_EXPIRED(t
, k
->exp
) && KEY_EXPIRED(t
, k
->del
))
166 /* --- @key_bytag@ --- *
168 * Arguments: @key_file *f@ = key file to find a key from
169 * @const char *tag@ = pointer to tag string
171 * Returns: Key with matching id or tag.
173 * Use: Returns a key given its tag or id. This function will return
174 * an expired key, but not a deleted one.
177 key
*key_bytag(key_file
*f
, const char *tag
)
182 key_ref
*kr
= sym_find(&f
->bytag
, tag
, -1, 0, 0);
184 if (kr
&& !(KEY_EXPIRED(t
, kr
->k
->exp
) && KEY_EXPIRED(t
, kr
->k
->del
)))
186 id
= strtoul(tag
, &p
, 16);
188 return (key_byid(f
, id
));
189 return (key_bytype(f
, tag
));
192 /* --- @key_qtag@ --- *
194 * Arguments: @key_file *f@ = key file to find a key from
195 * @const char *tag@ = pointer to tag string
196 * @dstr *d@ = pointer to string for full tag name
197 * @key **k@ = where to store the key pointer
198 * @key_data **kd@ = where to store the key data pointer
200 * Returns: Zero if OK, nonzero if it failed.
202 * Use: Performs a full lookup on a qualified tag name. The tag is
203 * qualified by the names of subkeys, separated by dots. Hence,
204 * a qualified tag is ID|TAG[.TAG...]. The various result
205 * pointers can be null to indicate that the result isn't
209 int key_qtag(key_file
*f
, const char *tag
, dstr
*d
, key
**k
, key_data
**kd
)
216 /* --- Find the end of the base tag --- */
218 if ((q
= strchr(tag
, '.')) == 0)
221 DPUTM(&dd
, tag
, q
- tag
);
226 /* --- Look up the key tag --- */
228 if ((kk
= key_bytag(f
, dd
.buf
)) == 0) {
233 /* --- Set the various initial bits of result up --- */
241 /* --- Now dig through the rest of the tag --- */
245 /* --- Stick on the next bit of the fullqtag --- */
248 while (*q
&& *q
!= '.') {
258 /* --- Look up the subkey --- */
260 if (kkd
->e
!= KENC_STRUCT
) {
264 if ((kkd
= key_structfind(kkd
, dd
.buf
)) == 0)
268 /* --- Return the results --- */
278 /*----- Miscellaneous functions -------------------------------------------*/
280 /* --- @key_delete@ --- *
282 * Arguments: @key_file *f@ = pointer to file block
283 * @key *k@ = key to delete
285 * Returns: Error code (one of the @KERR@ constants).
287 * Use: Removes the given key from the list. The key file must be
288 * writable. (Due to the horridness of the data structures,
289 * deleted keys aren't actually removed, just marked so that
290 * they can't be looked up or iterated over. One upshot of
291 * this is that they don't get written back to the file when
295 int key_delete(key_file
*f
, key
*k
)
298 k
->exp
= KEXP_EXPIRE
;
299 k
->del
= KEXP_EXPIRE
;
304 /* --- @key_expired@ --- *
306 * Arguments: @key *k@ = pointer to key block
308 * Returns: Zero if the key is OK, nonzero if it's expired.
311 int key_expired(key
*k
)
313 time_t now
= time(0);
314 return (KEY_EXPIRED(now
, k
->exp
) || KEY_EXPIRED(now
, k
->del
));
317 /* --- @key_expire@ --- *
319 * Arguments: @key_file *f@ = pointer to file block
320 * @key *k@ = pointer to key block
322 * Returns: Error code (one of the @KERR@ constants).
324 * Use: Immediately marks the key as expired. It may be removed
325 * immediately, if it is no longer required, and will be removed
326 * by a tidy operation when it is no longer required. The key
327 * file must be writable.
330 int key_expire(key_file
*f
, key
*k
)
333 k
->exp
= KEXP_EXPIRE
;
334 if (k
->del
== KEXP_FOREVER
)
335 k
->del
= KEXP_EXPIRE
;
340 /* --- @key_used@ --- *
342 * Arguments: @key_file *f@ = pointer to key file
343 * @key *k@ = pointer to key block
344 * @time_t t@ = when key can be removed
346 * Returns: Zero if OK, nonzero on failure.
348 * Use: Marks a key as being required until a given time. Even
349 * though the key may expire before then (and won't be returned
350 * by type after that time), it will still be available when
351 * requested explicitly by id. The key file must be writable.
353 * The only (current) reason for failure is attempting to use
354 * a key which can expire for something which can't.
357 int key_used(key_file
*f
, key
*k
, time_t t
)
360 if (t
== KEXP_FOREVER
) {
361 if (k
->exp
!= KEXP_FOREVER
)
362 return (KERR_WILLEXPIRE
);
363 } else if (k
->del
>= t
)
371 /* --- @key_fingerprint@ --- *
373 * Arguments: @key *k@ = the key to fingerprint
374 * @ghash *h@ = the hash to use
375 * @const key_filter *kf@ = filter to apply
377 * Returns: Nonzero if the key slightly matched the filter.
379 * Use: Updates the hash context with the key contents.
382 static int abyname(const void *a
, const void *b
) {
383 key_attr
*const *x
= a
, *const *y
= b
;
384 return (strcmp(SYM_NAME(*x
), SYM_NAME(*y
)));
387 int key_fingerprint(key
*k
, ghash
*h
, const key_filter
*kf
)
396 if (!key_encode(&k
->k
, &d
, kf
))
399 GH_HASH(h
, d
.buf
, d
.len
);
400 for (n
= 0, sym_mkiter(&ai
, &k
->a
); (a
= sym_next(&ai
)) != 0; n
++);
402 v
= xmalloc(n
* sizeof(*v
));
403 for (i
= 0, sym_mkiter(&ai
, &k
->a
); (a
= sym_next(&ai
)) != 0; i
++)
405 qsort(v
, n
, sizeof(*v
), abyname
);
406 len
= strlen(k
->type
); STORE8(b
, len
);
407 GH_HASH(h
, b
, 1); GH_HASH(h
, k
->type
, len
);
408 for (i
= 0; i
< n
; i
++) {
410 len
= strlen(SYM_NAME(a
)); STORE8(b
, len
);
411 GH_HASH(h
, b
, 1); GH_HASH(h
, SYM_NAME(a
), len
);
412 len
= strlen(a
->p
); STORE16(b
, len
);
413 GH_HASH(h
, b
, 2); GH_HASH(h
, a
->p
, len
);
422 /*----- That's all, folks -------------------------------------------------*/