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("$Id: mit_dump.c,v 1.3 2000/08/09 09:57:37 joda Exp $");
39 can have any number of princ stanzas.
40 format is as follows (only \n indicates newlines)
41 princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38)
42 %d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU)
43 %d\t (number of tl_data)
44 %d\t (number of key data, e.g. how many keys for this user)
45 %d\t (extra data length)
48 %d\t (max lifetime, seconds)
49 %d\t (max renewable life, seconds)
50 %d\t (expiration, seconds since epoch or 2145830400 for never)
51 %d\t (password expiration, seconds, 0 for never)
52 %d\t (last successful auth, seconds since epoch)
53 %d\t (last failed auth, per above)
54 %d\t (failed auth count)
55 foreach tl_data 0 to number of tl_data - 1 as above
56 %d\t%d\t (data type, data length)
57 foreach tl_data 0 to length-1
58 %02x (tl data contents[element n])
59 except if tl_data length is 0
62 foreach key 0 to number of keys - 1 as above
63 %d\t%d\t (key data version, kvno)
64 foreach version 0 to key data version - 1 (a key or a salt)
65 %d\t%d\t(data type for this key, data length for this key)
66 foreach key data length 0 to length-1
67 %02x (key data contents[element n])
68 except if key_data length is 0
71 foreach extra data length 0 to length - 1
72 %02x (extra data part)
80 hex_to_octet_string(const char *ptr
, krb5_data
*data
)
84 for(i
= 0; i
< data
->length
; i
++) {
85 if(sscanf(ptr
+ 2 * i
, "%02x", &v
) != 1)
87 ((unsigned char*)data
->data
)[i
] = v
;
98 } while(q
&& *q
== '\0');
103 getdata(char **p
, unsigned char *buf
, size_t len
)
107 char *q
= nexttoken(p
);
109 while(*q
&& i
< len
) {
110 if(sscanf(q
, "%02x", &v
) != 1)
122 char *q
= nexttoken(p
);
123 sscanf(q
, "%d", &val
);
127 #include <kadm5/admin.h>
130 attr_to_flags(unsigned attr
, HDBFlags
*flags
)
132 flags
->postdate
= !(attr
& KRB5_KDB_DISALLOW_POSTDATED
);
133 flags
->forwardable
= !(attr
& KRB5_KDB_DISALLOW_FORWARDABLE
);
134 flags
->initial
= !!(attr
& KRB5_KDB_DISALLOW_TGT_BASED
);
135 flags
->renewable
= !(attr
& KRB5_KDB_DISALLOW_RENEWABLE
);
136 flags
->proxiable
= !(attr
& KRB5_KDB_DISALLOW_PROXIABLE
);
138 flags
->invalid
= !!(attr
& KRB5_KDB_DISALLOW_ALL_TIX
);
139 flags
->require_preauth
= !!(attr
& KRB5_KDB_REQUIRES_PRE_AUTH
);
141 flags
->server
= !(attr
& KRB5_KDB_DISALLOW_SVR
);
142 flags
->change_pw
= !!(attr
& KRB5_KDB_PWCHANGE_SERVICE
);
143 flags
->client
= 1; /* XXX */
146 #define KRB5_KDB_SALTTYPE_NORMAL 0
147 #define KRB5_KDB_SALTTYPE_V4 1
148 #define KRB5_KDB_SALTTYPE_NOREALM 2
149 #define KRB5_KDB_SALTTYPE_ONLYREALM 3
150 #define KRB5_KDB_SALTTYPE_SPECIAL 4
151 #define KRB5_KDB_SALTTYPE_AFS3 5
153 static krb5_error_code
154 fix_salt(krb5_context context
, hdb_entry
*ent
, int key_num
)
157 Salt
*salt
= ent
->keys
.val
[key_num
].salt
;
159 switch((int)salt
->type
) {
160 case KRB5_KDB_SALTTYPE_NORMAL
:
161 salt
->type
= KRB5_PADATA_PW_SALT
;
163 case KRB5_KDB_SALTTYPE_V4
:
164 krb5_data_free(&salt
->salt
);
165 salt
->type
= KRB5_PADATA_PW_SALT
;
167 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 ent
;
227 struct prop_data
*pd
= arg
;
229 f
= fopen(file
, "r");
233 while(fgets(buf
, sizeof(buf
), 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
.principal
);
279 attributes
= getint(&p
); /* attributes */
280 attr_to_flags(attributes
, &ent
.flags
);
281 tmp
= getint(&p
); /* max life */
286 tmp
= getint(&p
); /* max renewable life */
288 ALLOC(ent
.max_renew
);
289 *ent
.max_renew
= tmp
;
291 tmp
= getint(&p
); /* expiration */
292 if(tmp
!= 0 && tmp
!= 2145830400) {
293 ALLOC(ent
.valid_end
);
294 *ent
.valid_end
= tmp
;
296 tmp
= getint(&p
); /* pw expiration */
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 KRB5_TL_LAST_PWD_CHANGE 1
314 #define KRB5_TL_MOD_PRINC 2
316 case KRB5_TL_MOD_PRINC
:
317 buf
= malloc(tl_length
);
318 getdata(&p
, buf
, tl_length
); /* data itself */
319 val
= buf
[0] | (buf
[1] << 8) | (buf
[2] << 16) | (buf
[3] << 24);
320 ret
= krb5_parse_name(pd
->context
, buf
+ 4, &princ
);
322 ALLOC(ent
.modified_by
);
323 ent
.modified_by
->time
= val
;
324 ent
.modified_by
->principal
= princ
;
331 ALLOC_SEQ(&ent
.keys
, num_key_data
);
332 for(i
= 0; i
< num_key_data
; i
++) {
334 key_versions
= getint(&p
); /* key data version */
335 ent
.kvno
= getint(&p
); /* XXX kvno */
337 ALLOC(ent
.keys
.val
[i
].mkvno
);
338 *ent
.keys
.val
[i
].mkvno
= 0;
340 /* key version 0 -- actual key */
341 ent
.keys
.val
[i
].key
.keytype
= getint(&p
); /* key type */
342 tmp
= getint(&p
); /* key length */
343 /* the first two bytes of the key is the key length --
345 krb5_data_alloc(&ent
.keys
.val
[i
].key
.keyvalue
, tmp
- 2);
346 q
= nexttoken(&p
); /* key itself */
347 hex_to_octet_string(q
+ 4, &ent
.keys
.val
[i
].key
.keyvalue
);
349 if(key_versions
> 1) {
350 /* key version 1 -- optional salt */
351 ALLOC(ent
.keys
.val
[i
].salt
);
352 ent
.keys
.val
[i
].salt
->type
= getint(&p
); /* salt type */
353 tmp
= getint(&p
); /* salt length */
355 krb5_data_alloc(&ent
.keys
.val
[i
].salt
->salt
, tmp
- 2);
356 q
= nexttoken(&p
); /* salt itself */
357 hex_to_octet_string(q
+ 4, &ent
.keys
.val
[i
].salt
->salt
);
359 ent
.keys
.val
[i
].salt
->salt
.length
= 0;
360 ent
.keys
.val
[i
].salt
->salt
.data
= NULL
;
361 tmp
= getint(&p
); /* -1, if no data. */
363 fix_salt(pd
->context
, &ent
, i
);
366 q
= nexttoken(&p
); /* extra data */
367 v5_prop(pd
->context
, NULL
, &ent
, arg
);