The pixie no longer needs to be setuid-root.
[u/mdw/catacomb] / key-fetch.c
CommitLineData
1aaed0ba 1/* -*-c-*-
2 *
12ed8a1f 3 * $Id$
1aaed0ba 4 *
5 * Higher-level key unpacking
6 *
7 * (c) 2000 Straylight/Edgeware
8 */
9
45c0fd36 10/*----- Licensing notice --------------------------------------------------*
1aaed0ba 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.
45c0fd36 18 *
1aaed0ba 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.
45c0fd36 23 *
1aaed0ba 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
1aaed0ba 30/*----- Header files ------------------------------------------------------*/
31
32#include <mLib/dstr.h>
33
34#include "key.h"
35#include "key-data.h"
36
37/*----- Main code ---------------------------------------------------------*/
38
39/* --- @key_fetchinit@ --- *
40 *
41 * Arguments: @const key_fetchdef *kf@ = pointer to base definition
42 * @key_packstruct *kps@ = pointer to destination packing def
43 * @void *p@ = pointer to destination block
44 *
45 * Returns: Pointer to packing definition.
46 *
47 * Use: Initializes a packing definition (@key_packdef@ structure).
48 * If @kps@ is null on entry, an appropriately sized block is
49 * allocated automatically. Otherwise it must be large enough.
50 */
51
52static size_t kfcount(const key_fetchdef *kf)
53{
54 size_t n = 1;
55 while (kf->name) {
56 n++;
57 if (kf->kf)
58 n += kfcount(kf->kf);
59 kf++;
60 }
61 return (n);
62}
63
64key_packdef *key_fetchinit(const key_fetchdef *kf,
65 key_packstruct *kp, void *p)
66{
67 size_t n = 1 + kfcount(kf);
68 key_packdef *kpd;
69 key_packstruct *kps;
70 char *cp = p;
71
72 /* --- If @kps@ is null, count the entries and allocate --- */
73
74 if (kp)
75 kp->name = 0;
76 else {
77 kp = xmalloc(n * sizeof(*kp));
78 kp->name = (char *)kp;
79 }
80
81 /* --- Fill in the top part --- */
82
ef13e9a4 83 kp->kp.e = KENC_STRUCT;
1aaed0ba 84 kp->kp.p = &kp[1];
ef13e9a4 85 kp->kp.kd = 0;
1aaed0ba 86 kpd = &kp->kp;
87
88 /* --- Initialize for the main loop --- */
89
90 kps = kp + n;
91 n = 0;
92 kp++;
93
94 /* --- Iterate over the entries in the table --- *
95 *
96 * The end of the target block is used as a stack to record where
97 * substructure is meant to occur. The integer @n@ is the depth of the
98 * stack; @kps@ is a full descending stack pointer. The @kp.p@ member of a
99 * stack element points back to an entry with substructure, the @kp.p@
100 * member of which refers to the @kf@ table for the substructure.
101 *
102 * This should all be about as clear as mud.
103 */
104
105 for (;;) {
106
107 /* --- Blat out a level's worth --- */
108
109 while (kf->name) {
110 kp->name = kf->name;
ef13e9a4 111 kp->kp.e = kf->e;
112 kp->kp.kd = 0;
1aaed0ba 113 if ((kf->e & KF_ENCMASK) != KENC_STRUCT)
114 kp->kp.p = cp + kf->off;
115 else {
116 (--kps)->kp.p = kp;
117 kp->kp.p = (void *)kf->kf;
118 n++;
119 }
120 kf++;
121 kp++;
122 }
123 (kp++)->name = 0;
124 if (!n)
125 break;
126
127 /* --- Pop an entry from the stack --- */
128
129 {
130 key_packstruct *kkp = (kps++)->kp.p;
131 kf = kkp->kp.p;
132 kkp->kp.p = kp;
133 n--;
134 }
135 }
136
137 /* --- We're done --- */
138
139 return (kpd);
140}
141
142/* --- @key_fetch@ --- *
143 *
144 * Arguments: @key_packdef *kp@ = pointer to packing structure
145 * @key *k@ = key file containing desired key
146 *
147 * Returns: Error code, or zero.
148 *
149 * Use: Fetches an unpacked key from a packed one.
150 */
151
152int key_fetch(key_packdef *kp, key *k)
153{
154 dstr d = DSTR_INIT;
155 int e;
156
157 key_fulltag(k, &d);
ef13e9a4 158 e = key_unpack(kp, k->k, &d);
1aaed0ba 159 dstr_destroy(&d);
160 return (e);
161}
162
163/* --- @key_fetchbyname@ --- *
164 *
165 * Arguments: @key_packdef *kp@ = pointer to packing structure
166 * @key_file *kf@ = key file containing desired key
167 * @const char *tag@ = user's tag describing the key
168 *
169 * Returns: Error code, or zero.
170 *
171 * Use: Fetches a named key from a key file and unpacks it
172 * conveniently.
173 */
174
175int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag)
176{
177 dstr d = DSTR_INIT;
ef13e9a4 178 key_data **kd;
1aaed0ba 179 int e;
180
181 if (key_qtag(kf, tag, &d, 0, &kd))
182 e = KERR_NOTFOUND;
183 else
ef13e9a4 184 e = key_unpack(kp, *kd, &d);
1aaed0ba 185 dstr_destroy(&d);
186 return (e);
187}
188
189/* --- @key_fetchdone@ --- *
190 *
191 * Arguments: @key_packdef *kp@ = pointer to packing structure
192 *
193 * Returns: ---
194 *
195 * Use: Frees a packing structure. If the structure was allocated by
196 * @key_fetchinit@ then it is freed.
197 */
198
199void key_fetchdone(key_packdef *kp)
200{
ef13e9a4 201 key_packstruct *kps =
202 (key_packstruct *)(((char *)kp) - offsetof(key_packstruct, kp));
1aaed0ba 203 key_unpackdone(kp);
204 if (kps->name)
12ed8a1f 205 xfree(kps);
45c0fd36 206}
1aaed0ba 207
208/*----- That's all, folks -------------------------------------------------*/