MFC:
[dragonfly.git] / crypto / heimdal-0.6.3 / kdc / hprop.c
blob3bc066fe19716d91fca0795c4842c0c47ad1090c
1 /*
2 * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #include "hprop.h"
36 RCSID("$Id: hprop.c,v 1.70 2002/09/04 18:19:41 joda Exp $");
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;
49 static char *source_type;
51 static char *afs_cell;
52 static char *v4_realm;
54 static int kaspecials_flag;
55 static int ka_use_null_salt;
57 static char *local_realm=NULL;
59 static int
60 open_socket(krb5_context context, const char *hostname, const char *port)
62 struct addrinfo *ai, *a;
63 struct addrinfo hints;
64 int error;
66 memset (&hints, 0, sizeof(hints));
67 hints.ai_socktype = SOCK_STREAM;
68 hints.ai_protocol = IPPROTO_TCP;
70 error = getaddrinfo (hostname, port, &hints, &ai);
71 if (error) {
72 warnx ("%s: %s", hostname, gai_strerror(error));
73 return -1;
76 for (a = ai; a != NULL; a = a->ai_next) {
77 int s;
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;
87 freeaddrinfo (ai);
88 return s;
90 warnx ("failed to contact %s", hostname);
91 freeaddrinfo (ai);
92 return -1;
95 krb5_error_code
96 v5_prop(krb5_context context, HDB *db, hdb_entry *entry, void *appdata)
98 krb5_error_code ret;
99 struct prop_data *pd = appdata;
100 krb5_data data;
102 if(encrypt_flag) {
103 ret = hdb_seal_keys_mkey(context, entry, mkey5);
104 if (ret) {
105 krb5_warn(context, ret, "hdb_seal_keys_mkey");
106 return ret;
109 if(decrypt_flag) {
110 ret = hdb_unseal_keys_mkey(context, entry, mkey5);
111 if (ret) {
112 krb5_warn(context, ret, "hdb_unseal_keys_mkey");
113 return ret;
117 ret = hdb_entry2value(context, entry, &data);
118 if(ret) {
119 krb5_warn(context, ret, "hdb_entry2value");
120 return ret;
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;
132 #ifdef KRB4
134 static char realm_buf[REALM_SZ];
136 static int
137 kdb_prop(void *arg, Principal *p)
139 int ret;
140 struct v4_principal pr;
142 memset(&pr, 0, sizeof(pr));
144 if(p->attributes != 0) {
145 warnx("%s.%s has non-zero attributes - skipping",
146 p->name, p->instance);
147 return 0;
149 strlcpy(pr.name, p->name, sizeof(pr.name));
150 strlcpy(pr.instance, p->instance, sizeof(pr.instance));
152 copy_to_key(&p->key_low, &p->key_high, pr.key);
153 pr.exp_date = p->exp_date;
154 pr.mod_date = p->mod_date;
155 strlcpy(pr.mod_name, p->mod_name, sizeof(pr.mod_name));
156 strlcpy(pr.mod_instance, p->mod_instance, sizeof(pr.mod_instance));
157 pr.max_life = p->max_life;
158 pr.mkvno = p->kdc_key_ver;
159 pr.kvno = p->key_version;
161 ret = v4_prop(arg, &pr);
162 memset(&pr, 0, sizeof(pr));
163 return ret;
166 #endif /* KRB4 */
168 #ifndef KRB4
169 static time_t
170 krb_life_to_time(time_t start, int life)
172 static int lifetimes[] = {
173 38400, 41055, 43894, 46929, 50174, 53643, 57352, 61318,
174 65558, 70091, 74937, 80119, 85658, 91581, 97914, 104684,
175 111922, 119661, 127935, 136781, 146239, 156350, 167161, 178720,
176 191077, 204289, 218415, 233517, 249664, 266926, 285383, 305116,
177 326213, 348769, 372885, 398668, 426234, 455705, 487215, 520904,
178 556921, 595430, 636601, 680618, 727680, 777995, 831789, 889303,
179 950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247,
180 1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000
183 #if 0
184 int i;
185 double q = exp((log(2592000.0) - log(38400.0)) / 63);
186 double x = 38400;
187 for(i = 0; i < 64; i++) {
188 lifetimes[i] = (int)x;
189 x *= q;
191 #endif
193 if(life == 0xff)
194 return NEVERDATE;
195 if(life < 0x80)
196 return start + life * 5 * 60;
197 if(life > 0xbf)
198 life = 0xbf;
199 return start + lifetimes[life - 0x80];
201 #endif /* !KRB4 */
204 v4_prop(void *arg, struct v4_principal *p)
206 struct prop_data *pd = arg;
207 hdb_entry ent;
208 krb5_error_code ret;
210 memset(&ent, 0, sizeof(ent));
212 ret = krb5_425_conv_principal(pd->context, p->name, p->instance, v4_realm,
213 &ent.principal);
214 if(ret) {
215 krb5_warn(pd->context, ret,
216 "krb5_425_conv_principal %s.%s@%s",
217 p->name, p->instance, v4_realm);
218 return 0;
221 if(verbose_flag) {
222 char *s;
223 krb5_unparse_name_short(pd->context, ent.principal, &s);
224 krb5_warnx(pd->context, "%s.%s -> %s", p->name, p->instance, s);
225 free(s);
228 ent.kvno = p->kvno;
229 ent.keys.len = 3;
230 ent.keys.val = malloc(ent.keys.len * sizeof(*ent.keys.val));
231 if(p->mkvno != -1) {
232 ent.keys.val[0].mkvno = malloc (sizeof(*ent.keys.val[0].mkvno));
233 *(ent.keys.val[0].mkvno) = p->mkvno;
234 } else
235 ent.keys.val[0].mkvno = NULL;
236 ent.keys.val[0].salt = calloc(1, sizeof(*ent.keys.val[0].salt));
237 ent.keys.val[0].salt->type = KRB5_PADATA_PW_SALT;
238 ent.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
239 krb5_data_alloc(&ent.keys.val[0].key.keyvalue, sizeof(des_cblock));
240 memcpy(ent.keys.val[0].key.keyvalue.data, p->key, 8);
242 copy_Key(&ent.keys.val[0], &ent.keys.val[1]);
243 ent.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
244 copy_Key(&ent.keys.val[0], &ent.keys.val[2]);
245 ent.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;
248 int life = krb_life_to_time(0, p->max_life);
249 if(life == NEVERDATE){
250 ent.max_life = NULL;
251 } else {
252 /* clean up lifetime a bit */
253 if(life > 86400)
254 life = (life + 86399) / 86400 * 86400;
255 else if(life > 3600)
256 life = (life + 3599) / 3600 * 3600;
257 ALLOC(ent.max_life);
258 *ent.max_life = life;
262 ALLOC(ent.valid_end);
263 *ent.valid_end = p->exp_date;
265 ret = krb5_make_principal(pd->context, &ent.created_by.principal,
266 v4_realm,
267 "kadmin",
268 "hprop",
269 NULL);
270 if(ret){
271 krb5_warn(pd->context, ret, "krb5_make_principal");
272 ret = 0;
273 goto out;
275 ent.created_by.time = time(NULL);
276 ALLOC(ent.modified_by);
277 ret = krb5_425_conv_principal(pd->context, p->mod_name, p->mod_instance,
278 v4_realm, &ent.modified_by->principal);
279 if(ret){
280 krb5_warn(pd->context, ret, "%s.%s@%s", p->name, p->instance, v4_realm);
281 ent.modified_by->principal = NULL;
282 ret = 0;
283 goto out;
285 ent.modified_by->time = p->mod_date;
287 ent.flags.forwardable = 1;
288 ent.flags.renewable = 1;
289 ent.flags.proxiable = 1;
290 ent.flags.postdate = 1;
291 ent.flags.client = 1;
292 ent.flags.server = 1;
294 /* special case password changing service */
295 if(strcmp(p->name, "changepw") == 0 &&
296 strcmp(p->instance, "kerberos") == 0) {
297 ent.flags.forwardable = 0;
298 ent.flags.renewable = 0;
299 ent.flags.proxiable = 0;
300 ent.flags.postdate = 0;
301 ent.flags.initial = 1;
302 ent.flags.change_pw = 1;
305 ret = v5_prop(pd->context, NULL, &ent, pd);
307 if (strcmp (p->name, "krbtgt") == 0
308 && strcmp (v4_realm, p->instance) != 0) {
309 krb5_free_principal (pd->context, ent.principal);
310 ret = krb5_425_conv_principal (pd->context, p->name,
311 v4_realm, p->instance,
312 &ent.principal);
313 if (ret == 0)
314 ret = v5_prop (pd->context, NULL, &ent, pd);
317 out:
318 hdb_free_entry(pd->context, &ent);
319 return ret;
322 #include "kadb.h"
324 /* read a `ka_entry' from `fd' at offset `pos' */
325 static void
326 read_block(krb5_context context, int fd, int32_t pos, void *buf, size_t len)
328 krb5_error_code ret;
329 #ifdef HAVE_PREAD
330 if((ret = pread(fd, buf, len, 64 + pos)) < 0)
331 krb5_err(context, 1, errno, "pread(%u)", 64 + pos);
332 #else
333 if(lseek(fd, 64 + pos, SEEK_SET) == (off_t)-1)
334 krb5_err(context, 1, errno, "lseek(%u)", 64 + pos);
335 ret = read(fd, buf, len);
336 if(ret < 0)
337 krb5_err(context, 1, errno, "read(%lu)", (unsigned long)len);
338 #endif
339 if(ret != len)
340 krb5_errx(context, 1, "read(%lu) = %u", (unsigned long)len, ret);
343 static int
344 ka_convert(struct prop_data *pd, int fd, struct ka_entry *ent)
346 int32_t flags = ntohl(ent->flags);
347 krb5_error_code ret;
348 hdb_entry hdb;
350 if(!kaspecials_flag
351 && (flags & KAFNORMAL) == 0) /* remove special entries */
352 return 0;
353 memset(&hdb, 0, sizeof(hdb));
354 ret = krb5_425_conv_principal(pd->context, ent->name, ent->instance,
355 v4_realm, &hdb.principal);
356 if(ret) {
357 krb5_warn(pd->context, ret,
358 "krb5_425_conv_principal (%s.%s@%s)",
359 ent->name, ent->instance, v4_realm);
360 return 0;
362 hdb.kvno = ntohl(ent->kvno);
363 hdb.keys.len = 3;
364 hdb.keys.val = malloc(hdb.keys.len * sizeof(*hdb.keys.val));
365 hdb.keys.val[0].mkvno = NULL;
366 hdb.keys.val[0].salt = calloc(1, sizeof(*hdb.keys.val[0].salt));
367 if (ka_use_null_salt) {
368 hdb.keys.val[0].salt->type = hdb_pw_salt;
369 hdb.keys.val[0].salt->salt.data = NULL;
370 hdb.keys.val[0].salt->salt.length = 0;
371 } else {
372 hdb.keys.val[0].salt->type = hdb_afs3_salt;
373 hdb.keys.val[0].salt->salt.data = strdup(afs_cell);
374 hdb.keys.val[0].salt->salt.length = strlen(afs_cell);
377 hdb.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
378 krb5_data_copy(&hdb.keys.val[0].key.keyvalue, ent->key, sizeof(ent->key));
379 copy_Key(&hdb.keys.val[0], &hdb.keys.val[1]);
380 hdb.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
381 copy_Key(&hdb.keys.val[0], &hdb.keys.val[2]);
382 hdb.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;
384 ALLOC(hdb.max_life);
385 *hdb.max_life = ntohl(ent->max_life);
387 if(ntohl(ent->valid_end) != NEVERDATE && ntohl(ent->valid_end) != -1){
388 ALLOC(hdb.valid_end);
389 *hdb.valid_end = ntohl(ent->valid_end);
392 if (ntohl(ent->pw_change) != NEVERDATE &&
393 ent->pw_expire != 255 &&
394 ent->pw_expire != 0) {
395 ALLOC(hdb.pw_end);
396 *hdb.pw_end = ntohl(ent->pw_change)
397 + 24 * 60 * 60 * ent->pw_expire;
400 ret = krb5_make_principal(pd->context, &hdb.created_by.principal,
401 v4_realm,
402 "kadmin",
403 "hprop",
404 NULL);
405 hdb.created_by.time = time(NULL);
407 if(ent->mod_ptr){
408 struct ka_entry mod;
409 ALLOC(hdb.modified_by);
410 read_block(pd->context, fd, ntohl(ent->mod_ptr), &mod, sizeof(mod));
412 krb5_425_conv_principal(pd->context, mod.name, mod.instance, v4_realm,
413 &hdb.modified_by->principal);
414 hdb.modified_by->time = ntohl(ent->mod_time);
415 memset(&mod, 0, sizeof(mod));
418 hdb.flags.forwardable = 1;
419 hdb.flags.renewable = 1;
420 hdb.flags.proxiable = 1;
421 hdb.flags.postdate = 1;
422 /* XXX - AFS 3.4a creates krbtgt.REALMOFCELL as NOTGS+NOSEAL */
423 if (strcmp(ent->name, "krbtgt") == 0 &&
424 (flags & (KAFNOTGS|KAFNOSEAL)) == (KAFNOTGS|KAFNOSEAL))
425 flags &= ~(KAFNOTGS|KAFNOSEAL);
427 hdb.flags.client = (flags & KAFNOTGS) == 0;
428 hdb.flags.server = (flags & KAFNOSEAL) == 0;
430 ret = v5_prop(pd->context, NULL, &hdb, pd);
431 hdb_free_entry(pd->context, &hdb);
432 return ret;
435 static int
436 ka_dump(struct prop_data *pd, const char *file)
438 struct ka_header header;
439 int i;
440 int fd = open(file, O_RDONLY);
442 if(fd < 0)
443 krb5_err(pd->context, 1, errno, "open(%s)", file);
444 read_block(pd->context, fd, 0, &header, sizeof(header));
445 if(header.version1 != header.version2)
446 krb5_errx(pd->context, 1, "Version mismatch in header: %ld/%ld",
447 (long)ntohl(header.version1), (long)ntohl(header.version2));
448 if(ntohl(header.version1) != 5)
449 krb5_errx(pd->context, 1, "Unknown database version %ld (expected 5)",
450 (long)ntohl(header.version1));
451 for(i = 0; i < ntohl(header.hashsize); i++){
452 int32_t pos = ntohl(header.hash[i]);
453 while(pos){
454 struct ka_entry ent;
455 read_block(pd->context, fd, pos, &ent, sizeof(ent));
456 ka_convert(pd, fd, &ent);
457 pos = ntohl(ent.next);
460 return 0;
465 struct getargs args[] = {
466 { "master-key", 'm', arg_string, &mkeyfile, "v5 master key file", "file" },
467 { "database", 'd', arg_string, &database, "database", "file" },
468 { "source", 0, arg_string, &source_type, "type of database to read",
469 "heimdal"
470 "|mit-dump"
471 "|krb4-dump"
472 #ifdef KRB4
473 "|krb4-db"
474 #endif
475 "|kaserver"
478 { "v4-realm", 'r', arg_string, &v4_realm, "v4 realm to use" },
479 { "cell", 'c', arg_string, &afs_cell, "name of AFS cell" },
480 { "kaspecials", 'S', arg_flag, &kaspecials_flag, "dump KASPECIAL keys"},
481 { "keytab", 'k', arg_string, &ktname, "keytab to use for authentication", "keytab" },
482 { "v5-realm", 'R', arg_string, &local_realm, "v5 realm to use" },
483 { "decrypt", 'D', arg_flag, &decrypt_flag, "decrypt keys" },
484 { "encrypt", 'E', arg_flag, &encrypt_flag, "encrypt keys" },
485 { "stdout", 'n', arg_flag, &to_stdout, "dump to stdout" },
486 { "verbose", 'v', arg_flag, &verbose_flag },
487 { "version", 0, arg_flag, &version_flag },
488 { "help", 'h', arg_flag, &help_flag }
491 static int num_args = sizeof(args) / sizeof(args[0]);
493 static void
494 usage(int ret)
496 arg_printusage (args, num_args, NULL, "[host[:port]] ...");
497 exit (ret);
500 static void
501 get_creds(krb5_context context, krb5_ccache *cache)
503 krb5_keytab keytab;
504 krb5_principal client;
505 krb5_error_code ret;
506 krb5_get_init_creds_opt init_opts;
507 krb5_preauthtype preauth = KRB5_PADATA_ENC_TIMESTAMP;
508 krb5_creds creds;
510 ret = krb5_kt_register(context, &hdb_kt_ops);
511 if(ret) krb5_err(context, 1, ret, "krb5_kt_register");
513 ret = krb5_kt_resolve(context, ktname, &keytab);
514 if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve");
516 ret = krb5_make_principal(context, &client, NULL,
517 "kadmin", HPROP_NAME, NULL);
518 if(ret) krb5_err(context, 1, ret, "krb5_make_principal");
520 krb5_get_init_creds_opt_init(&init_opts);
521 krb5_get_init_creds_opt_set_preauth_list(&init_opts, &preauth, 1);
523 ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, NULL, &init_opts);
524 if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds");
526 ret = krb5_kt_close(context, keytab);
527 if(ret) krb5_err(context, 1, ret, "krb5_kt_close");
529 ret = krb5_cc_gen_new(context, &krb5_mcc_ops, cache);
530 if(ret) krb5_err(context, 1, ret, "krb5_cc_gen_new");
532 ret = krb5_cc_initialize(context, *cache, client);
533 if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize");
535 krb5_free_principal(context, client);
537 ret = krb5_cc_store_cred(context, *cache, &creds);
538 if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred");
540 krb5_free_creds_contents(context, &creds);
543 enum hprop_source {
544 HPROP_HEIMDAL = 1,
545 HPROP_KRB4_DB,
546 HPROP_KRB4_DUMP,
547 HPROP_KASERVER,
548 HPROP_MIT_DUMP
551 #define IS_TYPE_V4(X) ((X) == HPROP_KRB4_DB || (X) == HPROP_KRB4_DUMP || (X) == HPROP_KASERVER)
553 struct {
554 int type;
555 const char *name;
556 } types[] = {
557 { HPROP_HEIMDAL, "heimdal" },
558 { HPROP_KRB4_DUMP, "krb4-dump" },
559 #ifdef KRB4
560 { HPROP_KRB4_DB, "krb4-db" },
561 #endif
562 { HPROP_KASERVER, "kaserver" },
563 { HPROP_MIT_DUMP, "mit-dump" }
566 static int
567 parse_source_type(const char *s)
569 int i;
570 for(i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
571 if(strstr(types[i].name, s) == types[i].name)
572 return types[i].type;
574 return 0;
577 static void
578 iterate (krb5_context context,
579 const char *database,
580 HDB *db,
581 int type,
582 struct prop_data *pd)
584 int ret;
586 switch(type) {
587 case HPROP_KRB4_DUMP:
588 ret = v4_prop_dump(pd, database);
589 break;
590 #ifdef KRB4
591 case HPROP_KRB4_DB:
592 ret = kerb_db_iterate ((k_iter_proc_t)kdb_prop, pd);
593 if(ret)
594 krb5_errx(context, 1, "kerb_db_iterate: %s",
595 krb_get_err_text(ret));
596 break;
597 #endif /* KRB4 */
598 case HPROP_KASERVER:
599 ret = ka_dump(pd, database);
600 if(ret)
601 krb5_err(context, 1, ret, "ka_dump");
602 break;
603 case HPROP_MIT_DUMP:
604 ret = mit_prop_dump(pd, database);
605 if (ret)
606 krb5_errx(context, 1, "mit_prop_dump: %s",
607 krb5_get_err_text(context, ret));
608 break;
609 case HPROP_HEIMDAL:
610 ret = hdb_foreach(context, db, HDB_F_DECRYPT, v5_prop, pd);
611 if(ret)
612 krb5_err(context, 1, ret, "hdb_foreach");
613 break;
617 static int
618 dump_database (krb5_context context, int type,
619 const char *database, HDB *db)
621 krb5_error_code ret;
622 struct prop_data pd;
623 krb5_data data;
625 pd.context = context;
626 pd.auth_context = NULL;
627 pd.sock = STDOUT_FILENO;
629 iterate (context, database, db, type, &pd);
630 krb5_data_zero (&data);
631 ret = krb5_write_message (context, &pd.sock, &data);
632 if (ret)
633 krb5_err(context, 1, ret, "krb5_write_message");
635 return 0;
638 static int
639 propagate_database (krb5_context context, int type,
640 const char *database,
641 HDB *db, krb5_ccache ccache,
642 int optind, int argc, char **argv)
644 krb5_principal server;
645 krb5_error_code ret;
646 int i;
648 for(i = optind; i < argc; i++){
649 krb5_auth_context auth_context;
650 int fd;
651 struct prop_data pd;
652 krb5_data data;
654 char *port, portstr[NI_MAXSERV];
656 port = strchr(argv[i], ':');
657 if(port == NULL) {
658 snprintf(portstr, sizeof(portstr), "%u",
659 ntohs(krb5_getportbyname (context, "hprop", "tcp",
660 HPROP_PORT)));
661 port = portstr;
662 } else
663 *port++ = '\0';
665 fd = open_socket(context, argv[i], port);
666 if(fd < 0) {
667 krb5_warn (context, errno, "connect %s", argv[i]);
668 continue;
671 ret = krb5_sname_to_principal(context, argv[i],
672 HPROP_NAME, KRB5_NT_SRV_HST, &server);
673 if(ret) {
674 krb5_warn(context, ret, "krb5_sname_to_principal(%s)", argv[i]);
675 close(fd);
676 continue;
679 if (local_realm) {
680 krb5_realm my_realm;
681 krb5_get_default_realm(context,&my_realm);
683 free (*krb5_princ_realm(context, server));
684 krb5_princ_set_realm(context,server,&my_realm);
687 auth_context = NULL;
688 ret = krb5_sendauth(context,
689 &auth_context,
690 &fd,
691 HPROP_VERSION,
692 NULL,
693 server,
694 AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
695 NULL, /* in_data */
696 NULL, /* in_creds */
697 ccache,
698 NULL,
699 NULL,
700 NULL);
702 krb5_free_principal(context, server);
704 if(ret) {
705 krb5_warn(context, ret, "krb5_sendauth");
706 close(fd);
707 continue;
710 pd.context = context;
711 pd.auth_context = auth_context;
712 pd.sock = fd;
714 iterate (context, database, db, type, &pd);
716 krb5_data_zero (&data);
717 ret = krb5_write_priv_message(context, auth_context, &fd, &data);
718 if(ret)
719 krb5_warn(context, ret, "krb5_write_priv_message");
721 ret = krb5_read_priv_message(context, auth_context, &fd, &data);
722 if(ret)
723 krb5_warn(context, ret, "krb5_read_priv_message");
724 else
725 krb5_data_free (&data);
727 krb5_auth_con_free(context, auth_context);
728 close(fd);
730 return 0;
734 main(int argc, char **argv)
736 krb5_error_code ret;
737 krb5_context context;
738 krb5_ccache ccache = NULL;
739 HDB *db = NULL;
740 int optind = 0;
742 int type = 0;
744 setprogname(argv[0]);
746 if(getarg(args, num_args, argc, argv, &optind))
747 usage(1);
749 if(help_flag)
750 usage(0);
752 if(version_flag){
753 print_version(NULL);
754 exit(0);
757 ret = krb5_init_context(&context);
758 if(ret)
759 exit(1);
761 if(local_realm)
762 krb5_set_default_realm(context, local_realm);
764 if(v4_realm == NULL) {
765 ret = krb5_get_default_realm(context, &v4_realm);
766 if(ret)
767 krb5_err(context, 1, ret, "krb5_get_default_realm");
770 if(afs_cell == NULL) {
771 afs_cell = strdup(v4_realm);
772 if(afs_cell == NULL)
773 krb5_errx(context, 1, "out of memory");
774 strlwr(afs_cell);
778 if(encrypt_flag && decrypt_flag)
779 krb5_errx(context, 1,
780 "only one of `--encrypt' and `--decrypt' is meaningful");
782 if(source_type != NULL) {
783 if(type != 0)
784 krb5_errx(context, 1, "more than one database type specified");
785 type = parse_source_type(source_type);
786 if(type == 0)
787 krb5_errx(context, 1, "unknown source type `%s'", source_type);
788 } else if(type == 0)
789 type = HPROP_HEIMDAL;
791 if(!to_stdout)
792 get_creds(context, &ccache);
794 if(decrypt_flag || encrypt_flag) {
795 ret = hdb_read_master_key(context, mkeyfile, &mkey5);
796 if(ret && ret != ENOENT)
797 krb5_err(context, 1, ret, "hdb_read_master_key");
798 if(ret)
799 krb5_errx(context, 1, "No master key file found");
802 #ifdef KRB4
803 if (IS_TYPE_V4(type)) {
804 int e;
806 if (v4_realm == NULL) {
807 e = krb_get_lrealm(realm_buf, 1);
808 if(e)
809 krb5_errx(context, 1, "krb_get_lrealm: %s",
810 krb_get_err_text(e));
811 v4_realm = realm_buf;
814 #endif
816 switch(type) {
817 #ifdef KRB4
818 case HPROP_KRB4_DB:
819 if (database == NULL)
820 krb5_errx(context, 1, "no database specified");
821 break;
822 #endif
823 case HPROP_KASERVER:
824 if (database == NULL)
825 database = DEFAULT_DATABASE;
826 ka_use_null_salt = krb5_config_get_bool_default(context, NULL, FALSE,
827 "hprop",
828 "afs_uses_null_salt",
829 NULL);
831 break;
832 case HPROP_KRB4_DUMP:
833 if (database == NULL)
834 krb5_errx(context, 1, "no dump file specified");
836 break;
837 case HPROP_MIT_DUMP:
838 if (database == NULL)
839 krb5_errx(context, 1, "no dump file specified");
840 break;
841 case HPROP_HEIMDAL:
842 ret = hdb_create (context, &db, database);
843 if(ret)
844 krb5_err(context, 1, ret, "hdb_create: %s", database);
845 ret = db->open(context, db, O_RDONLY, 0);
846 if(ret)
847 krb5_err(context, 1, ret, "db->open");
848 break;
849 default:
850 krb5_errx(context, 1, "unknown dump type `%d'", type);
851 break;
854 if (to_stdout)
855 dump_database (context, type, database, db);
856 else
857 propagate_database (context, type, database,
858 db, ccache, optind, argc, argv);
860 if(ccache != NULL)
861 krb5_cc_destroy(context, ccache);
863 if(db != NULL)
864 (*db->destroy)(context, db);
866 krb5_free_context(context);
867 return 0;