1 1.1 elric /* $NetBSD: print.c,v 1.2 2017/01/28 21:31:48 christos Exp $ */ 2 1.1 elric 3 1.1 elric /* 4 1.1 elric * Copyright (c) 1999-2005 Kungliga Tekniska Hgskolan 5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden). 6 1.1 elric * All rights reserved. 7 1.1 elric * 8 1.1 elric * Redistribution and use in source and binary forms, with or without 9 1.1 elric * modification, are permitted provided that the following conditions 10 1.1 elric * are met: 11 1.1 elric * 12 1.1 elric * 1. Redistributions of source code must retain the above copyright 13 1.1 elric * notice, this list of conditions and the following disclaimer. 14 1.1 elric * 15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 elric * notice, this list of conditions and the following disclaimer in the 17 1.1 elric * documentation and/or other materials provided with the distribution. 18 1.1 elric * 19 1.1 elric * 3. Neither the name of KTH nor the names of its contributors may be 20 1.1 elric * used to endorse or promote products derived from this software without 21 1.1 elric * specific prior written permission. 22 1.1 elric * 23 1.1 elric * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 24 1.1 elric * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 1.1 elric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 27 1.1 elric * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 1.1 elric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 1.1 elric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 1.1 elric * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 1.1 elric * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 1.1 elric * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 1.1 elric * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 34 1.1 elric 35 1.1 elric #include "hdb_locl.h" 36 1.1 elric #include <krb5/hex.h> 37 1.1 elric #include <ctype.h> 38 1.1 elric 39 1.1 elric /* 40 1.1 elric This is the present contents of a dump line. This might change at 41 1.1 elric any time. Fields are separated by white space. 42 1.1 elric 43 1.1 elric principal 44 1.1 elric keyblock 45 1.1 elric kvno 46 1.1 elric keys... 47 1.1 elric mkvno 48 1.1 elric enctype 49 1.1 elric keyvalue 50 1.1 elric salt (- means use normal salt) 51 1.1 elric creation date and principal 52 1.1 elric modification date and principal 53 1.1 elric principal valid from date (not used) 54 1.1 elric principal valid end date (not used) 55 1.1 elric principal key expires (not used) 56 1.1 elric max ticket life 57 1.1 elric max renewable life 58 1.1 elric flags 59 1.1 elric generation number 60 1.1 elric */ 61 1.1 elric 62 1.2 christos /* 63 1.2 christos * These utility functions return the number of bytes written or -1, and 64 1.2 christos * they set an error in the context. 65 1.2 christos */ 66 1.2 christos static ssize_t 67 1.1 elric append_string(krb5_context context, krb5_storage *sp, const char *fmt, ...) 68 1.1 elric { 69 1.2 christos ssize_t sz; 70 1.1 elric char *s; 71 1.2 christos int rc; 72 1.1 elric va_list ap; 73 1.1 elric va_start(ap, fmt); 74 1.2 christos rc = vasprintf(&s, fmt, ap); 75 1.1 elric va_end(ap); 76 1.2 christos if(rc < 0) { 77 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 78 1.2 christos return -1; 79 1.1 elric } 80 1.2 christos sz = krb5_storage_write(sp, s, strlen(s)); 81 1.1 elric free(s); 82 1.2 christos return sz; 83 1.1 elric } 84 1.1 elric 85 1.1 elric static krb5_error_code 86 1.2 christos append_hex(krb5_context context, krb5_storage *sp, 87 1.2 christos int always_encode, int lower, krb5_data *data) 88 1.1 elric { 89 1.2 christos ssize_t sz; 90 1.2 christos int printable = 1; 91 1.2 christos size_t i; 92 1.1 elric char *p; 93 1.1 elric 94 1.1 elric p = data->data; 95 1.2 christos if (!always_encode) { 96 1.2 christos for (i = 0; i < data->length; i++) { 97 1.2 christos if (!isalnum((unsigned char)p[i]) && p[i] != '.'){ 98 1.2 christos printable = 0; 99 1.2 christos break; 100 1.2 christos } 101 1.2 christos } 102 1.2 christos } 103 1.2 christos if (printable && !always_encode) 104 1.1 elric return append_string(context, sp, "\"%.*s\"", 105 1.1 elric data->length, data->data); 106 1.2 christos sz = hex_encode(data->data, data->length, &p); 107 1.2 christos if (sz == -1) return sz; 108 1.2 christos if (lower) 109 1.2 christos strlwr(p); 110 1.2 christos sz = append_string(context, sp, "%s", p); 111 1.1 elric free(p); 112 1.2 christos return sz; 113 1.1 elric } 114 1.1 elric 115 1.1 elric static char * 116 1.1 elric time2str(time_t t) 117 1.1 elric { 118 1.1 elric static char buf[128]; 119 1.1 elric strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", gmtime(&t)); 120 1.1 elric return buf; 121 1.1 elric } 122 1.1 elric 123 1.2 christos static ssize_t 124 1.1 elric append_event(krb5_context context, krb5_storage *sp, Event *ev) 125 1.1 elric { 126 1.2 christos krb5_error_code ret; 127 1.2 christos ssize_t sz; 128 1.1 elric char *pr = NULL; 129 1.1 elric if(ev == NULL) 130 1.1 elric return append_string(context, sp, "- "); 131 1.1 elric if (ev->principal != NULL) { 132 1.1 elric ret = krb5_unparse_name(context, ev->principal, &pr); 133 1.2 christos if (ret) return -1; /* krb5_unparse_name() sets error info */ 134 1.1 elric } 135 1.2 christos sz = append_string(context, sp, "%s:%s ", time2str(ev->time), 136 1.2 christos pr ? pr : "UNKNOWN"); 137 1.1 elric free(pr); 138 1.2 christos return sz; 139 1.2 christos } 140 1.2 christos 141 1.2 christos #define KRB5_KDB_SALTTYPE_NORMAL 0 142 1.2 christos #define KRB5_KDB_SALTTYPE_V4 1 143 1.2 christos #define KRB5_KDB_SALTTYPE_NOREALM 2 144 1.2 christos #define KRB5_KDB_SALTTYPE_ONLYREALM 3 145 1.2 christos #define KRB5_KDB_SALTTYPE_SPECIAL 4 146 1.2 christos #define KRB5_KDB_SALTTYPE_AFS3 5 147 1.2 christos 148 1.2 christos static ssize_t 149 1.2 christos append_mit_key(krb5_context context, krb5_storage *sp, 150 1.2 christos krb5_const_principal princ, 151 1.2 christos unsigned int kvno, Key *key) 152 1.2 christos { 153 1.2 christos krb5_error_code ret; 154 1.2 christos krb5_salt k5salt; 155 1.2 christos ssize_t sz; 156 1.2 christos size_t key_versions = key->salt ? 2 : 1; 157 1.2 christos size_t decrypted_key_length; 158 1.2 christos char buf[2]; 159 1.2 christos krb5_data keylenbytes; 160 1.2 christos unsigned int salttype; 161 1.2 christos 162 1.2 christos sz = append_string(context, sp, "\t%u\t%u\t%d\t%d\t", key_versions, kvno, 163 1.2 christos key->key.keytype, key->key.keyvalue.length + 2); 164 1.2 christos if (sz == -1) return sz; 165 1.2 christos ret = krb5_enctype_keysize(context, key->key.keytype, &decrypted_key_length); 166 1.2 christos if (ret) return -1; /* XXX we lose the error code */ 167 1.2 christos buf[0] = decrypted_key_length & 0xff; 168 1.2 christos buf[1] = (decrypted_key_length & 0xff00) >> 8; 169 1.2 christos keylenbytes.data = buf; 170 1.2 christos keylenbytes.length = sizeof (buf); 171 1.2 christos sz = append_hex(context, sp, 1, 1, &keylenbytes); 172 1.2 christos if (sz == -1) return sz; 173 1.2 christos sz = append_hex(context, sp, 1, 1, &key->key.keyvalue); 174 1.2 christos if (!key->salt) 175 1.2 christos return sz; 176 1.2 christos 177 1.2 christos /* Map salt to MIT KDB style */ 178 1.2 christos switch (key->salt->type) { 179 1.2 christos case KRB5_PADATA_PW_SALT: 180 1.2 christos 181 1.2 christos /* 182 1.2 christos * Compute normal salt and then see whether it matches the stored one 183 1.2 christos */ 184 1.2 christos ret = krb5_get_pw_salt(context, princ, &k5salt); 185 1.2 christos if (ret) return -1; 186 1.2 christos if (k5salt.saltvalue.length == key->salt->salt.length && 187 1.2 christos memcmp(k5salt.saltvalue.data, key->salt->salt.data, 188 1.2 christos k5salt.saltvalue.length) == 0) 189 1.2 christos salttype = KRB5_KDB_SALTTYPE_NORMAL; /* matches */ 190 1.2 christos else if (key->salt->salt.length == strlen(princ->realm) && 191 1.2 christos memcmp(key->salt->salt.data, princ->realm, 192 1.2 christos key->salt->salt.length) == 0) 193 1.2 christos salttype = KRB5_KDB_SALTTYPE_ONLYREALM; /* matches realm */ 194 1.2 christos else if (key->salt->salt.length == 195 1.2 christos k5salt.saltvalue.length - strlen(princ->realm) && 196 1.2 christos memcmp((char *)k5salt.saltvalue.data + strlen(princ->realm), 197 1.2 christos key->salt->salt.data, key->salt->salt.length) == 0) 198 1.2 christos salttype = KRB5_KDB_SALTTYPE_NOREALM; /* matches w/o realm */ 199 1.2 christos else 200 1.2 christos salttype = KRB5_KDB_SALTTYPE_NORMAL; /* hope for best */ 201 1.2 christos 202 1.2 christos break; 203 1.2 christos 204 1.2 christos case KRB5_PADATA_AFS3_SALT: 205 1.2 christos salttype = KRB5_KDB_SALTTYPE_AFS3; 206 1.2 christos break; 207 1.2 christos 208 1.2 christos default: 209 1.2 christos return -1; 210 1.2 christos } 211 1.2 christos 212 1.2 christos sz = append_string(context, sp, "\t%u\t%u\t", salttype, 213 1.2 christos key->salt->salt.length); 214 1.2 christos if (sz == -1) return sz; 215 1.2 christos return append_hex(context, sp, 1, 1, &key->salt->salt); 216 1.1 elric } 217 1.1 elric 218 1.1 elric static krb5_error_code 219 1.1 elric entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent) 220 1.1 elric { 221 1.1 elric char *p; 222 1.2 christos size_t i; 223 1.1 elric krb5_error_code ret; 224 1.1 elric 225 1.1 elric /* --- principal */ 226 1.1 elric ret = krb5_unparse_name(context, ent->principal, &p); 227 1.1 elric if(ret) 228 1.1 elric return ret; 229 1.1 elric append_string(context, sp, "%s ", p); 230 1.1 elric free(p); 231 1.1 elric /* --- kvno */ 232 1.1 elric append_string(context, sp, "%d", ent->kvno); 233 1.1 elric /* --- keys */ 234 1.1 elric for(i = 0; i < ent->keys.len; i++){ 235 1.1 elric /* --- mkvno, keytype */ 236 1.1 elric if(ent->keys.val[i].mkvno) 237 1.1 elric append_string(context, sp, ":%d:%d:", 238 1.1 elric *ent->keys.val[i].mkvno, 239 1.1 elric ent->keys.val[i].key.keytype); 240 1.1 elric else 241 1.1 elric append_string(context, sp, "::%d:", 242 1.1 elric ent->keys.val[i].key.keytype); 243 1.1 elric /* --- keydata */ 244 1.2 christos append_hex(context, sp, 0, 0, &ent->keys.val[i].key.keyvalue); 245 1.1 elric append_string(context, sp, ":"); 246 1.1 elric /* --- salt */ 247 1.1 elric if(ent->keys.val[i].salt){ 248 1.1 elric append_string(context, sp, "%u/", ent->keys.val[i].salt->type); 249 1.2 christos append_hex(context, sp, 0, 0, &ent->keys.val[i].salt->salt); 250 1.1 elric }else 251 1.1 elric append_string(context, sp, "-"); 252 1.1 elric } 253 1.1 elric append_string(context, sp, " "); 254 1.1 elric /* --- created by */ 255 1.1 elric append_event(context, sp, &ent->created_by); 256 1.1 elric /* --- modified by */ 257 1.1 elric append_event(context, sp, ent->modified_by); 258 1.1 elric 259 1.1 elric /* --- valid start */ 260 1.1 elric if(ent->valid_start) 261 1.1 elric append_string(context, sp, "%s ", time2str(*ent->valid_start)); 262 1.1 elric else 263 1.1 elric append_string(context, sp, "- "); 264 1.1 elric 265 1.1 elric /* --- valid end */ 266 1.1 elric if(ent->valid_end) 267 1.1 elric append_string(context, sp, "%s ", time2str(*ent->valid_end)); 268 1.1 elric else 269 1.1 elric append_string(context, sp, "- "); 270 1.1 elric 271 1.1 elric /* --- password ends */ 272 1.1 elric if(ent->pw_end) 273 1.1 elric append_string(context, sp, "%s ", time2str(*ent->pw_end)); 274 1.1 elric else 275 1.1 elric append_string(context, sp, "- "); 276 1.1 elric 277 1.1 elric /* --- max life */ 278 1.1 elric if(ent->max_life) 279 1.1 elric append_string(context, sp, "%d ", *ent->max_life); 280 1.1 elric else 281 1.1 elric append_string(context, sp, "- "); 282 1.1 elric 283 1.1 elric /* --- max renewable life */ 284 1.1 elric if(ent->max_renew) 285 1.1 elric append_string(context, sp, "%d ", *ent->max_renew); 286 1.1 elric else 287 1.1 elric append_string(context, sp, "- "); 288 1.1 elric 289 1.1 elric /* --- flags */ 290 1.1 elric append_string(context, sp, "%d ", HDBFlags2int(ent->flags)); 291 1.1 elric 292 1.1 elric /* --- generation number */ 293 1.1 elric if(ent->generation) { 294 1.1 elric append_string(context, sp, "%s:%d:%d ", time2str(ent->generation->time), 295 1.1 elric ent->generation->usec, 296 1.1 elric ent->generation->gen); 297 1.1 elric } else 298 1.1 elric append_string(context, sp, "- "); 299 1.1 elric 300 1.1 elric /* --- extensions */ 301 1.1 elric if(ent->extensions && ent->extensions->len > 0) { 302 1.1 elric for(i = 0; i < ent->extensions->len; i++) { 303 1.1 elric void *d; 304 1.2 christos size_t size, sz = 0; 305 1.1 elric 306 1.1 elric ASN1_MALLOC_ENCODE(HDB_extension, d, size, 307 1.1 elric &ent->extensions->val[i], &sz, ret); 308 1.1 elric if (ret) { 309 1.1 elric krb5_clear_error_message(context); 310 1.1 elric return ret; 311 1.1 elric } 312 1.1 elric if(size != sz) 313 1.1 elric krb5_abortx(context, "internal asn.1 encoder error"); 314 1.1 elric 315 1.1 elric if (hex_encode(d, size, &p) < 0) { 316 1.1 elric free(d); 317 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 318 1.1 elric return ENOMEM; 319 1.1 elric } 320 1.1 elric 321 1.1 elric free(d); 322 1.1 elric append_string(context, sp, "%s%s", p, 323 1.1 elric ent->extensions->len - 1 != i ? ":" : ""); 324 1.1 elric free(p); 325 1.1 elric } 326 1.1 elric } else 327 1.1 elric append_string(context, sp, "-"); 328 1.1 elric 329 1.2 christos return 0; 330 1.2 christos } 331 1.2 christos 332 1.2 christos #define KRB5_KDB_DISALLOW_POSTDATED 0x00000001 333 1.2 christos #define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002 334 1.2 christos #define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004 335 1.2 christos #define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008 336 1.2 christos #define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010 337 1.2 christos #define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020 338 1.2 christos #define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040 339 1.2 christos #define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080 340 1.2 christos #define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100 341 1.2 christos #define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200 342 1.2 christos #define KRB5_KDB_DISALLOW_SVR 0x00001000 343 1.2 christos #define KRB5_KDB_PWCHANGE_SERVICE 0x00002000 344 1.2 christos #define KRB5_KDB_SUPPORT_DESMD5 0x00004000 345 1.2 christos #define KRB5_KDB_NEW_PRINC 0x00008000 346 1.2 christos 347 1.2 christos static int 348 1.2 christos flags_to_attr(HDBFlags flags) 349 1.2 christos { 350 1.2 christos int a = 0; 351 1.2 christos 352 1.2 christos if (!flags.postdate) 353 1.2 christos a |= KRB5_KDB_DISALLOW_POSTDATED; 354 1.2 christos if (!flags.forwardable) 355 1.2 christos a |= KRB5_KDB_DISALLOW_FORWARDABLE; 356 1.2 christos if (flags.initial) 357 1.2 christos a |= KRB5_KDB_DISALLOW_TGT_BASED; 358 1.2 christos if (!flags.renewable) 359 1.2 christos a |= KRB5_KDB_DISALLOW_RENEWABLE; 360 1.2 christos if (!flags.proxiable) 361 1.2 christos a |= KRB5_KDB_DISALLOW_PROXIABLE; 362 1.2 christos if (flags.invalid) 363 1.2 christos a |= KRB5_KDB_DISALLOW_ALL_TIX; 364 1.2 christos if (flags.require_preauth) 365 1.2 christos a |= KRB5_KDB_REQUIRES_PRE_AUTH; 366 1.2 christos if (flags.require_hwauth) 367 1.2 christos a |= KRB5_KDB_REQUIRES_HW_AUTH; 368 1.2 christos if (!flags.server) 369 1.2 christos a |= KRB5_KDB_DISALLOW_SVR; 370 1.2 christos if (flags.change_pw) 371 1.2 christos a |= KRB5_KDB_PWCHANGE_SERVICE; 372 1.2 christos return a; 373 1.2 christos } 374 1.2 christos 375 1.2 christos krb5_error_code 376 1.2 christos entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent) 377 1.2 christos { 378 1.2 christos krb5_error_code ret; 379 1.2 christos ssize_t sz; 380 1.2 christos size_t i, k; 381 1.2 christos size_t num_tl_data = 0; 382 1.2 christos size_t num_key_data = 0; 383 1.2 christos char *p; 384 1.2 christos HDB_Ext_KeySet *hist_keys = NULL; 385 1.2 christos HDB_extension *extp; 386 1.2 christos time_t last_pw_chg = 0; 387 1.2 christos time_t exp = 0; 388 1.2 christos time_t pwexp = 0; 389 1.2 christos unsigned int max_life = 0; 390 1.2 christos unsigned int max_renew = 0; 391 1.2 christos 392 1.2 christos if (ent->modified_by) 393 1.2 christos num_tl_data++; 394 1.2 christos 395 1.2 christos ret = hdb_entry_get_pw_change_time(ent, &last_pw_chg); 396 1.2 christos if (ret) return ret; 397 1.2 christos if (last_pw_chg) 398 1.2 christos num_tl_data++; 399 1.2 christos 400 1.2 christos extp = hdb_find_extension(ent, choice_HDB_extension_data_hist_keys); 401 1.2 christos if (extp) 402 1.2 christos hist_keys = &extp->data.u.hist_keys; 403 1.2 christos 404 1.2 christos for (i = 0; i < ent->keys.len;i++) { 405 1.2 christos if (ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD4 || 406 1.2 christos ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD5) 407 1.2 christos continue; 408 1.2 christos num_key_data++; 409 1.2 christos } 410 1.2 christos if (hist_keys) { 411 1.2 christos for (i = 0; i < hist_keys->len; i++) { 412 1.2 christos /* 413 1.2 christos * MIT uses the highest kvno as the current kvno instead of 414 1.2 christos * tracking kvno separately, so we can't dump keysets with kvno 415 1.2 christos * higher than the entry's kvno. 416 1.2 christos */ 417 1.2 christos if (hist_keys->val[i].kvno >= ent->kvno) 418 1.2 christos continue; 419 1.2 christos for (k = 0; k < hist_keys->val[i].keys.len; k++) { 420 1.2 christos if (ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD4 || 421 1.2 christos ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD5) 422 1.2 christos continue; 423 1.2 christos num_key_data++; 424 1.2 christos } 425 1.2 christos } 426 1.2 christos } 427 1.1 elric 428 1.2 christos ret = krb5_unparse_name(context, ent->principal, &p); 429 1.2 christos if (ret) return ret; 430 1.2 christos sz = append_string(context, sp, "princ\t38\t%u\t%u\t%u\t0\t%s\t%d", 431 1.2 christos strlen(p), num_tl_data, num_key_data, p, 432 1.2 christos flags_to_attr(ent->flags)); 433 1.2 christos free(p); 434 1.2 christos if (sz == -1) return ENOMEM; 435 1.2 christos 436 1.2 christos if (ent->max_life) 437 1.2 christos max_life = *ent->max_life; 438 1.2 christos if (ent->max_renew) 439 1.2 christos max_renew = *ent->max_renew; 440 1.2 christos if (ent->valid_end) 441 1.2 christos exp = *ent->valid_end; 442 1.2 christos if (ent->pw_end) 443 1.2 christos pwexp = *ent->pw_end; 444 1.2 christos 445 1.2 christos sz = append_string(context, sp, "\t%u\t%u\t%u\t%u\t0\t0\t0", 446 1.2 christos max_life, max_renew, exp, pwexp); 447 1.2 christos if (sz == -1) return ENOMEM; 448 1.2 christos 449 1.2 christos /* Dump TL data we know: last pw chg and modified_by */ 450 1.2 christos #define mit_KRB5_TL_LAST_PWD_CHANGE 1 451 1.2 christos #define mit_KRB5_TL_MOD_PRINC 2 452 1.2 christos if (last_pw_chg) { 453 1.2 christos krb5_data d; 454 1.2 christos time_t val; 455 1.2 christos unsigned char *ptr; 456 1.2 christos 457 1.2 christos ptr = (unsigned char *)&last_pw_chg; 458 1.2 christos val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); 459 1.2 christos d.data = &val; 460 1.2 christos d.length = sizeof (last_pw_chg); 461 1.2 christos sz = append_string(context, sp, "\t%u\t%u\t", 462 1.2 christos mit_KRB5_TL_LAST_PWD_CHANGE, d.length); 463 1.2 christos if (sz == -1) return ENOMEM; 464 1.2 christos sz = append_hex(context, sp, 1, 1, &d); 465 1.2 christos if (sz == -1) return ENOMEM; 466 1.2 christos } 467 1.2 christos if (ent->modified_by) { 468 1.2 christos krb5_data d; 469 1.2 christos unsigned int val; 470 1.2 christos size_t plen; 471 1.2 christos unsigned char *ptr; 472 1.2 christos char *modby_p; 473 1.2 christos 474 1.2 christos ptr = (unsigned char *)&ent->modified_by->time; 475 1.2 christos val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); 476 1.2 christos d.data = &val; 477 1.2 christos d.length = sizeof (ent->modified_by->time); 478 1.2 christos ret = krb5_unparse_name(context, ent->modified_by->principal, &modby_p); 479 1.2 christos if (ret) return ret; 480 1.2 christos plen = strlen(modby_p); 481 1.2 christos sz = append_string(context, sp, "\t%u\t%u\t", 482 1.2 christos mit_KRB5_TL_MOD_PRINC, 483 1.2 christos d.length + plen + 1 /* NULL counted */); 484 1.2 christos if (sz == -1) return ENOMEM; 485 1.2 christos sz = append_hex(context, sp, 1, 1, &d); 486 1.2 christos if (sz == -1) { 487 1.2 christos free(modby_p); 488 1.2 christos return ENOMEM; 489 1.2 christos } 490 1.2 christos d.data = modby_p; 491 1.2 christos d.length = plen + 1; 492 1.2 christos sz = append_hex(context, sp, 1, 1, &d); 493 1.2 christos free(modby_p); 494 1.2 christos if (sz == -1) return ENOMEM; 495 1.2 christos } 496 1.2 christos /* 497 1.2 christos * Dump keys (remembering to not include any with kvno higher than 498 1.2 christos * the entry's because MIT doesn't track entry kvno separately from 499 1.2 christos * the entry's keys -- max kvno is it) 500 1.2 christos */ 501 1.2 christos for (i = 0; i < ent->keys.len; i++) { 502 1.2 christos if (ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD4 || 503 1.2 christos ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD5) 504 1.2 christos continue; 505 1.2 christos sz = append_mit_key(context, sp, ent->principal, ent->kvno, 506 1.2 christos &ent->keys.val[i]); 507 1.2 christos if (sz == -1) return ENOMEM; 508 1.2 christos } 509 1.2 christos for (i = 0; hist_keys && i < ent->kvno; i++) { 510 1.2 christos size_t m; 511 1.2 christos 512 1.2 christos /* dump historical keys */ 513 1.2 christos for (k = 0; k < hist_keys->len; k++) { 514 1.2 christos if (hist_keys->val[k].kvno != ent->kvno - i) 515 1.2 christos continue; 516 1.2 christos for (m = 0; m < hist_keys->val[k].keys.len; m++) { 517 1.2 christos if (ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD4 || 518 1.2 christos ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD5) 519 1.2 christos continue; 520 1.2 christos sz = append_mit_key(context, sp, ent->principal, 521 1.2 christos hist_keys->val[k].kvno, 522 1.2 christos &hist_keys->val[k].keys.val[m]); 523 1.2 christos if (sz == -1) return ENOMEM; 524 1.2 christos } 525 1.2 christos } 526 1.2 christos } 527 1.2 christos sz = append_string(context, sp, "\t-1;"); /* "extra data" */ 528 1.2 christos if (sz == -1) return ENOMEM; 529 1.1 elric return 0; 530 1.1 elric } 531 1.1 elric 532 1.1 elric krb5_error_code 533 1.2 christos hdb_entry2string(krb5_context context, hdb_entry *ent, char **str) 534 1.1 elric { 535 1.1 elric krb5_error_code ret; 536 1.1 elric krb5_data data; 537 1.1 elric krb5_storage *sp; 538 1.1 elric 539 1.1 elric sp = krb5_storage_emem(); 540 1.2 christos if (sp == NULL) { 541 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 542 1.1 elric return ENOMEM; 543 1.1 elric } 544 1.1 elric 545 1.1 elric ret = entry2string_int(context, sp, ent); 546 1.2 christos if (ret) { 547 1.1 elric krb5_storage_free(sp); 548 1.1 elric return ret; 549 1.1 elric } 550 1.1 elric 551 1.1 elric krb5_storage_write(sp, "\0", 1); 552 1.1 elric krb5_storage_to_data(sp, &data); 553 1.1 elric krb5_storage_free(sp); 554 1.1 elric *str = data.data; 555 1.1 elric return 0; 556 1.1 elric } 557 1.1 elric 558 1.1 elric /* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */ 559 1.1 elric 560 1.1 elric krb5_error_code 561 1.2 christos hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry, 562 1.2 christos void *data) 563 1.1 elric { 564 1.2 christos struct hdb_print_entry_arg *parg = data; 565 1.1 elric krb5_error_code ret; 566 1.1 elric krb5_storage *sp; 567 1.1 elric 568 1.2 christos fflush(parg->out); 569 1.2 christos sp = krb5_storage_from_fd(fileno(parg->out)); 570 1.2 christos if (sp == NULL) { 571 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 572 1.1 elric return ENOMEM; 573 1.1 elric } 574 1.1 elric 575 1.2 christos switch (parg->fmt) { 576 1.2 christos case HDB_DUMP_HEIMDAL: 577 1.2 christos ret = entry2string_int(context, sp, &entry->entry); 578 1.2 christos break; 579 1.2 christos case HDB_DUMP_MIT: 580 1.2 christos ret = entry2mit_string_int(context, sp, &entry->entry); 581 1.2 christos break; 582 1.2 christos default: 583 1.2 christos heim_abort("Only two dump formats supported: Heimdal and MIT"); 584 1.2 christos } 585 1.2 christos if (ret) { 586 1.1 elric krb5_storage_free(sp); 587 1.1 elric return ret; 588 1.1 elric } 589 1.1 elric 590 1.1 elric krb5_storage_write(sp, "\n", 1); 591 1.1 elric krb5_storage_free(sp); 592 1.1 elric return 0; 593 1.1 elric } 594