1 /*	$NetBSD: print.c,v 1.1.1.1 2011/04/13 18:14:42 elric Exp $	*/
2 
3 /*
4  * Copyright (c) 1999-2005 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of KTH nor the names of its contributors may be
20  *    used to endorse or promote products derived from this software without
21  *    specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
24  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
34 
35 #include "hdb_locl.h"
36 #include <krb5/hex.h>
37 #include <ctype.h>
38 
39 /*
40    This is the present contents of a dump line. This might change at
41    any time. Fields are separated by white space.
42 
43   principal
44   keyblock
45   	kvno
46 	keys...
47 		mkvno
48 		enctype
49 		keyvalue
50 		salt (- means use normal salt)
51   creation date and principal
52   modification date and principal
53   principal valid from date (not used)
54   principal valid end date (not used)
55   principal key expires (not used)
56   max ticket life
57   max renewable life
58   flags
59   generation number
60   */
61 
62 static krb5_error_code
63 append_string(krb5_context context, krb5_storage *sp, const char *fmt, ...)
64 {
65     krb5_error_code ret;
66     char *s;
67     va_list ap;
68     va_start(ap, fmt);
69     vasprintf(&s, fmt, ap);
70     va_end(ap);
71     if(s == NULL) {
72 	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
73 	return ENOMEM;
74     }
75     ret = krb5_storage_write(sp, s, strlen(s));
76     free(s);
77     return ret;
78 }
79 
80 static krb5_error_code
81 append_hex(krb5_context context, krb5_storage *sp, krb5_data *data)
82 {
83     int i, printable = 1;
84     char *p;
85 
86     p = data->data;
87     for(i = 0; i < data->length; i++)
88 	if(!isalnum((unsigned char)p[i]) && p[i] != '.'){
89 	    printable = 0;
90 	    break;
91 	}
92     if(printable)
93 	return append_string(context, sp, "\"%.*s\"",
94 			     data->length, data->data);
95     hex_encode(data->data, data->length, &p);
96     append_string(context, sp, "%s", p);
97     free(p);
98     return 0;
99 }
100 
101 static char *
102 time2str(time_t t)
103 {
104     static char buf[128];
105     strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", gmtime(&t));
106     return buf;
107 }
108 
109 static krb5_error_code
110 append_event(krb5_context context, krb5_storage *sp, Event *ev)
111 {
112     char *pr = NULL;
113     krb5_error_code ret;
114     if(ev == NULL)
115 	return append_string(context, sp, "- ");
116     if (ev->principal != NULL) {
117        ret = krb5_unparse_name(context, ev->principal, &pr);
118        if(ret)
119            return ret;
120     }
121     ret = append_string(context, sp, "%s:%s ",
122 			time2str(ev->time), pr ? pr : "UNKNOWN");
123     free(pr);
124     return ret;
125 }
126 
127 static krb5_error_code
128 entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
129 {
130     char *p;
131     int i;
132     krb5_error_code ret;
133 
134     /* --- principal */
135     ret = krb5_unparse_name(context, ent->principal, &p);
136     if(ret)
137 	return ret;
138     append_string(context, sp, "%s ", p);
139     free(p);
140     /* --- kvno */
141     append_string(context, sp, "%d", ent->kvno);
142     /* --- keys */
143     for(i = 0; i < ent->keys.len; i++){
144 	/* --- mkvno, keytype */
145 	if(ent->keys.val[i].mkvno)
146 	    append_string(context, sp, ":%d:%d:",
147 			  *ent->keys.val[i].mkvno,
148 			  ent->keys.val[i].key.keytype);
149 	else
150 	    append_string(context, sp, "::%d:",
151 			  ent->keys.val[i].key.keytype);
152 	/* --- keydata */
153 	append_hex(context, sp, &ent->keys.val[i].key.keyvalue);
154 	append_string(context, sp, ":");
155 	/* --- salt */
156 	if(ent->keys.val[i].salt){
157 	    append_string(context, sp, "%u/", ent->keys.val[i].salt->type);
158 	    append_hex(context, sp, &ent->keys.val[i].salt->salt);
159 	}else
160 	    append_string(context, sp, "-");
161     }
162     append_string(context, sp, " ");
163     /* --- created by */
164     append_event(context, sp, &ent->created_by);
165     /* --- modified by */
166     append_event(context, sp, ent->modified_by);
167 
168     /* --- valid start */
169     if(ent->valid_start)
170 	append_string(context, sp, "%s ", time2str(*ent->valid_start));
171     else
172 	append_string(context, sp, "- ");
173 
174     /* --- valid end */
175     if(ent->valid_end)
176 	append_string(context, sp, "%s ", time2str(*ent->valid_end));
177     else
178 	append_string(context, sp, "- ");
179 
180     /* --- password ends */
181     if(ent->pw_end)
182 	append_string(context, sp, "%s ", time2str(*ent->pw_end));
183     else
184 	append_string(context, sp, "- ");
185 
186     /* --- max life */
187     if(ent->max_life)
188 	append_string(context, sp, "%d ", *ent->max_life);
189     else
190 	append_string(context, sp, "- ");
191 
192     /* --- max renewable life */
193     if(ent->max_renew)
194 	append_string(context, sp, "%d ", *ent->max_renew);
195     else
196 	append_string(context, sp, "- ");
197 
198     /* --- flags */
199     append_string(context, sp, "%d ", HDBFlags2int(ent->flags));
200 
201     /* --- generation number */
202     if(ent->generation) {
203 	append_string(context, sp, "%s:%d:%d ", time2str(ent->generation->time),
204 		      ent->generation->usec,
205 		      ent->generation->gen);
206     } else
207 	append_string(context, sp, "- ");
208 
209     /* --- extensions */
210     if(ent->extensions && ent->extensions->len > 0) {
211 	for(i = 0; i < ent->extensions->len; i++) {
212 	    void *d;
213 	    size_t size, sz;
214 
215 	    ASN1_MALLOC_ENCODE(HDB_extension, d, size,
216 			       &ent->extensions->val[i], &sz, ret);
217 	    if (ret) {
218 		krb5_clear_error_message(context);
219 		return ret;
220 	    }
221 	    if(size != sz)
222 		krb5_abortx(context, "internal asn.1 encoder error");
223 
224 	    if (hex_encode(d, size, &p) < 0) {
225 		free(d);
226 		krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
227 		return ENOMEM;
228 	    }
229 
230 	    free(d);
231 	    append_string(context, sp, "%s%s", p,
232 			  ent->extensions->len - 1 != i ? ":" : "");
233 	    free(p);
234 	}
235     } else
236 	append_string(context, sp, "-");
237 
238 
239     return 0;
240 }
241 
242 krb5_error_code
243 hdb_entry2string (krb5_context context, hdb_entry *ent, char **str)
244 {
245     krb5_error_code ret;
246     krb5_data data;
247     krb5_storage *sp;
248 
249     sp = krb5_storage_emem();
250     if(sp == NULL) {
251 	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
252 	return ENOMEM;
253     }
254 
255     ret = entry2string_int(context, sp, ent);
256     if(ret) {
257 	krb5_storage_free(sp);
258 	return ret;
259     }
260 
261     krb5_storage_write(sp, "\0", 1);
262     krb5_storage_to_data(sp, &data);
263     krb5_storage_free(sp);
264     *str = data.data;
265     return 0;
266 }
267 
268 /* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */
269 
270 krb5_error_code
271 hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry, void *data)
272 {
273     krb5_error_code ret;
274     krb5_storage *sp;
275 
276     FILE *f = data;
277 
278     fflush(f);
279     sp = krb5_storage_from_fd(fileno(f));
280     if(sp == NULL) {
281 	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
282 	return ENOMEM;
283     }
284 
285     ret = entry2string_int(context, sp, &entry->entry);
286     if(ret) {
287 	krb5_storage_free(sp);
288 	return ret;
289     }
290 
291     krb5_storage_write(sp, "\n", 1);
292     krb5_storage_free(sp);
293     return 0;
294 }
295