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