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
37 can have any number of princ stanzas.
38 format is as follows (only \n indicates newlines)
39 princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38)
40 %d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU)
41 %d\t (number of tl_data)
42 %d\t (number of key data, e.g. how many keys for this user)
43 %d\t (extra data length)
46 %d\t (max lifetime, seconds)
47 %d\t (max renewable life, seconds)
48 %d\t (expiration, seconds since epoch or 2145830400 for never)
49 %d\t (password expiration, seconds, 0 for never)
50 %d\t (last successful auth, seconds since epoch)
51 %d\t (last failed auth, per above)
52 %d\t (failed auth count)
53 foreach tl_data 0 to number of tl_data - 1 as above
54 %d\t%d\t (data type, data length)
55 foreach tl_data 0 to length-1
56 %02x (tl data contents[element n])
57 except if tl_data length is 0
60 foreach key 0 to number of keys - 1 as above
61 %d\t%d\t (key data version, kvno)
62 foreach version 0 to key data version - 1 (a key or a salt)
63 %d\t%d\t(data type for this key, data length for this key)
64 foreach key data length 0 to length-1
65 %02x (key data contents[element n])
66 except if key_data length is 0
69 foreach extra data length 0 to length - 1
70 %02x (extra data part)
78 hex_to_octet_string(const char *ptr
, krb5_data
*data
)
82 for(i
= 0; i
< data
->length
; i
++) {
83 if(sscanf(ptr
+ 2 * i
, "%02x", &v
) != 1)
85 ((unsigned char*)data
->data
)[i
] = v
;
96 } while(q
&& *q
== '\0');
101 getdata(char **p
, unsigned char *buf
, size_t len
)
105 char *q
= nexttoken(p
);
107 while(*q
&& i
< len
) {
108 if(sscanf(q
, "%02x", &v
) != 1)
120 char *q
= nexttoken(p
);
121 sscanf(q
, "%d", &val
);
125 #include <kadm5/admin.h>
128 attr_to_flags(unsigned attr
, HDBFlags
*flags
)
130 flags
->postdate
= !(attr
& KRB5_KDB_DISALLOW_POSTDATED
);
131 flags
->forwardable
= !(attr
& KRB5_KDB_DISALLOW_FORWARDABLE
);
132 flags
->initial
= !!(attr
& KRB5_KDB_DISALLOW_TGT_BASED
);
133 flags
->renewable
= !(attr
& KRB5_KDB_DISALLOW_RENEWABLE
);
134 flags
->proxiable
= !(attr
& KRB5_KDB_DISALLOW_PROXIABLE
);
136 flags
->invalid
= !!(attr
& KRB5_KDB_DISALLOW_ALL_TIX
);
137 flags
->require_preauth
= !!(attr
& KRB5_KDB_REQUIRES_PRE_AUTH
);
138 flags
->require_hwauth
= !!(attr
& KRB5_KDB_REQUIRES_HW_AUTH
);
139 flags
->server
= !(attr
& KRB5_KDB_DISALLOW_SVR
);
140 flags
->change_pw
= !!(attr
& KRB5_KDB_PWCHANGE_SERVICE
);
141 flags
->client
= 1; /* XXX */
144 #define KRB5_KDB_SALTTYPE_NORMAL 0
145 #define KRB5_KDB_SALTTYPE_V4 1
146 #define KRB5_KDB_SALTTYPE_NOREALM 2
147 #define KRB5_KDB_SALTTYPE_ONLYREALM 3
148 #define KRB5_KDB_SALTTYPE_SPECIAL 4
149 #define KRB5_KDB_SALTTYPE_AFS3 5
151 static krb5_error_code
152 fix_salt(krb5_context context
, hdb_entry
*ent
, int key_num
)
155 Salt
*salt
= ent
->keys
.val
[key_num
].salt
;
157 switch((int)salt
->type
) {
158 case KRB5_KDB_SALTTYPE_NORMAL
:
159 salt
->type
= KRB5_PADATA_PW_SALT
;
161 case KRB5_KDB_SALTTYPE_V4
:
162 krb5_data_free(&salt
->salt
);
163 salt
->type
= KRB5_PADATA_PW_SALT
;
165 case KRB5_KDB_SALTTYPE_NOREALM
:
172 for (i
= 0; i
< ent
->principal
->name
.name_string
.len
; ++i
)
173 len
+= strlen(ent
->principal
->name
.name_string
.val
[i
]);
174 ret
= krb5_data_alloc (&salt
->salt
, len
);
178 for (i
= 0; i
< ent
->principal
->name
.name_string
.len
; ++i
) {
180 ent
->principal
->name
.name_string
.val
[i
],
181 strlen(ent
->principal
->name
.name_string
.val
[i
]));
182 p
+= strlen(ent
->principal
->name
.name_string
.val
[i
]);
185 salt
->type
= KRB5_PADATA_PW_SALT
;
188 case KRB5_KDB_SALTTYPE_ONLYREALM
:
189 krb5_data_free(&salt
->salt
);
190 ret
= krb5_data_copy(&salt
->salt
,
191 ent
->principal
->realm
,
192 strlen(ent
->principal
->realm
));
195 salt
->type
= KRB5_PADATA_PW_SALT
;
197 case KRB5_KDB_SALTTYPE_SPECIAL
:
198 salt
->type
= KRB5_PADATA_PW_SALT
;
200 case KRB5_KDB_SALTTYPE_AFS3
:
201 krb5_data_free(&salt
->salt
);
202 ret
= krb5_data_copy(&salt
->salt
,
203 ent
->principal
->realm
,
204 strlen(ent
->principal
->realm
));
207 salt
->type
= KRB5_PADATA_AFS3_SALT
;
216 mit_prop_dump(void *arg
, const char *file
)
222 struct hdb_entry_ex ent
;
224 struct prop_data
*pd
= arg
;
226 f
= fopen(file
, "r");
230 while(fgets(line
, sizeof(line
), f
)) {
244 memset(&ent
, 0, sizeof(ent
));
247 if(strcmp(q
, "kdb5_util") == 0) {
249 q
= nexttoken(&p
); /* load_dump */
250 if(strcmp(q
, "load_dump"))
251 errx(1, "line %d: unknown version", lineno
);
252 q
= nexttoken(&p
); /* load_dump */
253 if(strcmp(q
, "version"))
254 errx(1, "line %d: unknown version", lineno
);
255 q
= nexttoken(&p
); /* x.0 */
256 if(sscanf(q
, "%d", &major
) != 1)
257 errx(1, "line %d: unknown version", lineno
);
258 if(major
!= 4 && major
!= 5 && major
!= 6)
259 errx(1, "unknown dump file format, got %d, expected 4-6",
262 } else if(strcmp(q
, "policy") == 0) {
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 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 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 nexttoken(&p
); /* last auth */
302 nexttoken(&p
); /* last failed auth */
303 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_LAST_PWD_CHANGE
:
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);
323 ALLOC(ent
.entry
.extensions
);
324 ALLOC_SEQ(ent
.entry
.extensions
, 1);
325 ent
.entry
.extensions
->val
[0].mandatory
= 0;
326 ent
.entry
.extensions
->val
[0].data
.element
327 = choice_HDB_extension_data_last_pw_change
;
328 ent
.entry
.extensions
->val
[0].data
.u
.last_pw_change
= val
;
330 case mit_KRB5_TL_MOD_PRINC
:
331 buf
= malloc(tl_length
);
333 errx(ENOMEM
, "malloc");
334 getdata(&p
, buf
, tl_length
); /* data itself */
335 val
= buf
[0] | (buf
[1] << 8) | (buf
[2] << 16) | (buf
[3] << 24);
336 ret
= krb5_parse_name(pd
->context
, (char *)buf
+ 4, &princ
);
338 krb5_err(pd
->context
, 1, ret
,
339 "parse_name: %s", (char *)buf
+ 4);
341 ALLOC(ent
.entry
.modified_by
);
342 ent
.entry
.modified_by
->time
= val
;
343 ent
.entry
.modified_by
->principal
= princ
;
350 ALLOC_SEQ(&ent
.entry
.keys
, num_key_data
);
352 for(i
= 0; i
< num_key_data
; i
++) {
355 key_versions
= getint(&p
); /* key data version */
359 * An MIT dump file may contain multiple sets of keys with
360 * different kvnos. Since the Heimdal database can only represent
361 * one kvno per principal, we only want the highest set. Assume
362 * that set will be given first, and discard all keys with lower
365 if (kvno
> high_kvno
&& high_kvno
!= -1)
366 errx(1, "line %d: high kvno keys given after low kvno keys",
368 else if (kvno
< high_kvno
) {
369 nexttoken(&p
); /* key type */
370 nexttoken(&p
); /* key length */
371 nexttoken(&p
); /* key */
372 if (key_versions
> 1) {
373 nexttoken(&p
); /* salt type */
374 nexttoken(&p
); /* salt length */
375 nexttoken(&p
); /* salt */
377 ent
.entry
.keys
.len
--;
380 ent
.entry
.kvno
= kvno
;
382 ALLOC(ent
.entry
.keys
.val
[i
].mkvno
);
383 *ent
.entry
.keys
.val
[i
].mkvno
= 1;
385 /* key version 0 -- actual key */
386 ent
.entry
.keys
.val
[i
].key
.keytype
= getint(&p
); /* key type */
387 tmp
= getint(&p
); /* key length */
388 /* the first two bytes of the key is the key length --
390 krb5_data_alloc(&ent
.entry
.keys
.val
[i
].key
.keyvalue
, tmp
- 2);
391 q
= nexttoken(&p
); /* key itself */
392 hex_to_octet_string(q
+ 4, &ent
.entry
.keys
.val
[i
].key
.keyvalue
);
394 if(key_versions
> 1) {
395 /* key version 1 -- optional salt */
396 ALLOC(ent
.entry
.keys
.val
[i
].salt
);
397 ent
.entry
.keys
.val
[i
].salt
->type
= getint(&p
); /* salt type */
398 tmp
= getint(&p
); /* salt length */
400 krb5_data_alloc(&ent
.entry
.keys
.val
[i
].salt
->salt
, tmp
- 2);
401 q
= nexttoken(&p
); /* salt itself */
402 hex_to_octet_string(q
+ 4,
403 &ent
.entry
.keys
.val
[i
].salt
->salt
);
405 ent
.entry
.keys
.val
[i
].salt
->salt
.length
= 0;
406 ent
.entry
.keys
.val
[i
].salt
->salt
.data
= NULL
;
407 getint(&p
); /* -1, if no data. */
409 fix_salt(pd
->context
, &ent
.entry
, i
);
412 nexttoken(&p
); /* extra data */
413 v5_prop(pd
->context
, NULL
, &ent
, arg
);