d03ab969 |
1 | /* -*-c-*- |
2 | * |
3 | * $Id: key.h,v 1.1 1999/09/03 08:41:12 mdw Exp $ |
4 | * |
5 | * Simple key management |
6 | * |
7 | * (c) 1999 Mark Wooding |
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.h,v $ |
33 | * Revision 1.1 1999/09/03 08:41:12 mdw |
34 | * Initial import. |
35 | * |
36 | */ |
37 | |
38 | #ifndef KEY_H |
39 | #define KEY_H |
40 | |
41 | #ifdef __cplusplus |
42 | extern "C" { |
43 | #endif |
44 | |
45 | /*----- Header files ------------------------------------------------------*/ |
46 | |
47 | #include <stdio.h> |
48 | #include <time.h> |
49 | |
50 | #include <mLib/bits.h> |
51 | #include <mLib/hash.h> |
52 | #include <mLib/sym.h> |
53 | |
54 | /*----- Data structures ---------------------------------------------------*/ |
55 | |
56 | /* --- Key attributes --- * |
57 | * |
58 | * Each attribute is stored as a symbol in a symbol table. The value is |
59 | * the plain (not url-encoded) text to be written to the the file. If the |
60 | * value is binary data, then by this point it's base-64 encoded. |
61 | */ |
62 | |
63 | typedef struct key_attr { |
64 | sym_base _b; /* Symbol table data */ |
65 | char *p; /* Pointer to attribute value */ |
66 | } key_attr; |
67 | |
68 | /* --- Main key structure --- * |
69 | * |
70 | * Each key is stored in two symbol tables, one indexed by keyid, and the |
71 | * other indexed by type. Because many keys can have the same type, the type |
72 | * table contains a list of keys, sorted in descending order of expiry. |
73 | */ |
74 | |
75 | typedef struct key { |
76 | hash_base _b; /* Symbol table data */ |
77 | struct key *next; /* Next key of the same type */ |
78 | uint32 id; /* Key id used to name it */ |
79 | char *type; /* Textual key type */ |
80 | void *k; /* Actual key data */ |
81 | size_t ksz; /* Size of the key data */ |
82 | time_t exp, del; /* Expiry times for keys */ |
83 | sym_table a; /* Hashtable of key attributes */ |
84 | char *c; /* Any additional comments */ |
85 | } key; |
86 | |
87 | /* --- The keys-by-type entries --- */ |
88 | |
89 | typedef struct key_type { |
90 | sym_base _b; /* Symbol table data */ |
91 | key *k; /* Pointer to first key in list */ |
92 | } key_type; |
93 | |
94 | /* --- A key file --- */ |
95 | |
96 | typedef struct key_file { |
97 | FILE *fp; /* File pointer open on file */ |
98 | int fd; /* File descriptor open on file */ |
99 | char *name; /* Filename used to create it */ |
100 | unsigned f; /* Various useful flags */ |
101 | hash_table byid; /* Table of keys by keyid */ |
102 | sym_table bytype; /* Table of keys by type */ |
103 | size_t idload; /* Loading on id table */ |
104 | } key_file; |
105 | |
106 | /* --- Key file flags --- */ |
107 | |
108 | enum { |
109 | KF_WRITE = 1, /* File opened for writing */ |
110 | KF_MODIFIED = 2 /* File has been modified */ |
111 | }; |
112 | |
113 | /* --- Iterating over keys --- * |
114 | * |
115 | * Both of these are simple symbol table iterators, but they're made distinct |
116 | * types for the dubious benefits that type safety brings. |
117 | */ |
118 | |
119 | typedef struct { hash_iter i; time_t t; } key_iter; |
120 | typedef struct { sym_iter i; } key_attriter; |
121 | |
122 | /* --- File opening options --- */ |
123 | |
124 | enum { |
125 | KOPEN_READ, |
126 | KOPEN_WRITE |
127 | }; |
128 | |
129 | /* --- Various other magic numbers --- */ |
130 | |
131 | #define KEXP_UNUSED ((time_t)0) /* Key has never been used */ |
132 | #define KEXP_FOREVER ((time_t)-1) /* Never expire this key */ |
133 | #define KEXP_EXPIRE ((time_t)-2) /* Expire this key when unused */ |
134 | |
135 | /* --- Write attempt codes --- */ |
136 | |
137 | enum { |
138 | KWRITE_OK, /* Everything went fine */ |
139 | KWRITE_FAIL = -1, /* Close attempt failed */ |
140 | KWRITE_BROKEN = -2 /* Key ring needs manual fixing */ |
141 | }; |
142 | |
143 | /* --- Macros for testing expiry --- */ |
144 | |
145 | #define KEY_EXPIRED(now, exp) \ |
146 | ((exp) == KEXP_EXPIRE || ((exp) != KEXP_FOREVER && (exp) < (now))) |
147 | |
148 | #define KEY_DELETED(now, del) ((del) == KEXP_FOREVER || (del) < (now)) |
149 | |
150 | /*----- Functions provided ------------------------------------------------*/ |
151 | |
152 | /* --- @key_chktype@ --- * |
153 | * |
154 | * Arguments: @const char *type@ = pointer to a type string |
155 | * |
156 | * Returns: Zero if OK, -1 on error. |
157 | * |
158 | * Use: Checks whether a type string is OK. |
159 | */ |
160 | |
161 | extern int key_chktype(const char */*type*/); |
162 | |
163 | /* --- @key_chkcomment@ --- * |
164 | * |
165 | * Arguments: @const char *comment@ = pointer to a comment string |
166 | * |
167 | * Returns: Zero if OK, -1 on error. |
168 | * |
169 | * Use: Checks whether a comment string is OK. |
170 | */ |
171 | |
172 | extern int key_chkcomment(const char */*c*/); |
173 | |
174 | /* --- @key_mkiter@ --- * |
175 | * |
176 | * Arguments: @key_iter *i@ = pointer to iterator object |
177 | * @key_file *f@ = pointer to file structure |
178 | * |
179 | * Returns: --- |
180 | * |
181 | * Use: Initializes a key iterator. The keys are returned by |
182 | * @key_next@. |
183 | */ |
184 | |
185 | extern void key_mkiter(key_iter */*i*/, key_file */*f*/); |
186 | |
187 | /* --- @key_next@ --- * |
188 | * |
189 | * Arguments: @key_iter *i@ = pointer to iterator object |
190 | * |
191 | * Returns: Pointer to next key, or null. |
192 | * |
193 | * Use: Returns the next key in some arbitrary sequence. |
194 | */ |
195 | |
196 | extern key *key_next(key_iter */*i*/); |
197 | |
198 | /* --- @key_mkattriter@ --- * |
199 | * |
200 | * Arguments: @key_attriter *i@ = pointer to attribute iterator |
201 | * @key_file *f@ = pointer to key file |
202 | * @key *k@ = pointer to key |
203 | * |
204 | * Returns: --- |
205 | * |
206 | * Use: Initializes an attribute iterator. The attributes are |
207 | * returned by @key_nextattr@. |
208 | */ |
209 | |
210 | extern void key_mkattriter(key_attriter */*i*/, key_file */*f*/, key */*k*/); |
211 | |
212 | /* --- @key_nextattr@ --- * |
213 | * |
214 | * Arguments: @key_attriter *i@ = pointer to attribute iterator |
215 | * @const char **n, **v@ = pointers to name and value |
216 | * |
217 | * Returns: Zero if no attribute available, or nonzero if returned OK. |
218 | * |
219 | * Use: Returns the next attribute. |
220 | */ |
221 | |
222 | extern int key_nextattr(key_attriter */*i*/, |
223 | const char **/*n*/, const char **/*v*/); |
224 | |
225 | /* --- @key_bytype@ --- * |
226 | * |
227 | * Arguments: @key_file *f@ = key file we want a key from |
228 | * @const char *type@ = type string for desired key |
229 | * |
230 | * Returns: Pointer to the best key to use, or null. |
231 | * |
232 | * Use: Looks up a key by its type. Returns the key with the latest |
233 | * expiry time. This function will not return an expired key. |
234 | */ |
235 | |
236 | extern key *key_bytype(key_file */*f*/, const char */*type*/); |
237 | |
238 | /* --- @key_byid@ --- * |
239 | * |
240 | * Arguments: @key_file *f@ = key file to find a key from |
241 | * @uint32 id@ = id to look for |
242 | * |
243 | * Returns: Key with matching id. |
244 | * |
245 | * Use: Returns a key given its id. This function will return an |
246 | * expired key, but not a deleted one. |
247 | */ |
248 | |
249 | extern key *key_byid(key_file */*f*/, uint32 /*id*/); |
250 | |
251 | /* --- @key_getattr@ --- * |
252 | * |
253 | * Arguments: @key_file *f@ = pointer to file |
254 | * @key *k@ = pointer to key |
255 | * @const char *n@ = pointer to attribute name |
256 | * |
257 | * Returns: Pointer to attribute value, or null if not found. |
258 | * |
259 | * Use: Returns the value of a key attribute. |
260 | */ |
261 | |
262 | extern const char *key_getattr(key_file */*f*/, key */*k*/, |
263 | const char */*n*/); |
264 | |
265 | /* --- @key_putattr@ --- * |
266 | * |
267 | * Arguments: @key_file *f@ = pointer to file |
268 | * @key *k@ = pointer to key |
269 | * @const char *n@ = pointer to attribute name |
270 | * @const char *v@ = pointer to attribute value |
271 | * |
272 | * Returns: --- |
273 | * |
274 | * Use: Inserts an attribute on a key. If an attribute with the same |
275 | * name already exists, it is deleted. |
276 | */ |
277 | |
278 | extern void key_putattr(key_file */*f*/, key */*k*/, |
279 | const char */*n*/, const char */*v*/); |
280 | |
281 | /* --- @key_setcomment@ --- * |
282 | * |
283 | * Arguments: @key_file *f@ = pointer to key file block |
284 | * @key *k@ = pointer to key block |
285 | * @const char *c@ = pointer to comment to set, or zero |
286 | * |
287 | * Returns: --- |
288 | * |
289 | * Use: Replaces the key's current comment with a new one. |
290 | */ |
291 | |
292 | extern void key_setcomment(key_file */*f*/, key */*k*/, const char */*c*/); |
293 | |
294 | /* --- @key_merge@ --- * |
295 | * |
296 | * Arguments: @key_file *f@ = pointer to file structure |
297 | * @const char *file@ = name of file (for error messages) |
298 | * @FILE *fp@ = file handle to read from |
299 | * |
300 | * Returns: --- |
301 | * |
302 | * Use: Reads keys from a file, and inserts them into the file. |
303 | */ |
304 | |
305 | extern void key_merge(key_file */*f*/, const char */*file*/, FILE */*fp*/); |
306 | |
307 | /* --- @key_extract@ --- * |
308 | * |
309 | * Arguments: @key_file *f@ = pointer to file structure |
310 | * @key *k@ = key to extract |
311 | * @FILE *fp@ = file to write on |
312 | * |
313 | * Returns: Zero if OK, EOF on error. |
314 | * |
315 | * Use: Extracts a key to an ouptut file. |
316 | */ |
317 | |
318 | extern int key_extract(key_file */*f*/, key */*k*/, FILE */*fp*/); |
319 | |
320 | /* --- @key_write@ --- * |
321 | * |
322 | * Arguments: @key_file *f@ = pointer to key file block |
323 | * |
324 | * Returns: A @KWRITE_@ code indicating how well it worked. |
325 | * |
326 | * Use: Writes a key file's data back to the actual file. This code |
327 | * is extremely careful about error handling. It should usually |
328 | * be able to back out somewhere sensible, but it can tell when |
329 | * it's got itself into a real pickle and starts leaving well |
330 | * alone. |
331 | * |
332 | * Callers, please make sure that you ring alarm bells when this |
333 | * function returns @KWRITE_BROKEN@. |
334 | */ |
335 | |
336 | extern int key_write(key_file */*f*/); |
337 | |
338 | /* --- @key_open@ --- * |
339 | * |
340 | * Arguments: @key_file *f@ = pointer to file structure to initialize |
341 | * @const char *file@ = pointer to the file name |
342 | * @int how@ = opening options (@KOPEN_*@). |
343 | * |
344 | * Returns: Zero if it worked, nonzero otherwise. |
345 | * |
346 | * Use: Opens a key file, reads its contents, and stores them in a |
347 | * structure. The file is locked appropriately until closed |
348 | * using @key_close@. On an error, everything is cleared away |
349 | * tidily. If the file is opened with @KOPEN_WRITE@, it's |
350 | * created if necessary, with read and write permissions for its |
351 | * owner only. |
352 | */ |
353 | |
354 | extern int key_open(key_file */*f*/, const char */*file*/, int /*how*/); |
355 | |
356 | /* --- @key_close@ --- * |
357 | * |
358 | * Arguments: @key_file *f@ = pointer to key file block |
359 | * |
360 | * Returns: A @KWRITE_@ code indicating how it went. |
361 | * |
362 | * Use: Frees all the key data, writes any changes. Make sure that |
363 | * all hell breaks loose if this returns @KWRITE_BROKEN@. |
364 | */ |
365 | |
366 | extern int key_close(key_file */*f*/); |
367 | |
368 | /* --- @key_new@ --- |
369 | * |
370 | * Arguments: @key_file *f@ = pointer to key file |
371 | * @const char *type@ = the type of this key |
372 | * @const void *k@ = pointer to key data |
373 | * @size_t ksz@ = size of key data |
374 | * @time_t exp@ = when the key expires |
375 | * @const char *c@ = textual comment to attach |
376 | * |
377 | * Returns: Key block containing new data, or null if it couldn't be |
378 | * done. |
379 | * |
380 | * Use: Attaches a new key to a key file. You must have a writable |
381 | * key file for this to work. |
382 | * |
383 | * The type is a key type string. This interface doesn't care |
384 | * about how type strings are formatted: it just treats them as |
385 | * opaque gobs of text. Clients are advised to choose some |
386 | * standard for representing key types, though. |
387 | * |
388 | * The key can be any old binary mess. |
389 | * |
390 | * The expiry time should either be a time in the future, or the |
391 | * magic value @KEXP_FOREVER@ which means `never expire this |
392 | * key'. Be careful with `forever' keys. If I were you, I'd |
393 | * use a more sophisticated key management system than this for |
394 | * them. |
395 | * |
396 | * The comment can be any old text not containing newlines or |
397 | * nulls. This interface doesn't impose any length restrictions |
398 | * on comment lengths. |
399 | */ |
400 | |
401 | extern key *key_new(key_file */*f*/, const char */*type*/, |
402 | const void */*k*/, size_t /*ksz*/, |
403 | time_t /*exp*/, const char */*c*/); |
404 | |
405 | /* --- @key_delete@ --- * |
406 | * |
407 | * Arguments: @key_file *f@ = pointer to file block |
408 | * @key *k@ = key to delete |
409 | * |
410 | * Returns: --- |
411 | * |
412 | * Use: Removes the given key from the list. The key file must be |
413 | * writable. (Due to the horridness of the data structures, |
414 | * deleted keys aren't actually removed, just marked so that |
415 | * they can't be looked up or iterated over. One upshot of |
416 | * this is that they don't get written back to the file when |
417 | * it's closed.) |
418 | */ |
419 | |
420 | extern void key_delete(key_file */*f*/, key */*k*/); |
421 | |
422 | /* --- @key_expire@ --- * |
423 | * |
424 | * Arguments: @key_file *f@ = pointer to file block |
425 | * @key *k@ = pointer to key block |
426 | * |
427 | * Returns: --- |
428 | * |
429 | * Use: Immediately marks the key as expired. It may be removed |
430 | * immediately, if it is no longer required, and will be removed |
431 | * by a tidy operation when it is no longer required. The key |
432 | * file must be writable. |
433 | */ |
434 | |
435 | extern void key_expire(key_file */*f*/, key */*k*/); |
436 | |
437 | /* --- @key_used@ --- * |
438 | * |
439 | * Arguments: @key_file *f@ = pointer to key file |
440 | * @key *k@ = pointer to key block |
441 | * @time_t t@ = when key can be removed |
442 | * |
443 | * Returns: Zero if OK, nonzero on failure. |
444 | * |
445 | * Use: Marks a key as being required until a given time. Even |
446 | * though the key may expire before then (and won't be returned |
447 | * by type after that time), it will still be available when |
448 | * requested explicitly by id. The key file must be writable. |
449 | * |
450 | * The only (current) reason for failure is attempting to use |
451 | * a key which can expire for something which can't. |
452 | */ |
453 | |
454 | extern int key_used(key_file */*f*/, key */*k*/, time_t /*t*/); |
455 | |
456 | /*----- That's all, folks -------------------------------------------------*/ |
457 | |
458 | #ifdef __cplusplus |
459 | } |
460 | #endif |
461 | |
462 | #endif |