2 * Copyright (c) 2000 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 __RCSID("$Heimdal: mit_dump.c 21745 2007-07-31 16:11:25Z lha $"
40 can have any number of princ stanzas.
41 format is as follows (only \n indicates newlines)
42 princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38)
43 %d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU)
44 %d\t (number of tl_data)
45 %d\t (number of key data, e.g. how many keys for this user)
46 %d\t (extra data length)
49 %d\t (max lifetime, seconds)
50 %d\t (max renewable life, seconds)
51 %d\t (expiration, seconds since epoch or 2145830400 for never)
52 %d\t (password expiration, seconds, 0 for never)
53 %d\t (last successful auth, seconds since epoch)
54 %d\t (last failed auth, per above)
55 %d\t (failed auth count)
56 foreach tl_data 0 to number of tl_data - 1 as above
57 %d\t%d\t (data type, data length)
58 foreach tl_data 0 to length-1
59 %02x (tl data contents[element n])
60 except if tl_data length is 0
63 foreach key 0 to number of keys - 1 as above
64 %d\t%d\t (key data version, kvno)
65 foreach version 0 to key data version - 1 (a key or a salt)
66 %d\t%d\t(data type for this key, data length for this key)
67 foreach key data length 0 to length-1
68 %02x (key data contents[element n])
69 except if key_data length is 0
72 foreach extra data length 0 to length - 1
73 %02x (extra data part)
81 hex_to_octet_string(const char *ptr
, krb5_data
*data
)
85 for(i
= 0; i
< data
->length
; i
++) {
86 if(sscanf(ptr
+ 2 * i
, "%02x", &v
) != 1)
88 ((unsigned char*)data
->data
)[i
] = v
;
99 } while(q
&& *q
== '\0');
104 getdata(char **p
, unsigned char *buf
, size_t len
)
108 char *q
= nexttoken(p
);
110 while(*q
&& i
< len
) {
111 if(sscanf(q
, "%02x", &v
) != 1)
123 char *q
= nexttoken(p
);
124 sscanf(q
, "%d", &val
);
128 #include <kadm5/admin.h>
131 attr_to_flags(unsigned attr
, HDBFlags
*flags
)
133 flags
->postdate
= !(attr
& KRB5_KDB_DISALLOW_POSTDATED
);
134 flags
->forwardable
= !(attr
& KRB5_KDB_DISALLOW_FORWARDABLE
);
135 flags
->initial
= !!(attr
& KRB5_KDB_DISALLOW_TGT_BASED
);
136 flags
->renewable
= !(attr
& KRB5_KDB_DISALLOW_RENEWABLE
);
137 flags
->proxiable
= !(attr
& KRB5_KDB_DISALLOW_PROXIABLE
);
139 flags
->invalid
= !!(attr
& KRB5_KDB_DISALLOW_ALL_TIX
);
140 flags
->require_preauth
= !!(attr
& KRB5_KDB_REQUIRES_PRE_AUTH
);
142 flags
->server
= !(attr
& KRB5_KDB_DISALLOW_SVR
);
143 flags
->change_pw
= !!(attr
& KRB5_KDB_PWCHANGE_SERVICE
);
144 flags
->client
= 1; /* XXX */
147 #define KRB5_KDB_SALTTYPE_NORMAL 0
148 #define KRB5_KDB_SALTTYPE_V4 1
149 #define KRB5_KDB_SALTTYPE_NOREALM 2
150 #define KRB5_KDB_SALTTYPE_ONLYREALM 3
151 #define KRB5_KDB_SALTTYPE_SPECIAL 4
152 #define KRB5_KDB_SALTTYPE_AFS3 5
154 static krb5_error_code
155 fix_salt(krb5_context context
, hdb_entry
*ent
, int key_num
)
158 Salt
*salt
= ent
->keys
.val
[key_num
].salt
;
160 switch((int)salt
->type
) {
161 case KRB5_KDB_SALTTYPE_NORMAL
:
162 salt
->type
= KRB5_PADATA_PW_SALT
;
164 case KRB5_KDB_SALTTYPE_V4
:
165 krb5_data_free(&salt
->salt
);
166 salt
->type
= KRB5_PADATA_PW_SALT
;
168 case KRB5_KDB_SALTTYPE_NOREALM
:
175 for (i
= 0; i
< ent
->principal
->name
.name_string
.len
; ++i
)
176 len
+= strlen(ent
->principal
->name
.name_string
.val
[i
]);
177 ret
= krb5_data_alloc (&salt
->salt
, len
);
181 for (i
= 0; i
< ent
->principal
->name
.name_string
.len
; ++i
) {
183 ent
->principal
->name
.name_string
.val
[i
],
184 strlen(ent
->principal
->name
.name_string
.val
[i
]));
185 p
+= strlen(ent
->principal
->name
.name_string
.val
[i
]);
188 salt
->type
= KRB5_PADATA_PW_SALT
;
191 case KRB5_KDB_SALTTYPE_ONLYREALM
:
192 krb5_data_free(&salt
->salt
);
193 ret
= krb5_data_copy(&salt
->salt
,
194 ent
->principal
->realm
,
195 strlen(ent
->principal
->realm
));
198 salt
->type
= KRB5_PADATA_PW_SALT
;
200 case KRB5_KDB_SALTTYPE_SPECIAL
:
201 salt
->type
= KRB5_PADATA_PW_SALT
;
203 case KRB5_KDB_SALTTYPE_AFS3
:
204 krb5_data_free(&salt
->salt
);
205 ret
= krb5_data_copy(&salt
->salt
,
206 ent
->principal
->realm
,
207 strlen(ent
->principal
->realm
));
210 salt
->type
= KRB5_PADATA_AFS3_SALT
;
219 mit_prop_dump(void *arg
, const char *file
)
225 struct hdb_entry_ex ent
;
227 struct prop_data
*pd
= arg
;
229 f
= fopen(file
, "r");
233 while(fgets(line
, sizeof(line
), f
)) {
240 int extra_data_length
;
247 memset(&ent
, 0, sizeof(ent
));
250 if(strcmp(q
, "kdb5_util") == 0) {
252 q
= nexttoken(&p
); /* load_dump */
253 if(strcmp(q
, "load_dump"))
254 errx(1, "line %d: unknown version", lineno
);
255 q
= nexttoken(&p
); /* load_dump */
256 if(strcmp(q
, "version"))
257 errx(1, "line %d: unknown version", lineno
);
258 q
= nexttoken(&p
); /* x.0 */
259 if(sscanf(q
, "%d", &major
) != 1)
260 errx(1, "line %d: unknown version", lineno
);
262 errx(1, "unknown dump file format, got %d, expected 4", major
);
264 } else if(strcmp(q
, "princ") != 0) {
265 warnx("line %d: not a principal", lineno
);
270 warnx("line %d: bad base length %d != 38", lineno
, tmp
);
273 q
= nexttoken(&p
); /* length of principal */
274 num_tl_data
= getint(&p
); /* number of tl-data */
275 num_key_data
= getint(&p
); /* number of key-data */
276 extra_data_length
= getint(&p
); /* length of extra data */
277 q
= nexttoken(&p
); /* principal name */
278 krb5_parse_name(pd
->context
, q
, &ent
.entry
.principal
);
279 attributes
= getint(&p
); /* attributes */
280 attr_to_flags(attributes
, &ent
.entry
.flags
);
281 tmp
= getint(&p
); /* max life */
283 ALLOC(ent
.entry
.max_life
);
284 *ent
.entry
.max_life
= tmp
;
286 tmp
= getint(&p
); /* max renewable life */
288 ALLOC(ent
.entry
.max_renew
);
289 *ent
.entry
.max_renew
= tmp
;
291 tmp
= getint(&p
); /* expiration */
292 if(tmp
!= 0 && tmp
!= 2145830400) {
293 ALLOC(ent
.entry
.valid_end
);
294 *ent
.entry
.valid_end
= tmp
;
296 tmp
= getint(&p
); /* pw expiration */
298 ALLOC(ent
.entry
.pw_end
);
299 *ent
.entry
.pw_end
= tmp
;
301 q
= nexttoken(&p
); /* last auth */
302 q
= nexttoken(&p
); /* last failed auth */
303 q
= nexttoken(&p
); /* fail auth count */
304 for(i
= 0; i
< num_tl_data
; i
++) {
306 int tl_type
, tl_length
;
308 krb5_principal princ
;
310 tl_type
= getint(&p
); /* data type */
311 tl_length
= getint(&p
); /* data length */
313 #define mit_KRB5_TL_LAST_PWD_CHANGE 1
314 #define mit_KRB5_TL_MOD_PRINC 2
316 case mit_KRB5_TL_MOD_PRINC
:
317 buf
= malloc(tl_length
);
319 errx(ENOMEM
, "malloc");
320 getdata(&p
, buf
, tl_length
); /* data itself */
321 val
= buf
[0] | (buf
[1] << 8) | (buf
[2] << 16) | (buf
[3] << 24);
322 ret
= krb5_parse_name(pd
->context
, (char *)buf
+ 4, &princ
);
324 ALLOC(ent
.entry
.modified_by
);
325 ent
.entry
.modified_by
->time
= val
;
326 ent
.entry
.modified_by
->principal
= princ
;
333 ALLOC_SEQ(&ent
.entry
.keys
, num_key_data
);
334 for(i
= 0; i
< num_key_data
; i
++) {
336 key_versions
= getint(&p
); /* key data version */
337 ent
.entry
.kvno
= getint(&p
); /* XXX kvno */
339 ALLOC(ent
.entry
.keys
.val
[i
].mkvno
);
340 *ent
.entry
.keys
.val
[i
].mkvno
= 0;
342 /* key version 0 -- actual key */
343 ent
.entry
.keys
.val
[i
].key
.keytype
= getint(&p
); /* key type */
344 tmp
= getint(&p
); /* key length */
345 /* the first two bytes of the key is the key length --
347 krb5_data_alloc(&ent
.entry
.keys
.val
[i
].key
.keyvalue
, tmp
- 2);
348 q
= nexttoken(&p
); /* key itself */
349 hex_to_octet_string(q
+ 4, &ent
.entry
.keys
.val
[i
].key
.keyvalue
);
351 if(key_versions
> 1) {
352 /* key version 1 -- optional salt */
353 ALLOC(ent
.entry
.keys
.val
[i
].salt
);
354 ent
.entry
.keys
.val
[i
].salt
->type
= getint(&p
); /* salt type */
355 tmp
= getint(&p
); /* salt length */
357 krb5_data_alloc(&ent
.entry
.keys
.val
[i
].salt
->salt
, tmp
- 2);
358 q
= nexttoken(&p
); /* salt itself */
359 hex_to_octet_string(q
+ 4,
360 &ent
.entry
.keys
.val
[i
].salt
->salt
);
362 ent
.entry
.keys
.val
[i
].salt
->salt
.length
= 0;
363 ent
.entry
.keys
.val
[i
].salt
->salt
.data
= NULL
;
364 tmp
= getint(&p
); /* -1, if no data. */
366 fix_salt(pd
->context
, &ent
.entry
, i
);
369 q
= nexttoken(&p
); /* extra data */
370 v5_prop(pd
->context
, NULL
, &ent
, arg
);