print.c revision 1.1.1.2.6.1 1 1.1.1.2.6.1 pgoyette /* $NetBSD: print.c,v 1.1.1.2.6.1 2017/03/20 06:51:44 pgoyette Exp $ */
2 1.1 elric
3 1.1 elric /*
4 1.1 elric * Copyright (c) 1999-2005 Kungliga Tekniska Hgskolan
5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden).
6 1.1 elric * All rights reserved.
7 1.1 elric *
8 1.1 elric * Redistribution and use in source and binary forms, with or without
9 1.1 elric * modification, are permitted provided that the following conditions
10 1.1 elric * are met:
11 1.1 elric *
12 1.1 elric * 1. Redistributions of source code must retain the above copyright
13 1.1 elric * notice, this list of conditions and the following disclaimer.
14 1.1 elric *
15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 elric * notice, this list of conditions and the following disclaimer in the
17 1.1 elric * documentation and/or other materials provided with the distribution.
18 1.1 elric *
19 1.1 elric * 3. Neither the name of KTH nor the names of its contributors may be
20 1.1 elric * used to endorse or promote products derived from this software without
21 1.1 elric * specific prior written permission.
22 1.1 elric *
23 1.1 elric * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
24 1.1 elric * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 1.1 elric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
27 1.1 elric * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 1.1 elric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 1.1 elric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 1.1 elric * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 1.1 elric * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 1.1 elric * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33 1.1 elric * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
34 1.1 elric
35 1.1 elric #include "hdb_locl.h"
36 1.1 elric #include <krb5/hex.h>
37 1.1 elric #include <ctype.h>
38 1.1 elric
39 1.1 elric /*
40 1.1 elric This is the present contents of a dump line. This might change at
41 1.1 elric any time. Fields are separated by white space.
42 1.1 elric
43 1.1 elric principal
44 1.1 elric keyblock
45 1.1 elric kvno
46 1.1 elric keys...
47 1.1 elric mkvno
48 1.1 elric enctype
49 1.1 elric keyvalue
50 1.1 elric salt (- means use normal salt)
51 1.1 elric creation date and principal
52 1.1 elric modification date and principal
53 1.1 elric principal valid from date (not used)
54 1.1 elric principal valid end date (not used)
55 1.1 elric principal key expires (not used)
56 1.1 elric max ticket life
57 1.1 elric max renewable life
58 1.1 elric flags
59 1.1 elric generation number
60 1.1 elric */
61 1.1 elric
62 1.1.1.2.6.1 pgoyette /*
63 1.1.1.2.6.1 pgoyette * These utility functions return the number of bytes written or -1, and
64 1.1.1.2.6.1 pgoyette * they set an error in the context.
65 1.1.1.2.6.1 pgoyette */
66 1.1.1.2.6.1 pgoyette static ssize_t
67 1.1 elric append_string(krb5_context context, krb5_storage *sp, const char *fmt, ...)
68 1.1 elric {
69 1.1.1.2.6.1 pgoyette ssize_t sz;
70 1.1 elric char *s;
71 1.1.1.2.6.1 pgoyette int rc;
72 1.1 elric va_list ap;
73 1.1 elric va_start(ap, fmt);
74 1.1.1.2.6.1 pgoyette rc = vasprintf(&s, fmt, ap);
75 1.1 elric va_end(ap);
76 1.1.1.2.6.1 pgoyette if(rc < 0) {
77 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
78 1.1.1.2.6.1 pgoyette return -1;
79 1.1 elric }
80 1.1.1.2.6.1 pgoyette sz = krb5_storage_write(sp, s, strlen(s));
81 1.1 elric free(s);
82 1.1.1.2.6.1 pgoyette return sz;
83 1.1 elric }
84 1.1 elric
85 1.1 elric static krb5_error_code
86 1.1.1.2.6.1 pgoyette append_hex(krb5_context context, krb5_storage *sp,
87 1.1.1.2.6.1 pgoyette int always_encode, int lower, krb5_data *data)
88 1.1 elric {
89 1.1.1.2.6.1 pgoyette ssize_t sz;
90 1.1.1.2 pettai int printable = 1;
91 1.1.1.2 pettai size_t i;
92 1.1 elric char *p;
93 1.1 elric
94 1.1 elric p = data->data;
95 1.1.1.2.6.1 pgoyette if (!always_encode) {
96 1.1.1.2.6.1 pgoyette for (i = 0; i < data->length; i++) {
97 1.1.1.2.6.1 pgoyette if (!isalnum((unsigned char)p[i]) && p[i] != '.'){
98 1.1.1.2.6.1 pgoyette printable = 0;
99 1.1.1.2.6.1 pgoyette break;
100 1.1.1.2.6.1 pgoyette }
101 1.1.1.2.6.1 pgoyette }
102 1.1.1.2.6.1 pgoyette }
103 1.1.1.2.6.1 pgoyette if (printable && !always_encode)
104 1.1 elric return append_string(context, sp, "\"%.*s\"",
105 1.1 elric data->length, data->data);
106 1.1.1.2.6.1 pgoyette sz = hex_encode(data->data, data->length, &p);
107 1.1.1.2.6.1 pgoyette if (sz == -1) return sz;
108 1.1.1.2.6.1 pgoyette if (lower)
109 1.1.1.2.6.1 pgoyette strlwr(p);
110 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "%s", p);
111 1.1 elric free(p);
112 1.1.1.2.6.1 pgoyette return sz;
113 1.1 elric }
114 1.1 elric
115 1.1 elric static char *
116 1.1 elric time2str(time_t t)
117 1.1 elric {
118 1.1 elric static char buf[128];
119 1.1 elric strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", gmtime(&t));
120 1.1 elric return buf;
121 1.1 elric }
122 1.1 elric
123 1.1.1.2.6.1 pgoyette static ssize_t
124 1.1 elric append_event(krb5_context context, krb5_storage *sp, Event *ev)
125 1.1 elric {
126 1.1 elric krb5_error_code ret;
127 1.1.1.2.6.1 pgoyette ssize_t sz;
128 1.1.1.2.6.1 pgoyette char *pr = NULL;
129 1.1 elric if(ev == NULL)
130 1.1 elric return append_string(context, sp, "- ");
131 1.1 elric if (ev->principal != NULL) {
132 1.1 elric ret = krb5_unparse_name(context, ev->principal, &pr);
133 1.1.1.2.6.1 pgoyette if (ret) return -1; /* krb5_unparse_name() sets error info */
134 1.1 elric }
135 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "%s:%s ", time2str(ev->time),
136 1.1.1.2.6.1 pgoyette pr ? pr : "UNKNOWN");
137 1.1 elric free(pr);
138 1.1.1.2.6.1 pgoyette return sz;
139 1.1.1.2.6.1 pgoyette }
140 1.1.1.2.6.1 pgoyette
141 1.1.1.2.6.1 pgoyette #define KRB5_KDB_SALTTYPE_NORMAL 0
142 1.1.1.2.6.1 pgoyette #define KRB5_KDB_SALTTYPE_V4 1
143 1.1.1.2.6.1 pgoyette #define KRB5_KDB_SALTTYPE_NOREALM 2
144 1.1.1.2.6.1 pgoyette #define KRB5_KDB_SALTTYPE_ONLYREALM 3
145 1.1.1.2.6.1 pgoyette #define KRB5_KDB_SALTTYPE_SPECIAL 4
146 1.1.1.2.6.1 pgoyette #define KRB5_KDB_SALTTYPE_AFS3 5
147 1.1.1.2.6.1 pgoyette
148 1.1.1.2.6.1 pgoyette static ssize_t
149 1.1.1.2.6.1 pgoyette append_mit_key(krb5_context context, krb5_storage *sp,
150 1.1.1.2.6.1 pgoyette krb5_const_principal princ,
151 1.1.1.2.6.1 pgoyette unsigned int kvno, Key *key)
152 1.1.1.2.6.1 pgoyette {
153 1.1.1.2.6.1 pgoyette krb5_error_code ret;
154 1.1.1.2.6.1 pgoyette krb5_salt k5salt;
155 1.1.1.2.6.1 pgoyette ssize_t sz;
156 1.1.1.2.6.1 pgoyette size_t key_versions = key->salt ? 2 : 1;
157 1.1.1.2.6.1 pgoyette size_t decrypted_key_length;
158 1.1.1.2.6.1 pgoyette char buf[2];
159 1.1.1.2.6.1 pgoyette krb5_data keylenbytes;
160 1.1.1.2.6.1 pgoyette unsigned int salttype;
161 1.1.1.2.6.1 pgoyette
162 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "\t%u\t%u\t%d\t%d\t", key_versions, kvno,
163 1.1.1.2.6.1 pgoyette key->key.keytype, key->key.keyvalue.length + 2);
164 1.1.1.2.6.1 pgoyette if (sz == -1) return sz;
165 1.1.1.2.6.1 pgoyette ret = krb5_enctype_keysize(context, key->key.keytype, &decrypted_key_length);
166 1.1.1.2.6.1 pgoyette if (ret) return -1; /* XXX we lose the error code */
167 1.1.1.2.6.1 pgoyette buf[0] = decrypted_key_length & 0xff;
168 1.1.1.2.6.1 pgoyette buf[1] = (decrypted_key_length & 0xff00) >> 8;
169 1.1.1.2.6.1 pgoyette keylenbytes.data = buf;
170 1.1.1.2.6.1 pgoyette keylenbytes.length = sizeof (buf);
171 1.1.1.2.6.1 pgoyette sz = append_hex(context, sp, 1, 1, &keylenbytes);
172 1.1.1.2.6.1 pgoyette if (sz == -1) return sz;
173 1.1.1.2.6.1 pgoyette sz = append_hex(context, sp, 1, 1, &key->key.keyvalue);
174 1.1.1.2.6.1 pgoyette if (!key->salt)
175 1.1.1.2.6.1 pgoyette return sz;
176 1.1.1.2.6.1 pgoyette
177 1.1.1.2.6.1 pgoyette /* Map salt to MIT KDB style */
178 1.1.1.2.6.1 pgoyette switch (key->salt->type) {
179 1.1.1.2.6.1 pgoyette case KRB5_PADATA_PW_SALT:
180 1.1.1.2.6.1 pgoyette
181 1.1.1.2.6.1 pgoyette /*
182 1.1.1.2.6.1 pgoyette * Compute normal salt and then see whether it matches the stored one
183 1.1.1.2.6.1 pgoyette */
184 1.1.1.2.6.1 pgoyette ret = krb5_get_pw_salt(context, princ, &k5salt);
185 1.1.1.2.6.1 pgoyette if (ret) return -1;
186 1.1.1.2.6.1 pgoyette if (k5salt.saltvalue.length == key->salt->salt.length &&
187 1.1.1.2.6.1 pgoyette memcmp(k5salt.saltvalue.data, key->salt->salt.data,
188 1.1.1.2.6.1 pgoyette k5salt.saltvalue.length) == 0)
189 1.1.1.2.6.1 pgoyette salttype = KRB5_KDB_SALTTYPE_NORMAL; /* matches */
190 1.1.1.2.6.1 pgoyette else if (key->salt->salt.length == strlen(princ->realm) &&
191 1.1.1.2.6.1 pgoyette memcmp(key->salt->salt.data, princ->realm,
192 1.1.1.2.6.1 pgoyette key->salt->salt.length) == 0)
193 1.1.1.2.6.1 pgoyette salttype = KRB5_KDB_SALTTYPE_ONLYREALM; /* matches realm */
194 1.1.1.2.6.1 pgoyette else if (key->salt->salt.length ==
195 1.1.1.2.6.1 pgoyette k5salt.saltvalue.length - strlen(princ->realm) &&
196 1.1.1.2.6.1 pgoyette memcmp((char *)k5salt.saltvalue.data + strlen(princ->realm),
197 1.1.1.2.6.1 pgoyette key->salt->salt.data, key->salt->salt.length) == 0)
198 1.1.1.2.6.1 pgoyette salttype = KRB5_KDB_SALTTYPE_NOREALM; /* matches w/o realm */
199 1.1.1.2.6.1 pgoyette else
200 1.1.1.2.6.1 pgoyette salttype = KRB5_KDB_SALTTYPE_NORMAL; /* hope for best */
201 1.1.1.2.6.1 pgoyette
202 1.1.1.2.6.1 pgoyette break;
203 1.1.1.2.6.1 pgoyette
204 1.1.1.2.6.1 pgoyette case KRB5_PADATA_AFS3_SALT:
205 1.1.1.2.6.1 pgoyette salttype = KRB5_KDB_SALTTYPE_AFS3;
206 1.1.1.2.6.1 pgoyette break;
207 1.1.1.2.6.1 pgoyette
208 1.1.1.2.6.1 pgoyette default:
209 1.1.1.2.6.1 pgoyette return -1;
210 1.1.1.2.6.1 pgoyette }
211 1.1.1.2.6.1 pgoyette
212 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "\t%u\t%u\t", salttype,
213 1.1.1.2.6.1 pgoyette key->salt->salt.length);
214 1.1.1.2.6.1 pgoyette if (sz == -1) return sz;
215 1.1.1.2.6.1 pgoyette return append_hex(context, sp, 1, 1, &key->salt->salt);
216 1.1 elric }
217 1.1 elric
218 1.1 elric static krb5_error_code
219 1.1 elric entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
220 1.1 elric {
221 1.1 elric char *p;
222 1.1.1.2 pettai size_t i;
223 1.1 elric krb5_error_code ret;
224 1.1 elric
225 1.1 elric /* --- principal */
226 1.1 elric ret = krb5_unparse_name(context, ent->principal, &p);
227 1.1 elric if(ret)
228 1.1 elric return ret;
229 1.1 elric append_string(context, sp, "%s ", p);
230 1.1 elric free(p);
231 1.1 elric /* --- kvno */
232 1.1 elric append_string(context, sp, "%d", ent->kvno);
233 1.1 elric /* --- keys */
234 1.1 elric for(i = 0; i < ent->keys.len; i++){
235 1.1 elric /* --- mkvno, keytype */
236 1.1 elric if(ent->keys.val[i].mkvno)
237 1.1 elric append_string(context, sp, ":%d:%d:",
238 1.1 elric *ent->keys.val[i].mkvno,
239 1.1 elric ent->keys.val[i].key.keytype);
240 1.1 elric else
241 1.1 elric append_string(context, sp, "::%d:",
242 1.1 elric ent->keys.val[i].key.keytype);
243 1.1 elric /* --- keydata */
244 1.1.1.2.6.1 pgoyette append_hex(context, sp, 0, 0, &ent->keys.val[i].key.keyvalue);
245 1.1 elric append_string(context, sp, ":");
246 1.1 elric /* --- salt */
247 1.1 elric if(ent->keys.val[i].salt){
248 1.1 elric append_string(context, sp, "%u/", ent->keys.val[i].salt->type);
249 1.1.1.2.6.1 pgoyette append_hex(context, sp, 0, 0, &ent->keys.val[i].salt->salt);
250 1.1 elric }else
251 1.1 elric append_string(context, sp, "-");
252 1.1 elric }
253 1.1 elric append_string(context, sp, " ");
254 1.1 elric /* --- created by */
255 1.1 elric append_event(context, sp, &ent->created_by);
256 1.1 elric /* --- modified by */
257 1.1 elric append_event(context, sp, ent->modified_by);
258 1.1 elric
259 1.1 elric /* --- valid start */
260 1.1 elric if(ent->valid_start)
261 1.1 elric append_string(context, sp, "%s ", time2str(*ent->valid_start));
262 1.1 elric else
263 1.1 elric append_string(context, sp, "- ");
264 1.1 elric
265 1.1 elric /* --- valid end */
266 1.1 elric if(ent->valid_end)
267 1.1 elric append_string(context, sp, "%s ", time2str(*ent->valid_end));
268 1.1 elric else
269 1.1 elric append_string(context, sp, "- ");
270 1.1 elric
271 1.1 elric /* --- password ends */
272 1.1 elric if(ent->pw_end)
273 1.1 elric append_string(context, sp, "%s ", time2str(*ent->pw_end));
274 1.1 elric else
275 1.1 elric append_string(context, sp, "- ");
276 1.1 elric
277 1.1 elric /* --- max life */
278 1.1 elric if(ent->max_life)
279 1.1 elric append_string(context, sp, "%d ", *ent->max_life);
280 1.1 elric else
281 1.1 elric append_string(context, sp, "- ");
282 1.1 elric
283 1.1 elric /* --- max renewable life */
284 1.1 elric if(ent->max_renew)
285 1.1 elric append_string(context, sp, "%d ", *ent->max_renew);
286 1.1 elric else
287 1.1 elric append_string(context, sp, "- ");
288 1.1 elric
289 1.1 elric /* --- flags */
290 1.1 elric append_string(context, sp, "%d ", HDBFlags2int(ent->flags));
291 1.1 elric
292 1.1 elric /* --- generation number */
293 1.1 elric if(ent->generation) {
294 1.1 elric append_string(context, sp, "%s:%d:%d ", time2str(ent->generation->time),
295 1.1 elric ent->generation->usec,
296 1.1 elric ent->generation->gen);
297 1.1 elric } else
298 1.1 elric append_string(context, sp, "- ");
299 1.1 elric
300 1.1 elric /* --- extensions */
301 1.1 elric if(ent->extensions && ent->extensions->len > 0) {
302 1.1 elric for(i = 0; i < ent->extensions->len; i++) {
303 1.1 elric void *d;
304 1.1.1.2 pettai size_t size, sz = 0;
305 1.1 elric
306 1.1 elric ASN1_MALLOC_ENCODE(HDB_extension, d, size,
307 1.1 elric &ent->extensions->val[i], &sz, ret);
308 1.1 elric if (ret) {
309 1.1 elric krb5_clear_error_message(context);
310 1.1 elric return ret;
311 1.1 elric }
312 1.1 elric if(size != sz)
313 1.1 elric krb5_abortx(context, "internal asn.1 encoder error");
314 1.1 elric
315 1.1 elric if (hex_encode(d, size, &p) < 0) {
316 1.1 elric free(d);
317 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
318 1.1 elric return ENOMEM;
319 1.1 elric }
320 1.1 elric
321 1.1 elric free(d);
322 1.1 elric append_string(context, sp, "%s%s", p,
323 1.1 elric ent->extensions->len - 1 != i ? ":" : "");
324 1.1 elric free(p);
325 1.1 elric }
326 1.1 elric } else
327 1.1 elric append_string(context, sp, "-");
328 1.1 elric
329 1.1.1.2.6.1 pgoyette return 0;
330 1.1.1.2.6.1 pgoyette }
331 1.1 elric
332 1.1.1.2.6.1 pgoyette #define KRB5_KDB_DISALLOW_POSTDATED 0x00000001
333 1.1.1.2.6.1 pgoyette #define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002
334 1.1.1.2.6.1 pgoyette #define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004
335 1.1.1.2.6.1 pgoyette #define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008
336 1.1.1.2.6.1 pgoyette #define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010
337 1.1.1.2.6.1 pgoyette #define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020
338 1.1.1.2.6.1 pgoyette #define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040
339 1.1.1.2.6.1 pgoyette #define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080
340 1.1.1.2.6.1 pgoyette #define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100
341 1.1.1.2.6.1 pgoyette #define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200
342 1.1.1.2.6.1 pgoyette #define KRB5_KDB_DISALLOW_SVR 0x00001000
343 1.1.1.2.6.1 pgoyette #define KRB5_KDB_PWCHANGE_SERVICE 0x00002000
344 1.1.1.2.6.1 pgoyette #define KRB5_KDB_SUPPORT_DESMD5 0x00004000
345 1.1.1.2.6.1 pgoyette #define KRB5_KDB_NEW_PRINC 0x00008000
346 1.1.1.2.6.1 pgoyette
347 1.1.1.2.6.1 pgoyette static int
348 1.1.1.2.6.1 pgoyette flags_to_attr(HDBFlags flags)
349 1.1.1.2.6.1 pgoyette {
350 1.1.1.2.6.1 pgoyette int a = 0;
351 1.1.1.2.6.1 pgoyette
352 1.1.1.2.6.1 pgoyette if (!flags.postdate)
353 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_DISALLOW_POSTDATED;
354 1.1.1.2.6.1 pgoyette if (!flags.forwardable)
355 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_DISALLOW_FORWARDABLE;
356 1.1.1.2.6.1 pgoyette if (flags.initial)
357 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_DISALLOW_TGT_BASED;
358 1.1.1.2.6.1 pgoyette if (!flags.renewable)
359 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_DISALLOW_RENEWABLE;
360 1.1.1.2.6.1 pgoyette if (!flags.proxiable)
361 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_DISALLOW_PROXIABLE;
362 1.1.1.2.6.1 pgoyette if (flags.invalid)
363 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_DISALLOW_ALL_TIX;
364 1.1.1.2.6.1 pgoyette if (flags.require_preauth)
365 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_REQUIRES_PRE_AUTH;
366 1.1.1.2.6.1 pgoyette if (flags.require_hwauth)
367 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_REQUIRES_HW_AUTH;
368 1.1.1.2.6.1 pgoyette if (!flags.server)
369 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_DISALLOW_SVR;
370 1.1.1.2.6.1 pgoyette if (flags.change_pw)
371 1.1.1.2.6.1 pgoyette a |= KRB5_KDB_PWCHANGE_SERVICE;
372 1.1.1.2.6.1 pgoyette return a;
373 1.1.1.2.6.1 pgoyette }
374 1.1.1.2.6.1 pgoyette
375 1.1.1.2.6.1 pgoyette krb5_error_code
376 1.1.1.2.6.1 pgoyette entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent)
377 1.1.1.2.6.1 pgoyette {
378 1.1.1.2.6.1 pgoyette krb5_error_code ret;
379 1.1.1.2.6.1 pgoyette ssize_t sz;
380 1.1.1.2.6.1 pgoyette size_t i, k;
381 1.1.1.2.6.1 pgoyette size_t num_tl_data = 0;
382 1.1.1.2.6.1 pgoyette size_t num_key_data = 0;
383 1.1.1.2.6.1 pgoyette char *p;
384 1.1.1.2.6.1 pgoyette HDB_Ext_KeySet *hist_keys = NULL;
385 1.1.1.2.6.1 pgoyette HDB_extension *extp;
386 1.1.1.2.6.1 pgoyette time_t last_pw_chg = 0;
387 1.1.1.2.6.1 pgoyette time_t exp = 0;
388 1.1.1.2.6.1 pgoyette time_t pwexp = 0;
389 1.1.1.2.6.1 pgoyette unsigned int max_life = 0;
390 1.1.1.2.6.1 pgoyette unsigned int max_renew = 0;
391 1.1.1.2.6.1 pgoyette
392 1.1.1.2.6.1 pgoyette if (ent->modified_by)
393 1.1.1.2.6.1 pgoyette num_tl_data++;
394 1.1.1.2.6.1 pgoyette
395 1.1.1.2.6.1 pgoyette ret = hdb_entry_get_pw_change_time(ent, &last_pw_chg);
396 1.1.1.2.6.1 pgoyette if (ret) return ret;
397 1.1.1.2.6.1 pgoyette if (last_pw_chg)
398 1.1.1.2.6.1 pgoyette num_tl_data++;
399 1.1.1.2.6.1 pgoyette
400 1.1.1.2.6.1 pgoyette extp = hdb_find_extension(ent, choice_HDB_extension_data_hist_keys);
401 1.1.1.2.6.1 pgoyette if (extp)
402 1.1.1.2.6.1 pgoyette hist_keys = &extp->data.u.hist_keys;
403 1.1.1.2.6.1 pgoyette
404 1.1.1.2.6.1 pgoyette for (i = 0; i < ent->keys.len;i++) {
405 1.1.1.2.6.1 pgoyette if (ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD4 ||
406 1.1.1.2.6.1 pgoyette ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD5)
407 1.1.1.2.6.1 pgoyette continue;
408 1.1.1.2.6.1 pgoyette num_key_data++;
409 1.1.1.2.6.1 pgoyette }
410 1.1.1.2.6.1 pgoyette if (hist_keys) {
411 1.1.1.2.6.1 pgoyette for (i = 0; i < hist_keys->len; i++) {
412 1.1.1.2.6.1 pgoyette /*
413 1.1.1.2.6.1 pgoyette * MIT uses the highest kvno as the current kvno instead of
414 1.1.1.2.6.1 pgoyette * tracking kvno separately, so we can't dump keysets with kvno
415 1.1.1.2.6.1 pgoyette * higher than the entry's kvno.
416 1.1.1.2.6.1 pgoyette */
417 1.1.1.2.6.1 pgoyette if (hist_keys->val[i].kvno >= ent->kvno)
418 1.1.1.2.6.1 pgoyette continue;
419 1.1.1.2.6.1 pgoyette for (k = 0; k < hist_keys->val[i].keys.len; k++) {
420 1.1.1.2.6.1 pgoyette if (ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD4 ||
421 1.1.1.2.6.1 pgoyette ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD5)
422 1.1.1.2.6.1 pgoyette continue;
423 1.1.1.2.6.1 pgoyette num_key_data++;
424 1.1.1.2.6.1 pgoyette }
425 1.1.1.2.6.1 pgoyette }
426 1.1.1.2.6.1 pgoyette }
427 1.1.1.2.6.1 pgoyette
428 1.1.1.2.6.1 pgoyette ret = krb5_unparse_name(context, ent->principal, &p);
429 1.1.1.2.6.1 pgoyette if (ret) return ret;
430 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "princ\t38\t%u\t%u\t%u\t0\t%s\t%d",
431 1.1.1.2.6.1 pgoyette strlen(p), num_tl_data, num_key_data, p,
432 1.1.1.2.6.1 pgoyette flags_to_attr(ent->flags));
433 1.1.1.2.6.1 pgoyette free(p);
434 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
435 1.1.1.2.6.1 pgoyette
436 1.1.1.2.6.1 pgoyette if (ent->max_life)
437 1.1.1.2.6.1 pgoyette max_life = *ent->max_life;
438 1.1.1.2.6.1 pgoyette if (ent->max_renew)
439 1.1.1.2.6.1 pgoyette max_renew = *ent->max_renew;
440 1.1.1.2.6.1 pgoyette if (ent->valid_end)
441 1.1.1.2.6.1 pgoyette exp = *ent->valid_end;
442 1.1.1.2.6.1 pgoyette if (ent->pw_end)
443 1.1.1.2.6.1 pgoyette pwexp = *ent->pw_end;
444 1.1.1.2.6.1 pgoyette
445 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "\t%u\t%u\t%u\t%u\t0\t0\t0",
446 1.1.1.2.6.1 pgoyette max_life, max_renew, exp, pwexp);
447 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
448 1.1.1.2.6.1 pgoyette
449 1.1.1.2.6.1 pgoyette /* Dump TL data we know: last pw chg and modified_by */
450 1.1.1.2.6.1 pgoyette #define mit_KRB5_TL_LAST_PWD_CHANGE 1
451 1.1.1.2.6.1 pgoyette #define mit_KRB5_TL_MOD_PRINC 2
452 1.1.1.2.6.1 pgoyette if (last_pw_chg) {
453 1.1.1.2.6.1 pgoyette krb5_data d;
454 1.1.1.2.6.1 pgoyette time_t val;
455 1.1.1.2.6.1 pgoyette unsigned char *ptr;
456 1.1.1.2.6.1 pgoyette
457 1.1.1.2.6.1 pgoyette ptr = (unsigned char *)&last_pw_chg;
458 1.1.1.2.6.1 pgoyette val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
459 1.1.1.2.6.1 pgoyette d.data = &val;
460 1.1.1.2.6.1 pgoyette d.length = sizeof (last_pw_chg);
461 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "\t%u\t%u\t",
462 1.1.1.2.6.1 pgoyette mit_KRB5_TL_LAST_PWD_CHANGE, d.length);
463 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
464 1.1.1.2.6.1 pgoyette sz = append_hex(context, sp, 1, 1, &d);
465 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
466 1.1.1.2.6.1 pgoyette }
467 1.1.1.2.6.1 pgoyette if (ent->modified_by) {
468 1.1.1.2.6.1 pgoyette krb5_data d;
469 1.1.1.2.6.1 pgoyette unsigned int val;
470 1.1.1.2.6.1 pgoyette size_t plen;
471 1.1.1.2.6.1 pgoyette unsigned char *ptr;
472 1.1.1.2.6.1 pgoyette char *modby_p;
473 1.1.1.2.6.1 pgoyette
474 1.1.1.2.6.1 pgoyette ptr = (unsigned char *)&ent->modified_by->time;
475 1.1.1.2.6.1 pgoyette val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
476 1.1.1.2.6.1 pgoyette d.data = &val;
477 1.1.1.2.6.1 pgoyette d.length = sizeof (ent->modified_by->time);
478 1.1.1.2.6.1 pgoyette ret = krb5_unparse_name(context, ent->modified_by->principal, &modby_p);
479 1.1.1.2.6.1 pgoyette if (ret) return ret;
480 1.1.1.2.6.1 pgoyette plen = strlen(modby_p);
481 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "\t%u\t%u\t",
482 1.1.1.2.6.1 pgoyette mit_KRB5_TL_MOD_PRINC,
483 1.1.1.2.6.1 pgoyette d.length + plen + 1 /* NULL counted */);
484 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
485 1.1.1.2.6.1 pgoyette sz = append_hex(context, sp, 1, 1, &d);
486 1.1.1.2.6.1 pgoyette if (sz == -1) {
487 1.1.1.2.6.1 pgoyette free(modby_p);
488 1.1.1.2.6.1 pgoyette return ENOMEM;
489 1.1.1.2.6.1 pgoyette }
490 1.1.1.2.6.1 pgoyette d.data = modby_p;
491 1.1.1.2.6.1 pgoyette d.length = plen + 1;
492 1.1.1.2.6.1 pgoyette sz = append_hex(context, sp, 1, 1, &d);
493 1.1.1.2.6.1 pgoyette free(modby_p);
494 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
495 1.1.1.2.6.1 pgoyette }
496 1.1.1.2.6.1 pgoyette /*
497 1.1.1.2.6.1 pgoyette * Dump keys (remembering to not include any with kvno higher than
498 1.1.1.2.6.1 pgoyette * the entry's because MIT doesn't track entry kvno separately from
499 1.1.1.2.6.1 pgoyette * the entry's keys -- max kvno is it)
500 1.1.1.2.6.1 pgoyette */
501 1.1.1.2.6.1 pgoyette for (i = 0; i < ent->keys.len; i++) {
502 1.1.1.2.6.1 pgoyette if (ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD4 ||
503 1.1.1.2.6.1 pgoyette ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD5)
504 1.1.1.2.6.1 pgoyette continue;
505 1.1.1.2.6.1 pgoyette sz = append_mit_key(context, sp, ent->principal, ent->kvno,
506 1.1.1.2.6.1 pgoyette &ent->keys.val[i]);
507 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
508 1.1.1.2.6.1 pgoyette }
509 1.1.1.2.6.1 pgoyette for (i = 0; hist_keys && i < ent->kvno; i++) {
510 1.1.1.2.6.1 pgoyette size_t m;
511 1.1.1.2.6.1 pgoyette
512 1.1.1.2.6.1 pgoyette /* dump historical keys */
513 1.1.1.2.6.1 pgoyette for (k = 0; k < hist_keys->len; k++) {
514 1.1.1.2.6.1 pgoyette if (hist_keys->val[k].kvno != ent->kvno - i)
515 1.1.1.2.6.1 pgoyette continue;
516 1.1.1.2.6.1 pgoyette for (m = 0; m < hist_keys->val[k].keys.len; m++) {
517 1.1.1.2.6.1 pgoyette if (ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD4 ||
518 1.1.1.2.6.1 pgoyette ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD5)
519 1.1.1.2.6.1 pgoyette continue;
520 1.1.1.2.6.1 pgoyette sz = append_mit_key(context, sp, ent->principal,
521 1.1.1.2.6.1 pgoyette hist_keys->val[k].kvno,
522 1.1.1.2.6.1 pgoyette &hist_keys->val[k].keys.val[m]);
523 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
524 1.1.1.2.6.1 pgoyette }
525 1.1.1.2.6.1 pgoyette }
526 1.1.1.2.6.1 pgoyette }
527 1.1.1.2.6.1 pgoyette sz = append_string(context, sp, "\t-1;"); /* "extra data" */
528 1.1.1.2.6.1 pgoyette if (sz == -1) return ENOMEM;
529 1.1 elric return 0;
530 1.1 elric }
531 1.1 elric
532 1.1 elric krb5_error_code
533 1.1.1.2.6.1 pgoyette hdb_entry2string(krb5_context context, hdb_entry *ent, char **str)
534 1.1 elric {
535 1.1 elric krb5_error_code ret;
536 1.1 elric krb5_data data;
537 1.1 elric krb5_storage *sp;
538 1.1 elric
539 1.1 elric sp = krb5_storage_emem();
540 1.1.1.2.6.1 pgoyette if (sp == NULL) {
541 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
542 1.1 elric return ENOMEM;
543 1.1 elric }
544 1.1 elric
545 1.1 elric ret = entry2string_int(context, sp, ent);
546 1.1.1.2.6.1 pgoyette if (ret) {
547 1.1 elric krb5_storage_free(sp);
548 1.1 elric return ret;
549 1.1 elric }
550 1.1 elric
551 1.1 elric krb5_storage_write(sp, "\0", 1);
552 1.1 elric krb5_storage_to_data(sp, &data);
553 1.1 elric krb5_storage_free(sp);
554 1.1 elric *str = data.data;
555 1.1 elric return 0;
556 1.1 elric }
557 1.1 elric
558 1.1 elric /* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */
559 1.1 elric
560 1.1 elric krb5_error_code
561 1.1.1.2.6.1 pgoyette hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry,
562 1.1.1.2.6.1 pgoyette void *data)
563 1.1 elric {
564 1.1.1.2.6.1 pgoyette struct hdb_print_entry_arg *parg = data;
565 1.1 elric krb5_error_code ret;
566 1.1 elric krb5_storage *sp;
567 1.1 elric
568 1.1.1.2.6.1 pgoyette fflush(parg->out);
569 1.1.1.2.6.1 pgoyette sp = krb5_storage_from_fd(fileno(parg->out));
570 1.1.1.2.6.1 pgoyette if (sp == NULL) {
571 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
572 1.1 elric return ENOMEM;
573 1.1 elric }
574 1.1 elric
575 1.1.1.2.6.1 pgoyette switch (parg->fmt) {
576 1.1.1.2.6.1 pgoyette case HDB_DUMP_HEIMDAL:
577 1.1.1.2.6.1 pgoyette ret = entry2string_int(context, sp, &entry->entry);
578 1.1.1.2.6.1 pgoyette break;
579 1.1.1.2.6.1 pgoyette case HDB_DUMP_MIT:
580 1.1.1.2.6.1 pgoyette ret = entry2mit_string_int(context, sp, &entry->entry);
581 1.1.1.2.6.1 pgoyette break;
582 1.1.1.2.6.1 pgoyette default:
583 1.1.1.2.6.1 pgoyette heim_abort("Only two dump formats supported: Heimdal and MIT");
584 1.1.1.2.6.1 pgoyette }
585 1.1.1.2.6.1 pgoyette if (ret) {
586 1.1 elric krb5_storage_free(sp);
587 1.1 elric return ret;
588 1.1 elric }
589 1.1 elric
590 1.1 elric krb5_storage_write(sp, "\n", 1);
591 1.1 elric krb5_storage_free(sp);
592 1.1 elric return 0;
593 1.1 elric }
594