b10879acc1b4cb1ffb3ada7f7fb815b2f1af8f41
3 * Simple key management
5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
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.
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.
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,
28 /*----- Header files ------------------------------------------------------*/
35 #include <mLib/bits.h>
36 #include <mLib/hash.h>
37 #include <mLib/macros.h>
43 /*----- Useful macros -----------------------------------------------------*/
45 #define KEY_WRITE(f) do { \
46 if (!((f)->f & KF_WRITE)) \
47 return (KERR_READONLY); \
50 #define KEY_MODIFY(f) do { (f)->f |= KF_MODIFIED; } while (0)
52 #define KEY_LOAD(n) ((n) * 2)
54 /*----- Iteration and iterators -------------------------------------------*/
56 /* --- @key_mkiter@ --- *
58 * Arguments: @key_iter *i@ = pointer to iterator object
59 * @key_file *f@ = pointer to file structure
63 * Use: Initializes a key iterator. The keys are returned by
67 void key_mkiter(key_iter
*i
, key_file
*f
)
69 HASH_MKITER(&i
->i
, &f
->byid
);
73 /* --- @key_next@ --- *
75 * Arguments: @key_iter *i@ = pointer to iterator object
77 * Returns: Pointer to next key, or null.
79 * Use: Returns the next key in some arbitrary sequence.
82 key
*key_next(key_iter
*i
)
89 } while (k
&& KEY_EXPIRED(i
->t
, k
->exp
) && KEY_EXPIRED(i
->t
, k
->del
));
93 /*----- Lookup ------------------------------------------------------------*/
95 /* --- @key_bytype@ --- *
97 * Arguments: @key_file *f@ = key file we want a key from
98 * @const char *type@ = type string for desired key
100 * Returns: Pointer to the best key to use, or null.
102 * Use: Looks up a key by its type. Returns the key with the latest
103 * expiry time. This function will not return an expired key.
106 key
*key_bytype(key_file
*f
, const char *type
)
108 time_t now
= time(0);
112 if ((kr
= sym_find(&f
->bytype
, type
, -1, 0, 0)) == 0)
114 for (k
= kr
->k
; k
&& KEY_EXPIRED(now
, k
->exp
); k
= k
->next
)
119 /* --- @key_byid@ --- *
121 * Arguments: @key_file *f@ = key file to find a key from
122 * @uint32 id@ = id to look for
124 * Returns: Key with matching id.
126 * Use: Returns a key given its id. This function will return an
127 * expired key, but not a deleted one.
130 key
*key_byid(key_file
*f
, uint32 id
)
135 bin
= HASH_BIN(&f
->byid
, id
);
136 for (b
= *bin
; b
; b
= b
->next
) {
139 if (KEY_EXPIRED(t
, k
->exp
) && KEY_EXPIRED(t
, k
->del
))
147 /* --- @key_bytag@ --- *
149 * Arguments: @key_file *f@ = key file to find a key from
150 * @const char *tag@ = pointer to tag string
152 * Returns: Key with matching id or tag.
154 * Use: Returns a key given its tag or id. This function will return
155 * an expired key, but not a deleted one.
158 key
*key_bytag(key_file
*f
, const char *tag
)
163 key_ref
*kr
= sym_find(&f
->bytag
, tag
, -1, 0, 0);
166 if (kr
&& !(KEY_EXPIRED(t
, kr
->k
->exp
) && KEY_EXPIRED(t
, kr
->k
->del
)))
168 id
= strtoul(tag
, &p
, 16);
169 if (!*p
&& (k
= key_byid(f
, id
)) != 0) return (k
);
170 return (key_bytype(f
, tag
));
173 /* --- @key_qtag@ --- *
175 * Arguments: @key_file *f@ = key file to find a key from
176 * @const char *tag@ = pointer to tag string
177 * @dstr *d@ = pointer to string for full tag name
178 * @key **k@ = where to store the key pointer
179 * @key_data ***kd@ = where to store the key data pointer
181 * Returns: Zero if OK, nonzero if it failed.
183 * Use: Performs a full lookup on a qualified tag name. The tag is
184 * qualified by the names of subkeys, separated by dots. Hence,
185 * a qualified tag is ID|TAG[.TAG...]. The various result
186 * pointers can be null to indicate that the result isn't
190 int key_qtag(key_file
*f
, const char *tag
, dstr
*d
, key
**k
, key_data
***kd
)
197 /* --- Find the end of the base tag --- */
199 if ((q
= strchr(tag
, '.')) == 0)
202 DPUTM(&dd
, tag
, q
- tag
);
207 /* --- Look up the key tag --- */
209 if ((kk
= key_bytag(f
, dd
.buf
)) == 0) {
214 /* --- Set the various initial bits of result up --- */
222 /* --- Now dig through the rest of the tag --- */
228 /* --- Stick on the next bit of the fullqtag --- */
231 while (*q
&& *q
!= '.') {
241 /* --- Look up the subkey --- */
243 if ((*kkd
)->e
!= KENC_STRUCT
) {
247 if ((ks
= sym_find(&(*kkd
)->u
.s
, dd
.buf
, -1, 0, 0)) == 0) {
255 /* --- Return the results --- */
265 /*----- Miscellaneous functions -------------------------------------------*/
267 /* --- @key_delete@ --- *
269 * Arguments: @key_file *f@ = pointer to file block
270 * @key *k@ = key to delete
272 * Returns: Error code (one of the @KERR@ constants).
274 * Use: Removes the given key from the list. The key file must be
275 * writable. (Due to the horridness of the data structures,
276 * deleted keys aren't actually removed, just marked so that
277 * they can't be looked up or iterated over. One upshot of
278 * this is that they don't get written back to the file when
282 int key_delete(key_file
*f
, key
*k
)
285 k
->exp
= KEXP_EXPIRE
;
286 k
->del
= KEXP_EXPIRE
;
291 /* --- @key_expired@ --- *
293 * Arguments: @key *k@ = pointer to key block
295 * Returns: Zero if the key is OK, nonzero if it's expired.
298 int key_expired(key
*k
)
300 time_t now
= time(0);
301 return (KEY_EXPIRED(now
, k
->exp
) || KEY_EXPIRED(now
, k
->del
));
304 /* --- @key_expire@ --- *
306 * Arguments: @key_file *f@ = pointer to file block
307 * @key *k@ = pointer to key block
309 * Returns: Error code (one of the @KERR@ constants).
311 * Use: Immediately marks the key as expired. It may be removed
312 * immediately, if it is no longer required, and will be removed
313 * by a tidy operation when it is no longer required. The key
314 * file must be writable.
317 int key_expire(key_file
*f
, key
*k
)
320 k
->exp
= KEXP_EXPIRE
;
321 if (k
->del
== KEXP_FOREVER
)
322 k
->del
= KEXP_EXPIRE
;
327 /* --- @key_used@ --- *
329 * Arguments: @key_file *f@ = pointer to key file
330 * @key *k@ = pointer to key block
331 * @time_t t@ = when key can be removed
333 * Returns: Zero if OK, nonzero on failure.
335 * Use: Marks a key as being required until a given time. Even
336 * though the key may expire before then (and won't be returned
337 * by type after that time), it will still be available when
338 * requested explicitly by id. The key file must be writable.
340 * The only (current) reason for failure is attempting to use
341 * a key which can expire for something which can't.
344 int key_used(key_file
*f
, key
*k
, time_t t
)
347 if (t
== KEXP_FOREVER
) {
348 if (k
->exp
!= KEXP_FOREVER
)
349 return (KERR_WILLEXPIRE
);
350 } else if (k
->del
>= t
)
358 /* --- @key_fingerprint@ --- *
360 * Arguments: @key *k@ = the key to fingerprint
361 * @ghash *h@ = the hash to use
362 * @const key_filter *kf@ = filter to apply
364 * Returns: Nonzero if the key slightly matched the filter.
366 * Use: Updates the hash context with the key contents.
369 static int abyname(const void *a
, const void *b
) {
370 key_attr
*const *x
= a
, *const *y
= b
;
371 return (strcmp(SYM_NAME(*x
), SYM_NAME(*y
)));
374 int key_fingerprint(key
*k
, ghash
*h
, const key_filter
*kf
)
382 if (!key_encode(k
->k
, &d
, kf
))
385 GH_HASHSTR(h
, "catacomb-key-fingerprint:");
386 GH_HASHU32(h
, k
->id
);
387 GH_HASHSTR8(h
, k
->type
);
388 GH_HASH(h
, d
.buf
, d
.len
);
389 for (n
= 0, sym_mkiter(&ai
, &k
->a
); (a
= sym_next(&ai
)) != 0; n
++);
391 v
= xmalloc(n
* sizeof(*v
));
392 for (i
= 0, sym_mkiter(&ai
, &k
->a
); (a
= sym_next(&ai
)) != 0; i
++)
394 qsort(v
, n
, sizeof(*v
), abyname
);
395 for (i
= 0; i
< n
; i
++) {
396 GH_HASHSTR8(h
, SYM_NAME(v
[i
]));
397 GH_HASHSTR16(h
, v
[i
]->p
);
406 /*----- That's all, folks -------------------------------------------------*/