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