1 /* 2 * Copyright (c) 1997 - 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 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. 20 * 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 31 * SUCH DAMAGE. 32 */ 33 34 #include "hprop.h" 35 36 RCSID("$Id: hprop.c 21745 2007-07-31 16:11:25Z lha $"); 37 38 static int version_flag; 39 static int help_flag; 40 static const char *ktname = HPROP_KEYTAB; 41 static const char *database; 42 static char *mkeyfile; 43 static int to_stdout; 44 static int verbose_flag; 45 static int encrypt_flag; 46 static int decrypt_flag; 47 static hdb_master_key mkey5; 48 49 static char *source_type; 50 51 static char *afs_cell; 52 static char *v4_realm; 53 54 static int kaspecials_flag; 55 static int ka_use_null_salt; 56 57 static char *local_realm=NULL; 58 59 static int 60 open_socket(krb5_context context, const char *hostname, const char *port) 61 { 62 struct addrinfo *ai, *a; 63 struct addrinfo hints; 64 int error; 65 66 memset (&hints, 0, sizeof(hints)); 67 hints.ai_socktype = SOCK_STREAM; 68 hints.ai_protocol = IPPROTO_TCP; 69 70 error = getaddrinfo (hostname, port, &hints, &ai); 71 if (error) { 72 warnx ("%s: %s", hostname, gai_strerror(error)); 73 return -1; 74 } 75 76 for (a = ai; a != NULL; a = a->ai_next) { 77 int s; 78 79 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 80 if (s < 0) 81 continue; 82 if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { 83 warn ("connect(%s)", hostname); 84 close (s); 85 continue; 86 } 87 freeaddrinfo (ai); 88 return s; 89 } 90 warnx ("failed to contact %s", hostname); 91 freeaddrinfo (ai); 92 return -1; 93 } 94 95 krb5_error_code 96 v5_prop(krb5_context context, HDB *db, hdb_entry_ex *entry, void *appdata) 97 { 98 krb5_error_code ret; 99 struct prop_data *pd = appdata; 100 krb5_data data; 101 102 if(encrypt_flag) { 103 ret = hdb_seal_keys_mkey(context, &entry->entry, mkey5); 104 if (ret) { 105 krb5_warn(context, ret, "hdb_seal_keys_mkey"); 106 return ret; 107 } 108 } 109 if(decrypt_flag) { 110 ret = hdb_unseal_keys_mkey(context, &entry->entry, mkey5); 111 if (ret) { 112 krb5_warn(context, ret, "hdb_unseal_keys_mkey"); 113 return ret; 114 } 115 } 116 117 ret = hdb_entry2value(context, &entry->entry, &data); 118 if(ret) { 119 krb5_warn(context, ret, "hdb_entry2value"); 120 return ret; 121 } 122 123 if(to_stdout) 124 ret = krb5_write_message(context, &pd->sock, &data); 125 else 126 ret = krb5_write_priv_message(context, pd->auth_context, 127 &pd->sock, &data); 128 krb5_data_free(&data); 129 return ret; 130 } 131 132 int 133 v4_prop(void *arg, struct v4_principal *p) 134 { 135 struct prop_data *pd = arg; 136 hdb_entry_ex ent; 137 krb5_error_code ret; 138 139 memset(&ent, 0, sizeof(ent)); 140 141 ret = krb5_425_conv_principal(pd->context, p->name, p->instance, v4_realm, 142 &ent.entry.principal); 143 if(ret) { 144 krb5_warn(pd->context, ret, 145 "krb5_425_conv_principal %s.%s@%s", 146 p->name, p->instance, v4_realm); 147 return 0; 148 } 149 150 if(verbose_flag) { 151 char *s; 152 krb5_unparse_name_short(pd->context, ent.entry.principal, &s); 153 krb5_warnx(pd->context, "%s.%s -> %s", p->name, p->instance, s); 154 free(s); 155 } 156 157 ent.entry.kvno = p->kvno; 158 ent.entry.keys.len = 3; 159 ent.entry.keys.val = malloc(ent.entry.keys.len * sizeof(*ent.entry.keys.val)); 160 if (ent.entry.keys.val == NULL) 161 krb5_errx(pd->context, ENOMEM, "malloc"); 162 if(p->mkvno != -1) { 163 ent.entry.keys.val[0].mkvno = malloc (sizeof(*ent.entry.keys.val[0].mkvno)); 164 if (ent.entry.keys.val[0].mkvno == NULL) 165 krb5_errx(pd->context, ENOMEM, "malloc"); 166 *(ent.entry.keys.val[0].mkvno) = p->mkvno; 167 } else 168 ent.entry.keys.val[0].mkvno = NULL; 169 ent.entry.keys.val[0].salt = calloc(1, sizeof(*ent.entry.keys.val[0].salt)); 170 if (ent.entry.keys.val[0].salt == NULL) 171 krb5_errx(pd->context, ENOMEM, "calloc"); 172 ent.entry.keys.val[0].salt->type = KRB5_PADATA_PW_SALT; 173 ent.entry.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5; 174 krb5_data_alloc(&ent.entry.keys.val[0].key.keyvalue, DES_KEY_SZ); 175 memcpy(ent.entry.keys.val[0].key.keyvalue.data, p->key, 8); 176 177 copy_Key(&ent.entry.keys.val[0], &ent.entry.keys.val[1]); 178 ent.entry.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4; 179 copy_Key(&ent.entry.keys.val[0], &ent.entry.keys.val[2]); 180 ent.entry.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC; 181 182 { 183 int life = _krb5_krb_life_to_time(0, p->max_life); 184 if(life == NEVERDATE){ 185 ent.entry.max_life = NULL; 186 } else { 187 /* clean up lifetime a bit */ 188 if(life > 86400) 189 life = (life + 86399) / 86400 * 86400; 190 else if(life > 3600) 191 life = (life + 3599) / 3600 * 3600; 192 ALLOC(ent.entry.max_life); 193 *ent.entry.max_life = life; 194 } 195 } 196 197 ALLOC(ent.entry.valid_end); 198 *ent.entry.valid_end = p->exp_date; 199 200 ret = krb5_make_principal(pd->context, &ent.entry.created_by.principal, 201 v4_realm, 202 "kadmin", 203 "hprop", 204 NULL); 205 if(ret){ 206 krb5_warn(pd->context, ret, "krb5_make_principal"); 207 ret = 0; 208 goto out; 209 } 210 ent.entry.created_by.time = time(NULL); 211 ALLOC(ent.entry.modified_by); 212 ret = krb5_425_conv_principal(pd->context, p->mod_name, p->mod_instance, 213 v4_realm, &ent.entry.modified_by->principal); 214 if(ret){ 215 krb5_warn(pd->context, ret, "%s.%s@%s", p->name, p->instance, v4_realm); 216 ent.entry.modified_by->principal = NULL; 217 ret = 0; 218 goto out; 219 } 220 ent.entry.modified_by->time = p->mod_date; 221 222 ent.entry.flags.forwardable = 1; 223 ent.entry.flags.renewable = 1; 224 ent.entry.flags.proxiable = 1; 225 ent.entry.flags.postdate = 1; 226 ent.entry.flags.client = 1; 227 ent.entry.flags.server = 1; 228 229 /* special case password changing service */ 230 if(strcmp(p->name, "changepw") == 0 && 231 strcmp(p->instance, "kerberos") == 0) { 232 ent.entry.flags.forwardable = 0; 233 ent.entry.flags.renewable = 0; 234 ent.entry.flags.proxiable = 0; 235 ent.entry.flags.postdate = 0; 236 ent.entry.flags.initial = 1; 237 ent.entry.flags.change_pw = 1; 238 } 239 240 ret = v5_prop(pd->context, NULL, &ent, pd); 241 242 if (strcmp (p->name, "krbtgt") == 0 243 && strcmp (v4_realm, p->instance) != 0) { 244 krb5_free_principal (pd->context, ent.entry.principal); 245 ret = krb5_425_conv_principal (pd->context, p->name, 246 v4_realm, p->instance, 247 &ent.entry.principal); 248 if (ret == 0) 249 ret = v5_prop (pd->context, NULL, &ent, pd); 250 } 251 252 out: 253 hdb_free_entry(pd->context, &ent); 254 return ret; 255 } 256 257 #include "kadb.h" 258 259 /* read a `ka_entry' from `fd' at offset `pos' */ 260 static void 261 read_block(krb5_context context, int fd, int32_t pos, void *buf, size_t len) 262 { 263 krb5_error_code ret; 264 #ifdef HAVE_PREAD 265 if((ret = pread(fd, buf, len, 64 + pos)) < 0) 266 krb5_err(context, 1, errno, "pread(%u)", 64 + pos); 267 #else 268 if(lseek(fd, 64 + pos, SEEK_SET) == (off_t)-1) 269 krb5_err(context, 1, errno, "lseek(%u)", 64 + pos); 270 ret = read(fd, buf, len); 271 if(ret < 0) 272 krb5_err(context, 1, errno, "read(%lu)", (unsigned long)len); 273 #endif 274 if(ret != len) 275 krb5_errx(context, 1, "read(%lu) = %u", (unsigned long)len, ret); 276 } 277 278 static int 279 ka_convert(struct prop_data *pd, int fd, struct ka_entry *ent) 280 { 281 int32_t flags = ntohl(ent->flags); 282 krb5_error_code ret; 283 hdb_entry_ex hdb; 284 285 if(!kaspecials_flag 286 && (flags & KAFNORMAL) == 0) /* remove special entries */ 287 return 0; 288 memset(&hdb, 0, sizeof(hdb)); 289 ret = krb5_425_conv_principal(pd->context, ent->name, ent->instance, 290 v4_realm, &hdb.entry.principal); 291 if(ret) { 292 krb5_warn(pd->context, ret, 293 "krb5_425_conv_principal (%s.%s@%s)", 294 ent->name, ent->instance, v4_realm); 295 return 0; 296 } 297 hdb.entry.kvno = ntohl(ent->kvno); 298 hdb.entry.keys.len = 3; 299 hdb.entry.keys.val = 300 malloc(hdb.entry.keys.len * sizeof(*hdb.entry.keys.val)); 301 if (hdb.entry.keys.val == NULL) 302 krb5_errx(pd->context, ENOMEM, "malloc"); 303 hdb.entry.keys.val[0].mkvno = NULL; 304 hdb.entry.keys.val[0].salt = calloc(1, sizeof(*hdb.entry.keys.val[0].salt)); 305 if (hdb.entry.keys.val[0].salt == NULL) 306 krb5_errx(pd->context, ENOMEM, "calloc"); 307 if (ka_use_null_salt) { 308 hdb.entry.keys.val[0].salt->type = hdb_pw_salt; 309 hdb.entry.keys.val[0].salt->salt.data = NULL; 310 hdb.entry.keys.val[0].salt->salt.length = 0; 311 } else { 312 hdb.entry.keys.val[0].salt->type = hdb_afs3_salt; 313 hdb.entry.keys.val[0].salt->salt.data = strdup(afs_cell); 314 if (hdb.entry.keys.val[0].salt->salt.data == NULL) 315 krb5_errx(pd->context, ENOMEM, "strdup"); 316 hdb.entry.keys.val[0].salt->salt.length = strlen(afs_cell); 317 } 318 319 hdb.entry.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5; 320 krb5_data_copy(&hdb.entry.keys.val[0].key.keyvalue, 321 ent->key, 322 sizeof(ent->key)); 323 copy_Key(&hdb.entry.keys.val[0], &hdb.entry.keys.val[1]); 324 hdb.entry.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4; 325 copy_Key(&hdb.entry.keys.val[0], &hdb.entry.keys.val[2]); 326 hdb.entry.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC; 327 328 ALLOC(hdb.entry.max_life); 329 *hdb.entry.max_life = ntohl(ent->max_life); 330 331 if(ntohl(ent->valid_end) != NEVERDATE && ntohl(ent->valid_end) != 0xffffffff) { 332 ALLOC(hdb.entry.valid_end); 333 *hdb.entry.valid_end = ntohl(ent->valid_end); 334 } 335 336 if (ntohl(ent->pw_change) != NEVERDATE && 337 ent->pw_expire != 255 && 338 ent->pw_expire != 0) { 339 ALLOC(hdb.entry.pw_end); 340 *hdb.entry.pw_end = ntohl(ent->pw_change) 341 + 24 * 60 * 60 * ent->pw_expire; 342 } 343 344 ret = krb5_make_principal(pd->context, &hdb.entry.created_by.principal, 345 v4_realm, 346 "kadmin", 347 "hprop", 348 NULL); 349 hdb.entry.created_by.time = time(NULL); 350 351 if(ent->mod_ptr){ 352 struct ka_entry mod; 353 ALLOC(hdb.entry.modified_by); 354 read_block(pd->context, fd, ntohl(ent->mod_ptr), &mod, sizeof(mod)); 355 356 krb5_425_conv_principal(pd->context, mod.name, mod.instance, v4_realm, 357 &hdb.entry.modified_by->principal); 358 hdb.entry.modified_by->time = ntohl(ent->mod_time); 359 memset(&mod, 0, sizeof(mod)); 360 } 361 362 hdb.entry.flags.forwardable = 1; 363 hdb.entry.flags.renewable = 1; 364 hdb.entry.flags.proxiable = 1; 365 hdb.entry.flags.postdate = 1; 366 /* XXX - AFS 3.4a creates krbtgt.REALMOFCELL as NOTGS+NOSEAL */ 367 if (strcmp(ent->name, "krbtgt") == 0 && 368 (flags & (KAFNOTGS|KAFNOSEAL)) == (KAFNOTGS|KAFNOSEAL)) 369 flags &= ~(KAFNOTGS|KAFNOSEAL); 370 371 hdb.entry.flags.client = (flags & KAFNOTGS) == 0; 372 hdb.entry.flags.server = (flags & KAFNOSEAL) == 0; 373 374 ret = v5_prop(pd->context, NULL, &hdb, pd); 375 hdb_free_entry(pd->context, &hdb); 376 return ret; 377 } 378 379 static int 380 ka_dump(struct prop_data *pd, const char *file) 381 { 382 struct ka_header header; 383 int i; 384 int fd = open(file, O_RDONLY); 385 386 if(fd < 0) 387 krb5_err(pd->context, 1, errno, "open(%s)", file); 388 read_block(pd->context, fd, 0, &header, sizeof(header)); 389 if(header.version1 != header.version2) 390 krb5_errx(pd->context, 1, "Version mismatch in header: %ld/%ld", 391 (long)ntohl(header.version1), (long)ntohl(header.version2)); 392 if(ntohl(header.version1) != 5) 393 krb5_errx(pd->context, 1, "Unknown database version %ld (expected 5)", 394 (long)ntohl(header.version1)); 395 for(i = 0; i < ntohl(header.hashsize); i++){ 396 int32_t pos = ntohl(header.hash[i]); 397 while(pos){ 398 struct ka_entry ent; 399 read_block(pd->context, fd, pos, &ent, sizeof(ent)); 400 ka_convert(pd, fd, &ent); 401 pos = ntohl(ent.next); 402 } 403 } 404 return 0; 405 } 406 407 408 409 struct getargs args[] = { 410 { "master-key", 'm', arg_string, &mkeyfile, "v5 master key file", "file" }, 411 { "database", 'd', arg_string, &database, "database", "file" }, 412 { "source", 0, arg_string, &source_type, "type of database to read", 413 "heimdal" 414 "|mit-dump" 415 "|krb4-dump" 416 "|kaserver" 417 }, 418 419 { "v4-realm", 'r', arg_string, &v4_realm, "v4 realm to use" }, 420 { "cell", 'c', arg_string, &afs_cell, "name of AFS cell" }, 421 { "kaspecials", 'S', arg_flag, &kaspecials_flag, "dump KASPECIAL keys"}, 422 { "keytab", 'k', arg_string, &ktname, "keytab to use for authentication", "keytab" }, 423 { "v5-realm", 'R', arg_string, &local_realm, "v5 realm to use" }, 424 { "decrypt", 'D', arg_flag, &decrypt_flag, "decrypt keys" }, 425 { "encrypt", 'E', arg_flag, &encrypt_flag, "encrypt keys" }, 426 { "stdout", 'n', arg_flag, &to_stdout, "dump to stdout" }, 427 { "verbose", 'v', arg_flag, &verbose_flag }, 428 { "version", 0, arg_flag, &version_flag }, 429 { "help", 'h', arg_flag, &help_flag } 430 }; 431 432 static int num_args = sizeof(args) / sizeof(args[0]); 433 434 static void 435 usage(int ret) 436 { 437 arg_printusage (args, num_args, NULL, "[host[:port]] ..."); 438 exit (ret); 439 } 440 441 static void 442 get_creds(krb5_context context, krb5_ccache *cache) 443 { 444 krb5_keytab keytab; 445 krb5_principal client; 446 krb5_error_code ret; 447 krb5_get_init_creds_opt *init_opts; 448 krb5_preauthtype preauth = KRB5_PADATA_ENC_TIMESTAMP; 449 krb5_creds creds; 450 451 ret = krb5_kt_register(context, &hdb_kt_ops); 452 if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); 453 454 ret = krb5_kt_resolve(context, ktname, &keytab); 455 if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve"); 456 457 ret = krb5_make_principal(context, &client, NULL, 458 "kadmin", HPROP_NAME, NULL); 459 if(ret) krb5_err(context, 1, ret, "krb5_make_principal"); 460 461 ret = krb5_get_init_creds_opt_alloc(context, &init_opts); 462 if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); 463 krb5_get_init_creds_opt_set_preauth_list(init_opts, &preauth, 1); 464 465 ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, NULL, init_opts); 466 if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds"); 467 468 krb5_get_init_creds_opt_free(context, init_opts); 469 470 ret = krb5_kt_close(context, keytab); 471 if(ret) krb5_err(context, 1, ret, "krb5_kt_close"); 472 473 ret = krb5_cc_gen_new(context, &krb5_mcc_ops, cache); 474 if(ret) krb5_err(context, 1, ret, "krb5_cc_gen_new"); 475 476 ret = krb5_cc_initialize(context, *cache, client); 477 if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); 478 479 krb5_free_principal(context, client); 480 481 ret = krb5_cc_store_cred(context, *cache, &creds); 482 if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); 483 484 krb5_free_cred_contents(context, &creds); 485 } 486 487 enum hprop_source { 488 HPROP_HEIMDAL = 1, 489 HPROP_KRB4_DUMP, 490 HPROP_KASERVER, 491 HPROP_MIT_DUMP 492 }; 493 494 #define IS_TYPE_V4(X) ((X) == HPROP_KRB4_DUMP || (X) == HPROP_KASERVER) 495 496 struct { 497 int type; 498 const char *name; 499 } types[] = { 500 { HPROP_HEIMDAL, "heimdal" }, 501 { HPROP_KRB4_DUMP, "krb4-dump" }, 502 { HPROP_KASERVER, "kaserver" }, 503 { HPROP_MIT_DUMP, "mit-dump" } 504 }; 505 506 static int 507 parse_source_type(const char *s) 508 { 509 int i; 510 for(i = 0; i < sizeof(types) / sizeof(types[0]); i++) { 511 if(strstr(types[i].name, s) == types[i].name) 512 return types[i].type; 513 } 514 return 0; 515 } 516 517 static int 518 iterate (krb5_context context, 519 const char *database_name, 520 HDB *db, 521 int type, 522 struct prop_data *pd) 523 { 524 int ret; 525 526 switch(type) { 527 case HPROP_KRB4_DUMP: 528 ret = v4_prop_dump(pd, database_name); 529 if(ret) 530 krb5_warnx(context, "v4_prop_dump: %s", 531 krb5_get_err_text(context, ret)); 532 break; 533 case HPROP_KASERVER: 534 ret = ka_dump(pd, database_name); 535 if(ret) 536 krb5_warn(context, ret, "ka_dump"); 537 break; 538 case HPROP_MIT_DUMP: 539 ret = mit_prop_dump(pd, database_name); 540 if (ret) 541 krb5_warnx(context, "mit_prop_dump: %s", 542 krb5_get_err_text(context, ret)); 543 break; 544 case HPROP_HEIMDAL: 545 ret = hdb_foreach(context, db, HDB_F_DECRYPT, v5_prop, pd); 546 if(ret) 547 krb5_warn(context, ret, "hdb_foreach"); 548 break; 549 default: 550 krb5_errx(context, 1, "unknown prop type: %d", type); 551 } 552 return ret; 553 } 554 555 static int 556 dump_database (krb5_context context, int type, 557 const char *database_name, HDB *db) 558 { 559 krb5_error_code ret; 560 struct prop_data pd; 561 krb5_data data; 562 563 pd.context = context; 564 pd.auth_context = NULL; 565 pd.sock = STDOUT_FILENO; 566 567 ret = iterate (context, database_name, db, type, &pd); 568 if (ret) 569 krb5_errx(context, 1, "iterate failure"); 570 krb5_data_zero (&data); 571 ret = krb5_write_message (context, &pd.sock, &data); 572 if (ret) 573 krb5_err(context, 1, ret, "krb5_write_message"); 574 575 return 0; 576 } 577 578 static int 579 propagate_database (krb5_context context, int type, 580 const char *database_name, 581 HDB *db, krb5_ccache ccache, 582 int optidx, int argc, char **argv) 583 { 584 krb5_principal server; 585 krb5_error_code ret; 586 int i, failed = 0; 587 588 for(i = optidx; i < argc; i++){ 589 krb5_auth_context auth_context; 590 int fd; 591 struct prop_data pd; 592 krb5_data data; 593 594 char *port, portstr[NI_MAXSERV]; 595 char *host = argv[i]; 596 597 port = strchr(host, ':'); 598 if(port == NULL) { 599 snprintf(portstr, sizeof(portstr), "%u", 600 ntohs(krb5_getportbyname (context, "hprop", "tcp", 601 HPROP_PORT))); 602 port = portstr; 603 } else 604 *port++ = '\0'; 605 606 fd = open_socket(context, host, port); 607 if(fd < 0) { 608 failed++; 609 krb5_warn (context, errno, "connect %s", host); 610 continue; 611 } 612 613 ret = krb5_sname_to_principal(context, argv[i], 614 HPROP_NAME, KRB5_NT_SRV_HST, &server); 615 if(ret) { 616 failed++; 617 krb5_warn(context, ret, "krb5_sname_to_principal(%s)", host); 618 close(fd); 619 continue; 620 } 621 622 if (local_realm) { 623 krb5_realm my_realm; 624 krb5_get_default_realm(context,&my_realm); 625 626 free (*krb5_princ_realm(context, server)); 627 krb5_princ_set_realm(context,server,&my_realm); 628 } 629 630 auth_context = NULL; 631 ret = krb5_sendauth(context, 632 &auth_context, 633 &fd, 634 HPROP_VERSION, 635 NULL, 636 server, 637 AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY, 638 NULL, /* in_data */ 639 NULL, /* in_creds */ 640 ccache, 641 NULL, 642 NULL, 643 NULL); 644 645 krb5_free_principal(context, server); 646 647 if(ret) { 648 failed++; 649 krb5_warn(context, ret, "krb5_sendauth (%s)", host); 650 close(fd); 651 goto next_host; 652 } 653 654 pd.context = context; 655 pd.auth_context = auth_context; 656 pd.sock = fd; 657 658 ret = iterate (context, database_name, db, type, &pd); 659 if (ret) { 660 krb5_warnx(context, "iterate to host %s failed", host); 661 failed++; 662 goto next_host; 663 } 664 665 krb5_data_zero (&data); 666 ret = krb5_write_priv_message(context, auth_context, &fd, &data); 667 if(ret) { 668 krb5_warn(context, ret, "krb5_write_priv_message"); 669 failed++; 670 goto next_host; 671 } 672 673 ret = krb5_read_priv_message(context, auth_context, &fd, &data); 674 if(ret) { 675 krb5_warn(context, ret, "krb5_read_priv_message: %s", host); 676 failed++; 677 goto next_host; 678 } else 679 krb5_data_free (&data); 680 681 next_host: 682 krb5_auth_con_free(context, auth_context); 683 close(fd); 684 } 685 if (failed) 686 return 1; 687 return 0; 688 } 689 690 int 691 main(int argc, char **argv) 692 { 693 krb5_error_code ret; 694 krb5_context context; 695 krb5_ccache ccache = NULL; 696 HDB *db = NULL; 697 int optidx = 0; 698 699 int type, exit_code; 700 701 setprogname(argv[0]); 702 703 if(getarg(args, num_args, argc, argv, &optidx)) 704 usage(1); 705 706 if(help_flag) 707 usage(0); 708 709 if(version_flag){ 710 print_version(NULL); 711 exit(0); 712 } 713 714 ret = krb5_init_context(&context); 715 if(ret) 716 exit(1); 717 718 if(local_realm) 719 krb5_set_default_realm(context, local_realm); 720 721 if(v4_realm == NULL) { 722 ret = krb5_get_default_realm(context, &v4_realm); 723 if(ret) 724 krb5_err(context, 1, ret, "krb5_get_default_realm"); 725 } 726 727 if(afs_cell == NULL) { 728 afs_cell = strdup(v4_realm); 729 if(afs_cell == NULL) 730 krb5_errx(context, 1, "out of memory"); 731 strlwr(afs_cell); 732 } 733 734 735 if(encrypt_flag && decrypt_flag) 736 krb5_errx(context, 1, 737 "only one of `--encrypt' and `--decrypt' is meaningful"); 738 739 if(source_type != NULL) { 740 type = parse_source_type(source_type); 741 if(type == 0) 742 krb5_errx(context, 1, "unknown source type `%s'", source_type); 743 } else 744 type = HPROP_HEIMDAL; 745 746 if(!to_stdout) 747 get_creds(context, &ccache); 748 749 if(decrypt_flag || encrypt_flag) { 750 ret = hdb_read_master_key(context, mkeyfile, &mkey5); 751 if(ret && ret != ENOENT) 752 krb5_err(context, 1, ret, "hdb_read_master_key"); 753 if(ret) 754 krb5_errx(context, 1, "No master key file found"); 755 } 756 757 if (IS_TYPE_V4(type) && v4_realm == NULL) 758 krb5_errx(context, 1, "Its a Kerberos 4 database " 759 "but no realm configured"); 760 761 switch(type) { 762 case HPROP_KASERVER: 763 if (database == NULL) 764 database = DEFAULT_DATABASE; 765 ka_use_null_salt = krb5_config_get_bool_default(context, NULL, FALSE, 766 "hprop", 767 "afs_uses_null_salt", 768 NULL); 769 770 break; 771 case HPROP_KRB4_DUMP: 772 if (database == NULL) 773 krb5_errx(context, 1, "no dump file specified"); 774 775 break; 776 case HPROP_MIT_DUMP: 777 if (database == NULL) 778 krb5_errx(context, 1, "no dump file specified"); 779 break; 780 case HPROP_HEIMDAL: 781 ret = hdb_create (context, &db, database); 782 if(ret) 783 krb5_err(context, 1, ret, "hdb_create: %s", database); 784 ret = db->hdb_open(context, db, O_RDONLY, 0); 785 if(ret) 786 krb5_err(context, 1, ret, "db->hdb_open"); 787 break; 788 default: 789 krb5_errx(context, 1, "unknown dump type `%d'", type); 790 break; 791 } 792 793 if (to_stdout) 794 exit_code = dump_database (context, type, database, db); 795 else 796 exit_code = propagate_database (context, type, database, 797 db, ccache, optidx, argc, argv); 798 799 if(ccache != NULL) 800 krb5_cc_destroy(context, ccache); 801 802 if(db != NULL) 803 (*db->hdb_destroy)(context, db); 804 805 krb5_free_context(context); 806 return exit_code; 807 } 808