xref: /freebsd/crypto/heimdal/kdc/hprop.c (revision 0cadf2f4d7b9f212800448d915003abd40c2e40d)
1b528cefcSMark Murray /*
28373020dSJacques Vidrine  * Copyright (c) 1997 - 2002 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "hprop.h"
35b528cefcSMark Murray 
360cadf2f4SJacques Vidrine RCSID("$Id: hprop.c,v 1.70 2002/09/04 18:19:41 joda Exp $");
37b528cefcSMark Murray 
38b528cefcSMark Murray static int version_flag;
39b528cefcSMark Murray static int help_flag;
408373020dSJacques Vidrine static const char *ktname = HPROP_KEYTAB;
418373020dSJacques Vidrine static const char *database;
42b528cefcSMark Murray static char *mkeyfile;
43b528cefcSMark Murray static int to_stdout;
44b528cefcSMark Murray static int verbose_flag;
45b528cefcSMark Murray static int encrypt_flag;
46b528cefcSMark Murray static int decrypt_flag;
475e9cd1aeSAssar Westerlund static hdb_master_key mkey5;
48b528cefcSMark Murray 
495e9cd1aeSAssar Westerlund static char *source_type;
505e9cd1aeSAssar Westerlund 
51b528cefcSMark Murray static char *afs_cell;
524137ff4cSJacques Vidrine static char *v4_realm;
53b528cefcSMark Murray 
54b528cefcSMark Murray static int kaspecials_flag;
555e9cd1aeSAssar Westerlund static int ka_use_null_salt;
56b528cefcSMark Murray 
575e9cd1aeSAssar Westerlund static char *local_realm=NULL;
585e9cd1aeSAssar Westerlund 
59b528cefcSMark Murray static int
605e9cd1aeSAssar Westerlund open_socket(krb5_context context, const char *hostname, const char *port)
61b528cefcSMark Murray {
62b528cefcSMark Murray     struct addrinfo *ai, *a;
63b528cefcSMark Murray     struct addrinfo hints;
64b528cefcSMark Murray     int error;
65b528cefcSMark Murray 
66b528cefcSMark Murray     memset (&hints, 0, sizeof(hints));
67b528cefcSMark Murray     hints.ai_socktype = SOCK_STREAM;
68b528cefcSMark Murray     hints.ai_protocol = IPPROTO_TCP;
69b528cefcSMark Murray 
705e9cd1aeSAssar Westerlund     error = getaddrinfo (hostname, port, &hints, &ai);
71b528cefcSMark Murray     if (error) {
72b528cefcSMark Murray 	warnx ("%s: %s", hostname, gai_strerror(error));
73b528cefcSMark Murray 	return -1;
74b528cefcSMark Murray     }
75b528cefcSMark Murray 
76b528cefcSMark Murray     for (a = ai; a != NULL; a = a->ai_next) {
77b528cefcSMark Murray 	int s;
78b528cefcSMark Murray 
79b528cefcSMark Murray 	s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
80b528cefcSMark Murray 	if (s < 0)
81b528cefcSMark Murray 	    continue;
82b528cefcSMark Murray 	if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
83b528cefcSMark Murray 	    warn ("connect(%s)", hostname);
84b528cefcSMark Murray 	    close (s);
85b528cefcSMark Murray 	    continue;
86b528cefcSMark Murray 	}
87b528cefcSMark Murray 	freeaddrinfo (ai);
88b528cefcSMark Murray 	return s;
89b528cefcSMark Murray     }
90b528cefcSMark Murray     warnx ("failed to contact %s", hostname);
91b528cefcSMark Murray     freeaddrinfo (ai);
92b528cefcSMark Murray     return -1;
93b528cefcSMark Murray }
94b528cefcSMark Murray 
955e9cd1aeSAssar Westerlund krb5_error_code
96b528cefcSMark Murray v5_prop(krb5_context context, HDB *db, hdb_entry *entry, void *appdata)
97b528cefcSMark Murray {
98b528cefcSMark Murray     krb5_error_code ret;
99b528cefcSMark Murray     struct prop_data *pd = appdata;
100b528cefcSMark Murray     krb5_data data;
101b528cefcSMark Murray 
1025e9cd1aeSAssar Westerlund     if(encrypt_flag) {
1035e9cd1aeSAssar Westerlund 	ret = hdb_seal_keys_mkey(context, entry, mkey5);
1045e9cd1aeSAssar Westerlund 	if (ret) {
1055e9cd1aeSAssar Westerlund 	    krb5_warn(context, ret, "hdb_seal_keys_mkey");
1065e9cd1aeSAssar Westerlund 	    return ret;
1075e9cd1aeSAssar Westerlund 	}
1085e9cd1aeSAssar Westerlund     }
1095e9cd1aeSAssar Westerlund     if(decrypt_flag) {
1105e9cd1aeSAssar Westerlund 	ret = hdb_unseal_keys_mkey(context, entry, mkey5);
1115e9cd1aeSAssar Westerlund 	if (ret) {
1125e9cd1aeSAssar Westerlund 	    krb5_warn(context, ret, "hdb_unseal_keys_mkey");
1135e9cd1aeSAssar Westerlund 	    return ret;
1145e9cd1aeSAssar Westerlund 	}
1155e9cd1aeSAssar Westerlund     }
116b528cefcSMark Murray 
117b528cefcSMark Murray     ret = hdb_entry2value(context, entry, &data);
1185e9cd1aeSAssar Westerlund     if(ret) {
1195e9cd1aeSAssar Westerlund 	krb5_warn(context, ret, "hdb_entry2value");
1205e9cd1aeSAssar Westerlund 	return ret;
1215e9cd1aeSAssar Westerlund     }
122b528cefcSMark Murray 
123b528cefcSMark Murray     if(to_stdout)
1245e9cd1aeSAssar Westerlund 	ret = krb5_write_message(context, &pd->sock, &data);
125b528cefcSMark Murray     else
1265e9cd1aeSAssar Westerlund 	ret = krb5_write_priv_message(context, pd->auth_context,
1275e9cd1aeSAssar Westerlund 				      &pd->sock, &data);
128b528cefcSMark Murray     krb5_data_free(&data);
129b528cefcSMark Murray     return ret;
130b528cefcSMark Murray }
131b528cefcSMark Murray 
132b528cefcSMark Murray #ifdef KRB4
1335e9cd1aeSAssar Westerlund 
134b528cefcSMark Murray static char realm_buf[REALM_SZ];
135b528cefcSMark Murray 
136b528cefcSMark Murray static int
1375e9cd1aeSAssar Westerlund kdb_prop(void *arg, Principal *p)
1385e9cd1aeSAssar Westerlund {
1395e9cd1aeSAssar Westerlund     int ret;
1405e9cd1aeSAssar Westerlund     struct v4_principal pr;
1415e9cd1aeSAssar Westerlund 
1425e9cd1aeSAssar Westerlund     memset(&pr, 0, sizeof(pr));
1435e9cd1aeSAssar Westerlund 
1445e9cd1aeSAssar Westerlund     if(p->attributes != 0) {
1455e9cd1aeSAssar Westerlund 	warnx("%s.%s has non-zero attributes - skipping",
1465e9cd1aeSAssar Westerlund 	      p->name, p->instance);
1475e9cd1aeSAssar Westerlund 	    return 0;
1485e9cd1aeSAssar Westerlund     }
1495e9cd1aeSAssar Westerlund     strlcpy(pr.name, p->name, sizeof(pr.name));
1505e9cd1aeSAssar Westerlund     strlcpy(pr.instance, p->instance, sizeof(pr.instance));
1515e9cd1aeSAssar Westerlund 
1525e9cd1aeSAssar Westerlund     copy_to_key(&p->key_low, &p->key_high, pr.key);
1535e9cd1aeSAssar Westerlund     pr.exp_date = p->exp_date;
1545e9cd1aeSAssar Westerlund     pr.mod_date = p->mod_date;
1555e9cd1aeSAssar Westerlund     strlcpy(pr.mod_name, p->mod_name, sizeof(pr.mod_name));
1565e9cd1aeSAssar Westerlund     strlcpy(pr.mod_instance, p->mod_instance, sizeof(pr.mod_instance));
1575e9cd1aeSAssar Westerlund     pr.max_life = p->max_life;
1584137ff4cSJacques Vidrine     pr.mkvno = p->kdc_key_ver;
1595e9cd1aeSAssar Westerlund     pr.kvno = p->key_version;
1605e9cd1aeSAssar Westerlund 
1615e9cd1aeSAssar Westerlund     ret = v4_prop(arg, &pr);
1625e9cd1aeSAssar Westerlund     memset(&pr, 0, sizeof(pr));
1635e9cd1aeSAssar Westerlund     return ret;
1645e9cd1aeSAssar Westerlund }
1655e9cd1aeSAssar Westerlund 
1665e9cd1aeSAssar Westerlund #endif /* KRB4 */
1675e9cd1aeSAssar Westerlund 
1685e9cd1aeSAssar Westerlund #ifndef KRB4
1695e9cd1aeSAssar Westerlund static time_t
1705e9cd1aeSAssar Westerlund krb_life_to_time(time_t start, int life)
1715e9cd1aeSAssar Westerlund {
1725e9cd1aeSAssar Westerlund     static int lifetimes[] = {
1735e9cd1aeSAssar Westerlund 	  38400,   41055,   43894,   46929,   50174,   53643,   57352,   61318,
1745e9cd1aeSAssar Westerlund 	  65558,   70091,   74937,   80119,   85658,   91581,   97914,  104684,
1755e9cd1aeSAssar Westerlund 	 111922,  119661,  127935,  136781,  146239,  156350,  167161,  178720,
1765e9cd1aeSAssar Westerlund 	 191077,  204289,  218415,  233517,  249664,  266926,  285383,  305116,
1775e9cd1aeSAssar Westerlund 	 326213,  348769,  372885,  398668,  426234,  455705,  487215,  520904,
1785e9cd1aeSAssar Westerlund 	 556921,  595430,  636601,  680618,  727680,  777995,  831789,  889303,
1795e9cd1aeSAssar Westerlund 	 950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247,
1805e9cd1aeSAssar Westerlund 	1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000
1815e9cd1aeSAssar Westerlund     };
1825e9cd1aeSAssar Westerlund 
1835e9cd1aeSAssar Westerlund #if 0
1845e9cd1aeSAssar Westerlund     int i;
1855e9cd1aeSAssar Westerlund     double q = exp((log(2592000.0) - log(38400.0)) / 63);
1865e9cd1aeSAssar Westerlund     double x = 38400;
1875e9cd1aeSAssar Westerlund     for(i = 0; i < 64; i++) {
1885e9cd1aeSAssar Westerlund 	lifetimes[i] = (int)x;
1895e9cd1aeSAssar Westerlund 	x *= q;
1905e9cd1aeSAssar Westerlund     }
1915e9cd1aeSAssar Westerlund #endif
1925e9cd1aeSAssar Westerlund 
1935e9cd1aeSAssar Westerlund     if(life == 0xff)
1945e9cd1aeSAssar Westerlund 	return NEVERDATE;
1955e9cd1aeSAssar Westerlund     if(life < 0x80)
1965e9cd1aeSAssar Westerlund 	return start + life * 5 * 60;
1975e9cd1aeSAssar Westerlund     if(life > 0xbf)
1985e9cd1aeSAssar Westerlund 	life = 0xbf;
1995e9cd1aeSAssar Westerlund     return start + lifetimes[life - 0x80];
2005e9cd1aeSAssar Westerlund }
2015e9cd1aeSAssar Westerlund #endif /* !KRB4 */
2025e9cd1aeSAssar Westerlund 
2035e9cd1aeSAssar Westerlund int
2045e9cd1aeSAssar Westerlund v4_prop(void *arg, struct v4_principal *p)
205b528cefcSMark Murray {
206b528cefcSMark Murray     struct prop_data *pd = arg;
207b528cefcSMark Murray     hdb_entry ent;
208b528cefcSMark Murray     krb5_error_code ret;
209b528cefcSMark Murray 
210b528cefcSMark Murray     memset(&ent, 0, sizeof(ent));
211b528cefcSMark Murray 
2124137ff4cSJacques Vidrine     ret = krb5_425_conv_principal(pd->context, p->name, p->instance, v4_realm,
213b528cefcSMark Murray 				  &ent.principal);
214b528cefcSMark Murray     if(ret) {
215b528cefcSMark Murray 	krb5_warn(pd->context, ret,
216b528cefcSMark Murray 		  "krb5_425_conv_principal %s.%s@%s",
2174137ff4cSJacques Vidrine 		  p->name, p->instance, v4_realm);
218b528cefcSMark Murray 	return 0;
219b528cefcSMark Murray     }
220b528cefcSMark Murray 
221b528cefcSMark Murray     if(verbose_flag) {
222b528cefcSMark Murray 	char *s;
223b528cefcSMark Murray 	krb5_unparse_name_short(pd->context, ent.principal, &s);
224b528cefcSMark Murray 	krb5_warnx(pd->context, "%s.%s -> %s", p->name, p->instance, s);
225b528cefcSMark Murray 	free(s);
226b528cefcSMark Murray     }
227b528cefcSMark Murray 
2285e9cd1aeSAssar Westerlund     ent.kvno = p->kvno;
229b528cefcSMark Murray     ent.keys.len = 3;
230b528cefcSMark Murray     ent.keys.val = malloc(ent.keys.len * sizeof(*ent.keys.val));
2315e9cd1aeSAssar Westerlund     if(p->mkvno != -1) {
232b528cefcSMark Murray 	ent.keys.val[0].mkvno = malloc (sizeof(*ent.keys.val[0].mkvno));
2334137ff4cSJacques Vidrine 	*(ent.keys.val[0].mkvno) = p->mkvno;
2345e9cd1aeSAssar Westerlund     } else
2355e9cd1aeSAssar Westerlund 	ent.keys.val[0].mkvno = NULL;
236b528cefcSMark Murray     ent.keys.val[0].salt = calloc(1, sizeof(*ent.keys.val[0].salt));
2375e9cd1aeSAssar Westerlund     ent.keys.val[0].salt->type = KRB5_PADATA_PW_SALT;
238b528cefcSMark Murray     ent.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
239b528cefcSMark Murray     krb5_data_alloc(&ent.keys.val[0].key.keyvalue, sizeof(des_cblock));
2405e9cd1aeSAssar Westerlund     memcpy(ent.keys.val[0].key.keyvalue.data, p->key, 8);
241b528cefcSMark Murray 
242b528cefcSMark Murray     copy_Key(&ent.keys.val[0], &ent.keys.val[1]);
243b528cefcSMark Murray     ent.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
244b528cefcSMark Murray     copy_Key(&ent.keys.val[0], &ent.keys.val[2]);
245b528cefcSMark Murray     ent.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;
246b528cefcSMark Murray 
2475e9cd1aeSAssar Westerlund     {
2485e9cd1aeSAssar Westerlund 	int life = krb_life_to_time(0, p->max_life);
2495e9cd1aeSAssar Westerlund 	if(life == NEVERDATE){
250b528cefcSMark Murray 	    ent.max_life = NULL;
2515e9cd1aeSAssar Westerlund 	} else {
2525e9cd1aeSAssar Westerlund 	    /* clean up lifetime a bit */
2535e9cd1aeSAssar Westerlund 	    if(life > 86400)
2545e9cd1aeSAssar Westerlund 		life = (life + 86399) / 86400 * 86400;
2555e9cd1aeSAssar Westerlund 	    else if(life > 3600)
2565e9cd1aeSAssar Westerlund 		life = (life + 3599) / 3600 * 3600;
2575e9cd1aeSAssar Westerlund 	    ALLOC(ent.max_life);
2585e9cd1aeSAssar Westerlund 	    *ent.max_life = life;
2595e9cd1aeSAssar Westerlund 	}
260b528cefcSMark Murray     }
261b528cefcSMark Murray 
2625e9cd1aeSAssar Westerlund     ALLOC(ent.valid_end);
2635e9cd1aeSAssar Westerlund     *ent.valid_end = p->exp_date;
2645e9cd1aeSAssar Westerlund 
265b528cefcSMark Murray     ret = krb5_make_principal(pd->context, &ent.created_by.principal,
2664137ff4cSJacques Vidrine 			      v4_realm,
267b528cefcSMark Murray 			      "kadmin",
268b528cefcSMark Murray 			      "hprop",
269b528cefcSMark Murray 			      NULL);
270b528cefcSMark Murray     if(ret){
271b528cefcSMark Murray 	krb5_warn(pd->context, ret, "krb5_make_principal");
272b528cefcSMark Murray 	ret = 0;
273b528cefcSMark Murray 	goto out;
274b528cefcSMark Murray     }
275b528cefcSMark Murray     ent.created_by.time = time(NULL);
276b528cefcSMark Murray     ALLOC(ent.modified_by);
277b528cefcSMark Murray     ret = krb5_425_conv_principal(pd->context, p->mod_name, p->mod_instance,
2784137ff4cSJacques Vidrine 				  v4_realm, &ent.modified_by->principal);
279b528cefcSMark Murray     if(ret){
2804137ff4cSJacques Vidrine 	krb5_warn(pd->context, ret, "%s.%s@%s", p->name, p->instance, v4_realm);
281b528cefcSMark Murray 	ent.modified_by->principal = NULL;
282b528cefcSMark Murray 	ret = 0;
283b528cefcSMark Murray 	goto out;
284b528cefcSMark Murray     }
285b528cefcSMark Murray     ent.modified_by->time = p->mod_date;
286b528cefcSMark Murray 
287b528cefcSMark Murray     ent.flags.forwardable = 1;
288b528cefcSMark Murray     ent.flags.renewable = 1;
289b528cefcSMark Murray     ent.flags.proxiable = 1;
290b528cefcSMark Murray     ent.flags.postdate = 1;
291b528cefcSMark Murray     ent.flags.client = 1;
292b528cefcSMark Murray     ent.flags.server = 1;
293b528cefcSMark Murray 
294b528cefcSMark Murray     /* special case password changing service */
295b528cefcSMark Murray     if(strcmp(p->name, "changepw") == 0 &&
296b528cefcSMark Murray        strcmp(p->instance, "kerberos") == 0) {
297b528cefcSMark Murray 	ent.flags.forwardable = 0;
298b528cefcSMark Murray 	ent.flags.renewable = 0;
299b528cefcSMark Murray 	ent.flags.proxiable = 0;
300b528cefcSMark Murray 	ent.flags.postdate = 0;
301b528cefcSMark Murray 	ent.flags.initial = 1;
302b528cefcSMark Murray 	ent.flags.change_pw = 1;
303b528cefcSMark Murray     }
304b528cefcSMark Murray 
305b528cefcSMark Murray     ret = v5_prop(pd->context, NULL, &ent, pd);
306b528cefcSMark Murray 
307b528cefcSMark Murray     if (strcmp (p->name, "krbtgt") == 0
3084137ff4cSJacques Vidrine 	&& strcmp (v4_realm, p->instance) != 0) {
309b528cefcSMark Murray 	krb5_free_principal (pd->context, ent.principal);
310b528cefcSMark Murray 	ret = krb5_425_conv_principal (pd->context, p->name,
3114137ff4cSJacques Vidrine 				       v4_realm, p->instance,
312b528cefcSMark Murray 				       &ent.principal);
313b528cefcSMark Murray 	if (ret == 0)
314b528cefcSMark Murray 	    ret = v5_prop (pd->context, NULL, &ent, pd);
315b528cefcSMark Murray     }
316b528cefcSMark Murray 
317b528cefcSMark Murray   out:
318b528cefcSMark Murray     hdb_free_entry(pd->context, &ent);
319b528cefcSMark Murray     return ret;
320b528cefcSMark Murray }
321b528cefcSMark Murray 
322b528cefcSMark Murray #include "kadb.h"
323b528cefcSMark Murray 
324b528cefcSMark Murray /* read a `ka_entry' from `fd' at offset `pos' */
325b528cefcSMark Murray static void
326b528cefcSMark Murray read_block(krb5_context context, int fd, int32_t pos, void *buf, size_t len)
327b528cefcSMark Murray {
328b528cefcSMark Murray     krb5_error_code ret;
3294137ff4cSJacques Vidrine #ifdef HAVE_PREAD
3304137ff4cSJacques Vidrine     if((ret = pread(fd, buf, len, 64 + pos)) < 0)
3314137ff4cSJacques Vidrine 	krb5_err(context, 1, errno, "pread(%u)", 64 + pos);
3324137ff4cSJacques Vidrine #else
333b528cefcSMark Murray     if(lseek(fd, 64 + pos, SEEK_SET) == (off_t)-1)
334b528cefcSMark Murray 	krb5_err(context, 1, errno, "lseek(%u)", 64 + pos);
335b528cefcSMark Murray     ret = read(fd, buf, len);
336b528cefcSMark Murray     if(ret < 0)
3374137ff4cSJacques Vidrine 	krb5_err(context, 1, errno, "read(%lu)", (unsigned long)len);
3384137ff4cSJacques Vidrine #endif
339b528cefcSMark Murray     if(ret != len)
3404137ff4cSJacques Vidrine 	krb5_errx(context, 1, "read(%lu) = %u", (unsigned long)len, ret);
341b528cefcSMark Murray }
342b528cefcSMark Murray 
343b528cefcSMark Murray static int
3444137ff4cSJacques Vidrine ka_convert(struct prop_data *pd, int fd, struct ka_entry *ent)
345b528cefcSMark Murray {
346b528cefcSMark Murray     int32_t flags = ntohl(ent->flags);
347b528cefcSMark Murray     krb5_error_code ret;
348b528cefcSMark Murray     hdb_entry hdb;
349b528cefcSMark Murray 
350b528cefcSMark Murray     if(!kaspecials_flag
351b528cefcSMark Murray        && (flags & KAFNORMAL) == 0) /* remove special entries */
352b528cefcSMark Murray 	return 0;
353b528cefcSMark Murray     memset(&hdb, 0, sizeof(hdb));
3544137ff4cSJacques Vidrine     ret = krb5_425_conv_principal(pd->context, ent->name, ent->instance,
3554137ff4cSJacques Vidrine 				  v4_realm, &hdb.principal);
356b528cefcSMark Murray     if(ret) {
357b528cefcSMark Murray 	krb5_warn(pd->context, ret,
358b528cefcSMark Murray 		  "krb5_425_conv_principal (%s.%s@%s)",
3594137ff4cSJacques Vidrine 		  ent->name, ent->instance, v4_realm);
360b528cefcSMark Murray 	return 0;
361b528cefcSMark Murray     }
362b528cefcSMark Murray     hdb.kvno = ntohl(ent->kvno);
363b528cefcSMark Murray     hdb.keys.len = 3;
364b528cefcSMark Murray     hdb.keys.val = malloc(hdb.keys.len * sizeof(*hdb.keys.val));
365b528cefcSMark Murray     hdb.keys.val[0].mkvno = NULL;
366b528cefcSMark Murray     hdb.keys.val[0].salt = calloc(1, sizeof(*hdb.keys.val[0].salt));
3675e9cd1aeSAssar Westerlund     if (ka_use_null_salt) {
3685e9cd1aeSAssar Westerlund 	hdb.keys.val[0].salt->type = hdb_pw_salt;
3695e9cd1aeSAssar Westerlund 	hdb.keys.val[0].salt->salt.data = NULL;
3705e9cd1aeSAssar Westerlund 	hdb.keys.val[0].salt->salt.length = 0;
3715e9cd1aeSAssar Westerlund     } else {
372b528cefcSMark Murray 	hdb.keys.val[0].salt->type = hdb_afs3_salt;
3734137ff4cSJacques Vidrine 	hdb.keys.val[0].salt->salt.data = strdup(afs_cell);
3744137ff4cSJacques Vidrine 	hdb.keys.val[0].salt->salt.length = strlen(afs_cell);
3755e9cd1aeSAssar Westerlund     }
376b528cefcSMark Murray 
377b528cefcSMark Murray     hdb.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
378b528cefcSMark Murray     krb5_data_copy(&hdb.keys.val[0].key.keyvalue, ent->key, sizeof(ent->key));
379b528cefcSMark Murray     copy_Key(&hdb.keys.val[0], &hdb.keys.val[1]);
380b528cefcSMark Murray     hdb.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
381b528cefcSMark Murray     copy_Key(&hdb.keys.val[0], &hdb.keys.val[2]);
382b528cefcSMark Murray     hdb.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;
383b528cefcSMark Murray 
384b528cefcSMark Murray     ALLOC(hdb.max_life);
385b528cefcSMark Murray     *hdb.max_life = ntohl(ent->max_life);
386b528cefcSMark Murray 
3875e9cd1aeSAssar Westerlund     if(ntohl(ent->valid_end) != NEVERDATE && ntohl(ent->valid_end) != -1){
3885e9cd1aeSAssar Westerlund 	ALLOC(hdb.valid_end);
3895e9cd1aeSAssar Westerlund 	*hdb.valid_end = ntohl(ent->valid_end);
3905e9cd1aeSAssar Westerlund     }
3915e9cd1aeSAssar Westerlund 
3925e9cd1aeSAssar Westerlund     if (ntohl(ent->pw_change) != NEVERDATE &&
3935e9cd1aeSAssar Westerlund 	ent->pw_expire != 255 &&
3945e9cd1aeSAssar Westerlund 	ent->pw_expire != 0) {
395b528cefcSMark Murray 	ALLOC(hdb.pw_end);
3965e9cd1aeSAssar Westerlund 	*hdb.pw_end = ntohl(ent->pw_change)
3975e9cd1aeSAssar Westerlund 	    + 24 * 60 * 60 * ent->pw_expire;
398b528cefcSMark Murray     }
399b528cefcSMark Murray 
400b528cefcSMark Murray     ret = krb5_make_principal(pd->context, &hdb.created_by.principal,
4014137ff4cSJacques Vidrine 			      v4_realm,
402b528cefcSMark Murray 			      "kadmin",
403b528cefcSMark Murray 			      "hprop",
404b528cefcSMark Murray 			      NULL);
405b528cefcSMark Murray     hdb.created_by.time = time(NULL);
406b528cefcSMark Murray 
407b528cefcSMark Murray     if(ent->mod_ptr){
408b528cefcSMark Murray 	struct ka_entry mod;
409b528cefcSMark Murray 	ALLOC(hdb.modified_by);
410b528cefcSMark Murray 	read_block(pd->context, fd, ntohl(ent->mod_ptr), &mod, sizeof(mod));
411b528cefcSMark Murray 
4124137ff4cSJacques Vidrine 	krb5_425_conv_principal(pd->context, mod.name, mod.instance, v4_realm,
413b528cefcSMark Murray 				&hdb.modified_by->principal);
414b528cefcSMark Murray 	hdb.modified_by->time = ntohl(ent->mod_time);
415b528cefcSMark Murray 	memset(&mod, 0, sizeof(mod));
416b528cefcSMark Murray     }
417b528cefcSMark Murray 
418b528cefcSMark Murray     hdb.flags.forwardable = 1;
419b528cefcSMark Murray     hdb.flags.renewable = 1;
420b528cefcSMark Murray     hdb.flags.proxiable = 1;
421b528cefcSMark Murray     hdb.flags.postdate = 1;
422b528cefcSMark Murray     /* XXX - AFS 3.4a creates krbtgt.REALMOFCELL as NOTGS+NOSEAL */
423b528cefcSMark Murray     if (strcmp(ent->name, "krbtgt") == 0 &&
424b528cefcSMark Murray 	(flags & (KAFNOTGS|KAFNOSEAL)) == (KAFNOTGS|KAFNOSEAL))
425b528cefcSMark Murray 	flags &= ~(KAFNOTGS|KAFNOSEAL);
426b528cefcSMark Murray 
427b528cefcSMark Murray     hdb.flags.client = (flags & KAFNOTGS) == 0;
428b528cefcSMark Murray     hdb.flags.server = (flags & KAFNOSEAL) == 0;
429b528cefcSMark Murray 
430b528cefcSMark Murray     ret = v5_prop(pd->context, NULL, &hdb, pd);
431b528cefcSMark Murray     hdb_free_entry(pd->context, &hdb);
432b528cefcSMark Murray     return ret;
433b528cefcSMark Murray }
434b528cefcSMark Murray 
435b528cefcSMark Murray static int
4364137ff4cSJacques Vidrine ka_dump(struct prop_data *pd, const char *file)
437b528cefcSMark Murray {
438b528cefcSMark Murray     struct ka_header header;
439b528cefcSMark Murray     int i;
440b528cefcSMark Murray     int fd = open(file, O_RDONLY);
441b528cefcSMark Murray 
442b528cefcSMark Murray     if(fd < 0)
443b528cefcSMark Murray 	krb5_err(pd->context, 1, errno, "open(%s)", file);
444b528cefcSMark Murray     read_block(pd->context, fd, 0, &header, sizeof(header));
445b528cefcSMark Murray     if(header.version1 != header.version2)
446adb0ddaeSAssar Westerlund 	krb5_errx(pd->context, 1, "Version mismatch in header: %ld/%ld",
447adb0ddaeSAssar Westerlund 		  (long)ntohl(header.version1), (long)ntohl(header.version2));
448b528cefcSMark Murray     if(ntohl(header.version1) != 5)
449adb0ddaeSAssar Westerlund 	krb5_errx(pd->context, 1, "Unknown database version %ld (expected 5)",
450adb0ddaeSAssar Westerlund 		  (long)ntohl(header.version1));
451b528cefcSMark Murray     for(i = 0; i < ntohl(header.hashsize); i++){
452b528cefcSMark Murray 	int32_t pos = ntohl(header.hash[i]);
453b528cefcSMark Murray 	while(pos){
454b528cefcSMark Murray 	    struct ka_entry ent;
455b528cefcSMark Murray 	    read_block(pd->context, fd, pos, &ent, sizeof(ent));
4564137ff4cSJacques Vidrine 	    ka_convert(pd, fd, &ent);
457b528cefcSMark Murray 	    pos = ntohl(ent.next);
458b528cefcSMark Murray 	}
459b528cefcSMark Murray     }
460b528cefcSMark Murray     return 0;
461b528cefcSMark Murray }
462b528cefcSMark Murray 
463b528cefcSMark Murray 
464b528cefcSMark Murray 
465b528cefcSMark Murray struct getargs args[] = {
466b528cefcSMark Murray     { "master-key", 'm', arg_string, &mkeyfile, "v5 master key file", "file" },
467b528cefcSMark Murray     { "database", 'd',	arg_string, &database, "database", "file" },
4685e9cd1aeSAssar Westerlund     { "source",   0,	arg_string, &source_type, "type of database to read",
4695e9cd1aeSAssar Westerlund       "heimdal"
4705e9cd1aeSAssar Westerlund       "|mit-dump"
4715e9cd1aeSAssar Westerlund       "|krb4-dump"
472b528cefcSMark Murray #ifdef KRB4
4735e9cd1aeSAssar Westerlund       "|krb4-db"
4744137ff4cSJacques Vidrine #endif
4755e9cd1aeSAssar Westerlund       "|kaserver"
4765e9cd1aeSAssar Westerlund     },
4775e9cd1aeSAssar Westerlund 
4784137ff4cSJacques Vidrine     { "v4-realm", 'r',  arg_string, &v4_realm, "v4 realm to use" },
479b528cefcSMark Murray     { "cell",	  'c',  arg_string, &afs_cell, "name of AFS cell" },
480b528cefcSMark Murray     { "kaspecials", 'S', arg_flag,   &kaspecials_flag, "dump KASPECIAL keys"},
481b528cefcSMark Murray     { "keytab",   'k',	arg_string, &ktname, "keytab to use for authentication", "keytab" },
4825e9cd1aeSAssar Westerlund     { "v5-realm", 'R',  arg_string, &local_realm, "v5 realm to use" },
483b528cefcSMark Murray     { "decrypt",  'D',  arg_flag,   &decrypt_flag,   "decrypt keys" },
484b528cefcSMark Murray     { "encrypt",  'E',  arg_flag,   &encrypt_flag,   "encrypt keys" },
485b528cefcSMark Murray     { "stdout",	  'n',  arg_flag,   &to_stdout, "dump to stdout" },
486b528cefcSMark Murray     { "verbose",  'v',	arg_flag, &verbose_flag },
487b528cefcSMark Murray     { "version",   0,	arg_flag, &version_flag },
488b528cefcSMark Murray     { "help",     'h',	arg_flag, &help_flag }
489b528cefcSMark Murray };
490b528cefcSMark Murray 
491b528cefcSMark Murray static int num_args = sizeof(args) / sizeof(args[0]);
492b528cefcSMark Murray 
493b528cefcSMark Murray static void
494b528cefcSMark Murray usage(int ret)
495b528cefcSMark Murray {
4964137ff4cSJacques Vidrine     arg_printusage (args, num_args, NULL, "[host[:port]] ...");
497b528cefcSMark Murray     exit (ret);
498b528cefcSMark Murray }
499b528cefcSMark Murray 
500b528cefcSMark Murray static void
501b528cefcSMark Murray get_creds(krb5_context context, krb5_ccache *cache)
502b528cefcSMark Murray {
503b528cefcSMark Murray     krb5_keytab keytab;
504b528cefcSMark Murray     krb5_principal client;
505b528cefcSMark Murray     krb5_error_code ret;
506b528cefcSMark Murray     krb5_get_init_creds_opt init_opts;
507b528cefcSMark Murray     krb5_preauthtype preauth = KRB5_PADATA_ENC_TIMESTAMP;
508b528cefcSMark Murray     krb5_creds creds;
509b528cefcSMark Murray 
5105e9cd1aeSAssar Westerlund     ret = krb5_kt_register(context, &hdb_kt_ops);
5115e9cd1aeSAssar Westerlund     if(ret) krb5_err(context, 1, ret, "krb5_kt_register");
5125e9cd1aeSAssar Westerlund 
513b528cefcSMark Murray     ret = krb5_kt_resolve(context, ktname, &keytab);
514b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve");
515b528cefcSMark Murray 
516b528cefcSMark Murray     ret = krb5_make_principal(context, &client, NULL,
517b528cefcSMark Murray 			      "kadmin", HPROP_NAME, NULL);
518b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_make_principal");
519b528cefcSMark Murray 
520b528cefcSMark Murray     krb5_get_init_creds_opt_init(&init_opts);
521b528cefcSMark Murray     krb5_get_init_creds_opt_set_preauth_list(&init_opts, &preauth, 1);
522b528cefcSMark Murray 
523b528cefcSMark Murray     ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, NULL, &init_opts);
524b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds");
525b528cefcSMark Murray 
526b528cefcSMark Murray     ret = krb5_kt_close(context, keytab);
527b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_kt_close");
528b528cefcSMark Murray 
529b528cefcSMark Murray     ret = krb5_cc_gen_new(context, &krb5_mcc_ops, cache);
530b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_cc_gen_new");
531b528cefcSMark Murray 
532b528cefcSMark Murray     ret = krb5_cc_initialize(context, *cache, client);
533b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize");
534b528cefcSMark Murray 
5354137ff4cSJacques Vidrine     krb5_free_principal(context, client);
5364137ff4cSJacques Vidrine 
537b528cefcSMark Murray     ret = krb5_cc_store_cred(context, *cache, &creds);
538b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred");
5394137ff4cSJacques Vidrine 
5404137ff4cSJacques Vidrine     krb5_free_creds_contents(context, &creds);
541b528cefcSMark Murray }
542b528cefcSMark Murray 
5435e9cd1aeSAssar Westerlund enum hprop_source {
5445e9cd1aeSAssar Westerlund     HPROP_HEIMDAL = 1,
5455e9cd1aeSAssar Westerlund     HPROP_KRB4_DB,
5465e9cd1aeSAssar Westerlund     HPROP_KRB4_DUMP,
5475e9cd1aeSAssar Westerlund     HPROP_KASERVER,
5485e9cd1aeSAssar Westerlund     HPROP_MIT_DUMP
5495e9cd1aeSAssar Westerlund };
5505e9cd1aeSAssar Westerlund 
5515e9cd1aeSAssar Westerlund #define IS_TYPE_V4(X) ((X) == HPROP_KRB4_DB || (X) == HPROP_KRB4_DUMP || (X) == HPROP_KASERVER)
5525e9cd1aeSAssar Westerlund 
5535e9cd1aeSAssar Westerlund struct {
5545e9cd1aeSAssar Westerlund     int type;
5555e9cd1aeSAssar Westerlund     const char *name;
5565e9cd1aeSAssar Westerlund } types[] = {
5575e9cd1aeSAssar Westerlund     { HPROP_HEIMDAL,	"heimdal" },
5585e9cd1aeSAssar Westerlund     { HPROP_KRB4_DUMP,	"krb4-dump" },
5595e9cd1aeSAssar Westerlund #ifdef KRB4
5605e9cd1aeSAssar Westerlund     { HPROP_KRB4_DB,	"krb4-db" },
5614137ff4cSJacques Vidrine #endif
5625e9cd1aeSAssar Westerlund     { HPROP_KASERVER, 	"kaserver" },
5635e9cd1aeSAssar Westerlund     { HPROP_MIT_DUMP,	"mit-dump" }
5645e9cd1aeSAssar Westerlund };
5655e9cd1aeSAssar Westerlund 
5665e9cd1aeSAssar Westerlund static int
5675e9cd1aeSAssar Westerlund parse_source_type(const char *s)
5685e9cd1aeSAssar Westerlund {
5695e9cd1aeSAssar Westerlund     int i;
5705e9cd1aeSAssar Westerlund     for(i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
5715e9cd1aeSAssar Westerlund 	if(strstr(types[i].name, s) == types[i].name)
5725e9cd1aeSAssar Westerlund 	    return types[i].type;
5735e9cd1aeSAssar Westerlund     }
5745e9cd1aeSAssar Westerlund     return 0;
5755e9cd1aeSAssar Westerlund }
5765e9cd1aeSAssar Westerlund 
577b528cefcSMark Murray static void
578b528cefcSMark Murray iterate (krb5_context context,
579b528cefcSMark Murray 	 const char *database,
580b528cefcSMark Murray 	 HDB *db,
5815e9cd1aeSAssar Westerlund 	 int type,
582b528cefcSMark Murray 	 struct prop_data *pd)
583b528cefcSMark Murray {
5845e9cd1aeSAssar Westerlund     int ret;
5855e9cd1aeSAssar Westerlund 
5865e9cd1aeSAssar Westerlund     switch(type) {
5875e9cd1aeSAssar Westerlund     case HPROP_KRB4_DUMP:
5885e9cd1aeSAssar Westerlund 	ret = v4_prop_dump(pd, database);
5895e9cd1aeSAssar Westerlund 	break;
590b528cefcSMark Murray #ifdef KRB4
5915e9cd1aeSAssar Westerlund     case HPROP_KRB4_DB:
5925e9cd1aeSAssar Westerlund 	ret = kerb_db_iterate ((k_iter_proc_t)kdb_prop, pd);
5935e9cd1aeSAssar Westerlund 	if(ret)
594b528cefcSMark Murray 	    krb5_errx(context, 1, "kerb_db_iterate: %s",
5955e9cd1aeSAssar Westerlund 		      krb_get_err_text(ret));
5965e9cd1aeSAssar Westerlund 	break;
5975e9cd1aeSAssar Westerlund #endif /* KRB4 */
5984137ff4cSJacques Vidrine     case HPROP_KASERVER:
5994137ff4cSJacques Vidrine 	ret = ka_dump(pd, database);
6004137ff4cSJacques Vidrine 	if(ret)
6014137ff4cSJacques Vidrine 	    krb5_err(context, 1, ret, "ka_dump");
6024137ff4cSJacques Vidrine 	break;
6035e9cd1aeSAssar Westerlund     case HPROP_MIT_DUMP:
6045e9cd1aeSAssar Westerlund 	ret = mit_prop_dump(pd, database);
6055e9cd1aeSAssar Westerlund 	if (ret)
6065e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "mit_prop_dump: %s",
6075e9cd1aeSAssar Westerlund 		      krb5_get_err_text(context, ret));
6085e9cd1aeSAssar Westerlund 	break;
6095e9cd1aeSAssar Westerlund     case HPROP_HEIMDAL:
6105e9cd1aeSAssar Westerlund 	ret = hdb_foreach(context, db, HDB_F_DECRYPT, v5_prop, pd);
611b528cefcSMark Murray 	if(ret)
612b528cefcSMark Murray 	    krb5_err(context, 1, ret, "hdb_foreach");
6135e9cd1aeSAssar Westerlund 	break;
614b528cefcSMark Murray     }
615b528cefcSMark Murray }
616b528cefcSMark Murray 
617b528cefcSMark Murray static int
6185e9cd1aeSAssar Westerlund dump_database (krb5_context context, int type,
6194137ff4cSJacques Vidrine 	       const char *database, HDB *db)
620b528cefcSMark Murray {
6215e9cd1aeSAssar Westerlund     krb5_error_code ret;
622b528cefcSMark Murray     struct prop_data pd;
6235e9cd1aeSAssar Westerlund     krb5_data data;
624b528cefcSMark Murray 
625b528cefcSMark Murray     pd.context      = context;
626b528cefcSMark Murray     pd.auth_context = NULL;
627b528cefcSMark Murray     pd.sock         = STDOUT_FILENO;
628b528cefcSMark Murray 
6294137ff4cSJacques Vidrine     iterate (context, database, db, type, &pd);
6305e9cd1aeSAssar Westerlund     krb5_data_zero (&data);
6315e9cd1aeSAssar Westerlund     ret = krb5_write_message (context, &pd.sock, &data);
6325e9cd1aeSAssar Westerlund     if (ret)
6335e9cd1aeSAssar Westerlund 	krb5_err(context, 1, ret, "krb5_write_message");
6345e9cd1aeSAssar Westerlund 
635b528cefcSMark Murray     return 0;
636b528cefcSMark Murray }
637b528cefcSMark Murray 
638b528cefcSMark Murray static int
6395e9cd1aeSAssar Westerlund propagate_database (krb5_context context, int type,
6404137ff4cSJacques Vidrine 		    const char *database,
641b528cefcSMark Murray 		    HDB *db, krb5_ccache ccache,
642b528cefcSMark Murray 		    int optind, int argc, char **argv)
643b528cefcSMark Murray {
644b528cefcSMark Murray     krb5_principal server;
645b528cefcSMark Murray     krb5_error_code ret;
646b528cefcSMark Murray     int i;
647b528cefcSMark Murray 
648b528cefcSMark Murray     for(i = optind; i < argc; i++){
649b528cefcSMark Murray 	krb5_auth_context auth_context;
650b528cefcSMark Murray 	int fd;
651b528cefcSMark Murray 	struct prop_data pd;
652b528cefcSMark Murray 	krb5_data data;
653b528cefcSMark Murray 
6545e9cd1aeSAssar Westerlund 	char *port, portstr[NI_MAXSERV];
6555e9cd1aeSAssar Westerlund 
6565e9cd1aeSAssar Westerlund 	port = strchr(argv[i], ':');
6575e9cd1aeSAssar Westerlund 	if(port == NULL) {
6585e9cd1aeSAssar Westerlund 	    snprintf(portstr, sizeof(portstr), "%u",
6595e9cd1aeSAssar Westerlund 		     ntohs(krb5_getportbyname (context, "hprop", "tcp",
6605e9cd1aeSAssar Westerlund 					       HPROP_PORT)));
6615e9cd1aeSAssar Westerlund 	    port = portstr;
6625e9cd1aeSAssar Westerlund 	} else
6635e9cd1aeSAssar Westerlund 	    *port++ = '\0';
6645e9cd1aeSAssar Westerlund 
6655e9cd1aeSAssar Westerlund 	fd = open_socket(context, argv[i], port);
666b528cefcSMark Murray 	if(fd < 0) {
667b528cefcSMark Murray 	    krb5_warn (context, errno, "connect %s", argv[i]);
668b528cefcSMark Murray 	    continue;
669b528cefcSMark Murray 	}
670b528cefcSMark Murray 
671b528cefcSMark Murray 	ret = krb5_sname_to_principal(context, argv[i],
672b528cefcSMark Murray 				      HPROP_NAME, KRB5_NT_SRV_HST, &server);
673b528cefcSMark Murray 	if(ret) {
674b528cefcSMark Murray 	    krb5_warn(context, ret, "krb5_sname_to_principal(%s)", argv[i]);
675b528cefcSMark Murray 	    close(fd);
676b528cefcSMark Murray 	    continue;
677b528cefcSMark Murray 	}
678b528cefcSMark Murray 
6795e9cd1aeSAssar Westerlund         if (local_realm) {
6805e9cd1aeSAssar Westerlund             krb5_realm my_realm;
6815e9cd1aeSAssar Westerlund             krb5_get_default_realm(context,&my_realm);
6825e9cd1aeSAssar Westerlund 
6834137ff4cSJacques Vidrine 	    free (*krb5_princ_realm(context, server));
6845e9cd1aeSAssar Westerlund             krb5_princ_set_realm(context,server,&my_realm);
6855e9cd1aeSAssar Westerlund         }
6865e9cd1aeSAssar Westerlund 
687b528cefcSMark Murray 	auth_context = NULL;
688b528cefcSMark Murray 	ret = krb5_sendauth(context,
689b528cefcSMark Murray 			    &auth_context,
690b528cefcSMark Murray 			    &fd,
691b528cefcSMark Murray 			    HPROP_VERSION,
692b528cefcSMark Murray 			    NULL,
693b528cefcSMark Murray 			    server,
6940cadf2f4SJacques Vidrine 			    AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
695b528cefcSMark Murray 			    NULL, /* in_data */
696b528cefcSMark Murray 			    NULL, /* in_creds */
697b528cefcSMark Murray 			    ccache,
698b528cefcSMark Murray 			    NULL,
699b528cefcSMark Murray 			    NULL,
700b528cefcSMark Murray 			    NULL);
701b528cefcSMark Murray 
7024137ff4cSJacques Vidrine 	krb5_free_principal(context, server);
7034137ff4cSJacques Vidrine 
704b528cefcSMark Murray 	if(ret) {
705b528cefcSMark Murray 	    krb5_warn(context, ret, "krb5_sendauth");
706b528cefcSMark Murray 	    close(fd);
707b528cefcSMark Murray 	    continue;
708b528cefcSMark Murray 	}
709b528cefcSMark Murray 
710b528cefcSMark Murray 	pd.context      = context;
711b528cefcSMark Murray 	pd.auth_context = auth_context;
712b528cefcSMark Murray 	pd.sock         = fd;
713b528cefcSMark Murray 
7144137ff4cSJacques Vidrine 	iterate (context, database, db, type, &pd);
715b528cefcSMark Murray 
7165e9cd1aeSAssar Westerlund 	krb5_data_zero (&data);
7175e9cd1aeSAssar Westerlund 	ret = krb5_write_priv_message(context, auth_context, &fd, &data);
718b528cefcSMark Murray 	if(ret)
7195e9cd1aeSAssar Westerlund 	    krb5_warn(context, ret, "krb5_write_priv_message");
720b528cefcSMark Murray 
7215e9cd1aeSAssar Westerlund 	ret = krb5_read_priv_message(context, auth_context, &fd, &data);
722b528cefcSMark Murray 	if(ret)
7235e9cd1aeSAssar Westerlund 	    krb5_warn(context, ret, "krb5_read_priv_message");
724b528cefcSMark Murray 	else
725b528cefcSMark Murray 	    krb5_data_free (&data);
726b528cefcSMark Murray 
727b528cefcSMark Murray 	krb5_auth_con_free(context, auth_context);
728b528cefcSMark Murray 	close(fd);
729b528cefcSMark Murray     }
730b528cefcSMark Murray     return 0;
731b528cefcSMark Murray }
732b528cefcSMark Murray 
733b528cefcSMark Murray int
734b528cefcSMark Murray main(int argc, char **argv)
735b528cefcSMark Murray {
736b528cefcSMark Murray     krb5_error_code ret;
737b528cefcSMark Murray     krb5_context context;
7384137ff4cSJacques Vidrine     krb5_ccache ccache = NULL;
7394137ff4cSJacques Vidrine     HDB *db = NULL;
740b528cefcSMark Murray     int optind = 0;
741b528cefcSMark Murray 
7425e9cd1aeSAssar Westerlund     int type = 0;
7435e9cd1aeSAssar Westerlund 
744adb0ddaeSAssar Westerlund     setprogname(argv[0]);
745b528cefcSMark Murray 
746b528cefcSMark Murray     if(getarg(args, num_args, argc, argv, &optind))
747b528cefcSMark Murray 	usage(1);
748b528cefcSMark Murray 
749b528cefcSMark Murray     if(help_flag)
750b528cefcSMark Murray 	usage(0);
751b528cefcSMark Murray 
752b528cefcSMark Murray     if(version_flag){
753b528cefcSMark Murray 	print_version(NULL);
754b528cefcSMark Murray 	exit(0);
755b528cefcSMark Murray     }
756b528cefcSMark Murray 
757b528cefcSMark Murray     ret = krb5_init_context(&context);
758b528cefcSMark Murray     if(ret)
759b528cefcSMark Murray 	exit(1);
760b528cefcSMark Murray 
7615e9cd1aeSAssar Westerlund     if(local_realm)
7625e9cd1aeSAssar Westerlund 	krb5_set_default_realm(context, local_realm);
7635e9cd1aeSAssar Westerlund 
7644137ff4cSJacques Vidrine     if(v4_realm == NULL) {
7654137ff4cSJacques Vidrine 	ret = krb5_get_default_realm(context, &v4_realm);
7664137ff4cSJacques Vidrine 	if(ret)
7674137ff4cSJacques Vidrine 	    krb5_err(context, 1, ret, "krb5_get_default_realm");
7684137ff4cSJacques Vidrine     }
7694137ff4cSJacques Vidrine 
7704137ff4cSJacques Vidrine     if(afs_cell == NULL) {
7714137ff4cSJacques Vidrine 	afs_cell = strdup(v4_realm);
7724137ff4cSJacques Vidrine 	if(afs_cell == NULL)
7734137ff4cSJacques Vidrine 	    krb5_errx(context, 1, "out of memory");
7744137ff4cSJacques Vidrine 	strlwr(afs_cell);
7754137ff4cSJacques Vidrine     }
7764137ff4cSJacques Vidrine 
7775e9cd1aeSAssar Westerlund 
778b528cefcSMark Murray     if(encrypt_flag && decrypt_flag)
779b528cefcSMark Murray 	krb5_errx(context, 1,
7805e9cd1aeSAssar Westerlund 		  "only one of `--encrypt' and `--decrypt' is meaningful");
7815e9cd1aeSAssar Westerlund 
7825e9cd1aeSAssar Westerlund     if(source_type != NULL) {
7835e9cd1aeSAssar Westerlund 	if(type != 0)
7845e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "more than one database type specified");
7855e9cd1aeSAssar Westerlund 	type = parse_source_type(source_type);
7865e9cd1aeSAssar Westerlund 	if(type == 0)
7875e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "unknown source type `%s'", source_type);
7885e9cd1aeSAssar Westerlund     } else if(type == 0)
7895e9cd1aeSAssar Westerlund 	type = HPROP_HEIMDAL;
790b528cefcSMark Murray 
791b528cefcSMark Murray     if(!to_stdout)
792b528cefcSMark Murray 	get_creds(context, &ccache);
793b528cefcSMark Murray 
7945e9cd1aeSAssar Westerlund     if(decrypt_flag || encrypt_flag) {
795b528cefcSMark Murray 	ret = hdb_read_master_key(context, mkeyfile, &mkey5);
796b528cefcSMark Murray 	if(ret && ret != ENOENT)
797b528cefcSMark Murray 	    krb5_err(context, 1, ret, "hdb_read_master_key");
798b528cefcSMark Murray 	if(ret)
7995e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "No master key file found");
800b528cefcSMark Murray     }
801b528cefcSMark Murray 
802b528cefcSMark Murray #ifdef KRB4
8035e9cd1aeSAssar Westerlund     if (IS_TYPE_V4(type)) {
804b528cefcSMark Murray 	int e;
805b528cefcSMark Murray 
8064137ff4cSJacques Vidrine 	if (v4_realm == NULL) {
807b528cefcSMark Murray 	    e = krb_get_lrealm(realm_buf, 1);
808b528cefcSMark Murray 	    if(e)
809b528cefcSMark Murray 		krb5_errx(context, 1, "krb_get_lrealm: %s",
810b528cefcSMark Murray 			  krb_get_err_text(e));
8114137ff4cSJacques Vidrine 	    v4_realm = realm_buf;
812b528cefcSMark Murray 	}
813b528cefcSMark Murray     }
8145e9cd1aeSAssar Westerlund #endif
815b528cefcSMark Murray 
8165e9cd1aeSAssar Westerlund     switch(type) {
8175e9cd1aeSAssar Westerlund #ifdef KRB4
8185e9cd1aeSAssar Westerlund     case HPROP_KRB4_DB:
8195e9cd1aeSAssar Westerlund 	if (database == NULL)
8205e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "no database specified");
8215e9cd1aeSAssar Westerlund 	break;
8224137ff4cSJacques Vidrine #endif
8235e9cd1aeSAssar Westerlund     case HPROP_KASERVER:
8245e9cd1aeSAssar Westerlund 	if (database == NULL)
8255e9cd1aeSAssar Westerlund 	    database = DEFAULT_DATABASE;
8265e9cd1aeSAssar Westerlund 	ka_use_null_salt = krb5_config_get_bool_default(context, NULL, FALSE,
8275e9cd1aeSAssar Westerlund 							"hprop",
8285e9cd1aeSAssar Westerlund 							"afs_uses_null_salt",
8295e9cd1aeSAssar Westerlund 							NULL);
8305e9cd1aeSAssar Westerlund 
8315e9cd1aeSAssar Westerlund 	break;
8325e9cd1aeSAssar Westerlund     case HPROP_KRB4_DUMP:
8335e9cd1aeSAssar Westerlund 	if (database == NULL)
8345e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "no dump file specified");
8354137ff4cSJacques Vidrine 
8365e9cd1aeSAssar Westerlund 	break;
8375e9cd1aeSAssar Westerlund     case HPROP_MIT_DUMP:
8385e9cd1aeSAssar Westerlund 	if (database == NULL)
8395e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "no dump file specified");
8405e9cd1aeSAssar Westerlund 	break;
8415e9cd1aeSAssar Westerlund     case HPROP_HEIMDAL:
842b528cefcSMark Murray 	ret = hdb_create (context, &db, database);
843b528cefcSMark Murray 	if(ret)
844b528cefcSMark Murray 	    krb5_err(context, 1, ret, "hdb_create: %s", database);
845b528cefcSMark Murray 	ret = db->open(context, db, O_RDONLY, 0);
846b528cefcSMark Murray 	if(ret)
847b528cefcSMark Murray 	    krb5_err(context, 1, ret, "db->open");
8485e9cd1aeSAssar Westerlund 	break;
8495e9cd1aeSAssar Westerlund     default:
8505e9cd1aeSAssar Westerlund 	krb5_errx(context, 1, "unknown dump type `%d'", type);
8515e9cd1aeSAssar Westerlund 	break;
852b528cefcSMark Murray     }
853b528cefcSMark Murray 
854b528cefcSMark Murray     if (to_stdout)
8554137ff4cSJacques Vidrine 	dump_database (context, type, database, db);
856b528cefcSMark Murray     else
8574137ff4cSJacques Vidrine 	propagate_database (context, type, database,
8585e9cd1aeSAssar Westerlund 			    db, ccache, optind, argc, argv);
8594137ff4cSJacques Vidrine 
8604137ff4cSJacques Vidrine     if(ccache != NULL)
8614137ff4cSJacques Vidrine 	krb5_cc_destroy(context, ccache);
8624137ff4cSJacques Vidrine 
8634137ff4cSJacques Vidrine     if(db != NULL)
8644137ff4cSJacques Vidrine 	(*db->destroy)(context, db);
8654137ff4cSJacques Vidrine 
8664137ff4cSJacques Vidrine     krb5_free_context(context);
867b528cefcSMark Murray     return 0;
868b528cefcSMark Murray }
869