Add _krb5_kcm_is_running/_krb5_kcm_noop API
[heimdal.git] / kdc / hprop.c
blob7973a26f6e5132c31574c73acd08e6afe3351e0b
1 /*
2 * Copyright (c) 1997 - 2004 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$");
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, DES_KEY_SZ);
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) != 0xffffffff) {
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 ret = krb5_get_init_creds_opt_alloc(context, &init_opts);
521 if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
522 krb5_get_init_creds_opt_set_preauth_list(init_opts, &preauth, 1);
524 ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, NULL, init_opts);
525 if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds");
527 krb5_get_init_creds_opt_free(init_opts);
529 ret = krb5_kt_close(context, keytab);
530 if(ret) krb5_err(context, 1, ret, "krb5_kt_close");
532 ret = krb5_cc_gen_new(context, &krb5_mcc_ops, cache);
533 if(ret) krb5_err(context, 1, ret, "krb5_cc_gen_new");
535 ret = krb5_cc_initialize(context, *cache, client);
536 if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize");
538 krb5_free_principal(context, client);
540 ret = krb5_cc_store_cred(context, *cache, &creds);
541 if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred");
543 krb5_free_cred_contents(context, &creds);
546 enum hprop_source {
547 HPROP_HEIMDAL = 1,
548 HPROP_KRB4_DB,
549 HPROP_KRB4_DUMP,
550 HPROP_KASERVER,
551 HPROP_MIT_DUMP
554 #define IS_TYPE_V4(X) ((X) == HPROP_KRB4_DB || (X) == HPROP_KRB4_DUMP || (X) == HPROP_KASERVER)
556 struct {
557 int type;
558 const char *name;
559 } types[] = {
560 { HPROP_HEIMDAL, "heimdal" },
561 { HPROP_KRB4_DUMP, "krb4-dump" },
562 #ifdef KRB4
563 { HPROP_KRB4_DB, "krb4-db" },
564 #endif
565 { HPROP_KASERVER, "kaserver" },
566 { HPROP_MIT_DUMP, "mit-dump" }
569 static int
570 parse_source_type(const char *s)
572 int i;
573 for(i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
574 if(strstr(types[i].name, s) == types[i].name)
575 return types[i].type;
577 return 0;
580 static void
581 iterate (krb5_context context,
582 const char *database,
583 HDB *db,
584 int type,
585 struct prop_data *pd)
587 int ret;
589 switch(type) {
590 case HPROP_KRB4_DUMP:
591 ret = v4_prop_dump(pd, database);
592 break;
593 #ifdef KRB4
594 case HPROP_KRB4_DB:
595 ret = kerb_db_iterate ((k_iter_proc_t)kdb_prop, pd);
596 if(ret)
597 krb5_errx(context, 1, "kerb_db_iterate: %s",
598 krb_get_err_text(ret));
599 break;
600 #endif /* KRB4 */
601 case HPROP_KASERVER:
602 ret = ka_dump(pd, database);
603 if(ret)
604 krb5_err(context, 1, ret, "ka_dump");
605 break;
606 case HPROP_MIT_DUMP:
607 ret = mit_prop_dump(pd, database);
608 if (ret)
609 krb5_errx(context, 1, "mit_prop_dump: %s",
610 krb5_get_err_text(context, ret));
611 break;
612 case HPROP_HEIMDAL:
613 ret = hdb_foreach(context, db, HDB_F_DECRYPT, v5_prop, pd);
614 if(ret)
615 krb5_err(context, 1, ret, "hdb_foreach");
616 break;
620 static int
621 dump_database (krb5_context context, int type,
622 const char *database, HDB *db)
624 krb5_error_code ret;
625 struct prop_data pd;
626 krb5_data data;
628 pd.context = context;
629 pd.auth_context = NULL;
630 pd.sock = STDOUT_FILENO;
632 iterate (context, database, db, type, &pd);
633 krb5_data_zero (&data);
634 ret = krb5_write_message (context, &pd.sock, &data);
635 if (ret)
636 krb5_err(context, 1, ret, "krb5_write_message");
638 return 0;
641 static int
642 propagate_database (krb5_context context, int type,
643 const char *database,
644 HDB *db, krb5_ccache ccache,
645 int optind, int argc, char **argv)
647 krb5_principal server;
648 krb5_error_code ret;
649 int i;
651 for(i = optind; i < argc; i++){
652 krb5_auth_context auth_context;
653 int fd;
654 struct prop_data pd;
655 krb5_data data;
657 char *port, portstr[NI_MAXSERV];
659 port = strchr(argv[i], ':');
660 if(port == NULL) {
661 snprintf(portstr, sizeof(portstr), "%u",
662 ntohs(krb5_getportbyname (context, "hprop", "tcp",
663 HPROP_PORT)));
664 port = portstr;
665 } else
666 *port++ = '\0';
668 fd = open_socket(context, argv[i], port);
669 if(fd < 0) {
670 krb5_warn (context, errno, "connect %s", argv[i]);
671 continue;
674 ret = krb5_sname_to_principal(context, argv[i],
675 HPROP_NAME, KRB5_NT_SRV_HST, &server);
676 if(ret) {
677 krb5_warn(context, ret, "krb5_sname_to_principal(%s)", argv[i]);
678 close(fd);
679 continue;
682 if (local_realm) {
683 krb5_realm my_realm;
684 krb5_get_default_realm(context,&my_realm);
686 free (*krb5_princ_realm(context, server));
687 krb5_princ_set_realm(context,server,&my_realm);
690 auth_context = NULL;
691 ret = krb5_sendauth(context,
692 &auth_context,
693 &fd,
694 HPROP_VERSION,
695 NULL,
696 server,
697 AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
698 NULL, /* in_data */
699 NULL, /* in_creds */
700 ccache,
701 NULL,
702 NULL,
703 NULL);
705 krb5_free_principal(context, server);
707 if(ret) {
708 krb5_warn(context, ret, "krb5_sendauth");
709 close(fd);
710 continue;
713 pd.context = context;
714 pd.auth_context = auth_context;
715 pd.sock = fd;
717 iterate (context, database, db, type, &pd);
719 krb5_data_zero (&data);
720 ret = krb5_write_priv_message(context, auth_context, &fd, &data);
721 if(ret)
722 krb5_warn(context, ret, "krb5_write_priv_message");
724 ret = krb5_read_priv_message(context, auth_context, &fd, &data);
725 if(ret)
726 krb5_warn(context, ret, "krb5_read_priv_message");
727 else
728 krb5_data_free (&data);
730 krb5_auth_con_free(context, auth_context);
731 close(fd);
733 return 0;
737 main(int argc, char **argv)
739 krb5_error_code ret;
740 krb5_context context;
741 krb5_ccache ccache = NULL;
742 HDB *db = NULL;
743 int optind = 0;
745 int type = 0;
747 setprogname(argv[0]);
749 if(getarg(args, num_args, argc, argv, &optind))
750 usage(1);
752 if(help_flag)
753 usage(0);
755 if(version_flag){
756 print_version(NULL);
757 exit(0);
760 ret = krb5_init_context(&context);
761 if(ret)
762 exit(1);
764 if(local_realm)
765 krb5_set_default_realm(context, local_realm);
767 if(v4_realm == NULL) {
768 ret = krb5_get_default_realm(context, &v4_realm);
769 if(ret)
770 krb5_err(context, 1, ret, "krb5_get_default_realm");
773 if(afs_cell == NULL) {
774 afs_cell = strdup(v4_realm);
775 if(afs_cell == NULL)
776 krb5_errx(context, 1, "out of memory");
777 strlwr(afs_cell);
781 if(encrypt_flag && decrypt_flag)
782 krb5_errx(context, 1,
783 "only one of `--encrypt' and `--decrypt' is meaningful");
785 if(source_type != NULL) {
786 if(type != 0)
787 krb5_errx(context, 1, "more than one database type specified");
788 type = parse_source_type(source_type);
789 if(type == 0)
790 krb5_errx(context, 1, "unknown source type `%s'", source_type);
791 } else if(type == 0)
792 type = HPROP_HEIMDAL;
794 if(!to_stdout)
795 get_creds(context, &ccache);
797 if(decrypt_flag || encrypt_flag) {
798 ret = hdb_read_master_key(context, mkeyfile, &mkey5);
799 if(ret && ret != ENOENT)
800 krb5_err(context, 1, ret, "hdb_read_master_key");
801 if(ret)
802 krb5_errx(context, 1, "No master key file found");
805 #ifdef KRB4
806 if (IS_TYPE_V4(type)) {
807 int e;
809 if (v4_realm == NULL) {
810 e = krb_get_lrealm(realm_buf, 1);
811 if(e)
812 krb5_errx(context, 1, "krb_get_lrealm: %s",
813 krb_get_err_text(e));
814 v4_realm = realm_buf;
817 #endif
819 switch(type) {
820 #ifdef KRB4
821 case HPROP_KRB4_DB:
822 if (database == NULL)
823 krb5_errx(context, 1, "no database specified");
824 break;
825 #endif
826 case HPROP_KASERVER:
827 if (database == NULL)
828 database = DEFAULT_DATABASE;
829 ka_use_null_salt = krb5_config_get_bool_default(context, NULL, FALSE,
830 "hprop",
831 "afs_uses_null_salt",
832 NULL);
834 break;
835 case HPROP_KRB4_DUMP:
836 if (database == NULL)
837 krb5_errx(context, 1, "no dump file specified");
839 break;
840 case HPROP_MIT_DUMP:
841 if (database == NULL)
842 krb5_errx(context, 1, "no dump file specified");
843 break;
844 case HPROP_HEIMDAL:
845 ret = hdb_create (context, &db, database);
846 if(ret)
847 krb5_err(context, 1, ret, "hdb_create: %s", database);
848 ret = db->hdb_open(context, db, O_RDONLY, 0);
849 if(ret)
850 krb5_err(context, 1, ret, "db->hdb_open");
851 break;
852 default:
853 krb5_errx(context, 1, "unknown dump type `%d'", type);
854 break;
857 if (to_stdout)
858 dump_database (context, type, database, db);
859 else
860 propagate_database (context, type, database,
861 db, ccache, optind, argc, argv);
863 if(ccache != NULL)
864 krb5_cc_destroy(context, ccache);
866 if(db != NULL)
867 (*db->hdb_destroy)(context, db);
869 krb5_free_context(context);
870 return 0;