xref: /freebsd/crypto/heimdal/kdc/hprop.c (revision 5e9cd1ae)
1b528cefcSMark Murray /*
25e9cd1aeSAssar Westerlund  * Copyright (c) 1997 - 2001 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 
365e9cd1aeSAssar Westerlund RCSID("$Id: hprop.c,v 1.60 2001/02/05 03:40:00 assar Exp $");
37b528cefcSMark Murray 
38b528cefcSMark Murray static int version_flag;
39b528cefcSMark Murray static int help_flag;
40b528cefcSMark Murray static char *ktname = HPROP_KEYTAB;
41b528cefcSMark Murray static 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;
525e9cd1aeSAssar Westerlund static char *realm;
53b528cefcSMark Murray 
54b528cefcSMark Murray #ifdef KRB4
555e9cd1aeSAssar Westerlund static int v4_db;
565e9cd1aeSAssar Westerlund 
575e9cd1aeSAssar Westerlund static des_cblock mkey4;
585e9cd1aeSAssar Westerlund static des_key_schedule msched4;
59b528cefcSMark Murray 
60b528cefcSMark Murray #ifdef KASERVER_DB
61b528cefcSMark Murray static int kaspecials_flag;
625e9cd1aeSAssar Westerlund static int ka_db;
635e9cd1aeSAssar Westerlund static int ka_use_null_salt;
64b528cefcSMark Murray #endif
65b528cefcSMark Murray #endif
66b528cefcSMark Murray 
675e9cd1aeSAssar Westerlund static char *local_realm=NULL;
685e9cd1aeSAssar Westerlund 
69b528cefcSMark Murray static int
705e9cd1aeSAssar Westerlund open_socket(krb5_context context, const char *hostname, const char *port)
71b528cefcSMark Murray {
72b528cefcSMark Murray     struct addrinfo *ai, *a;
73b528cefcSMark Murray     struct addrinfo hints;
74b528cefcSMark Murray     int error;
75b528cefcSMark Murray 
76b528cefcSMark Murray     memset (&hints, 0, sizeof(hints));
77b528cefcSMark Murray     hints.ai_socktype = SOCK_STREAM;
78b528cefcSMark Murray     hints.ai_protocol = IPPROTO_TCP;
79b528cefcSMark Murray 
805e9cd1aeSAssar Westerlund     error = getaddrinfo (hostname, port, &hints, &ai);
81b528cefcSMark Murray     if (error) {
82b528cefcSMark Murray 	warnx ("%s: %s", hostname, gai_strerror(error));
83b528cefcSMark Murray 	return -1;
84b528cefcSMark Murray     }
85b528cefcSMark Murray 
86b528cefcSMark Murray     for (a = ai; a != NULL; a = a->ai_next) {
87b528cefcSMark Murray 	int s;
88b528cefcSMark Murray 
89b528cefcSMark Murray 	s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
90b528cefcSMark Murray 	if (s < 0)
91b528cefcSMark Murray 	    continue;
92b528cefcSMark Murray 	if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
93b528cefcSMark Murray 	    warn ("connect(%s)", hostname);
94b528cefcSMark Murray 	    close (s);
95b528cefcSMark Murray 	    continue;
96b528cefcSMark Murray 	}
97b528cefcSMark Murray 	freeaddrinfo (ai);
98b528cefcSMark Murray 	return s;
99b528cefcSMark Murray     }
100b528cefcSMark Murray     warnx ("failed to contact %s", hostname);
101b528cefcSMark Murray     freeaddrinfo (ai);
102b528cefcSMark Murray     return -1;
103b528cefcSMark Murray }
104b528cefcSMark Murray 
1055e9cd1aeSAssar Westerlund krb5_error_code
106b528cefcSMark Murray v5_prop(krb5_context context, HDB *db, hdb_entry *entry, void *appdata)
107b528cefcSMark Murray {
108b528cefcSMark Murray     krb5_error_code ret;
109b528cefcSMark Murray     struct prop_data *pd = appdata;
110b528cefcSMark Murray     krb5_data data;
111b528cefcSMark Murray 
1125e9cd1aeSAssar Westerlund     if(encrypt_flag) {
1135e9cd1aeSAssar Westerlund 	ret = hdb_seal_keys_mkey(context, entry, mkey5);
1145e9cd1aeSAssar Westerlund 	if (ret) {
1155e9cd1aeSAssar Westerlund 	    krb5_warn(context, ret, "hdb_seal_keys_mkey");
1165e9cd1aeSAssar Westerlund 	    return ret;
1175e9cd1aeSAssar Westerlund 	}
1185e9cd1aeSAssar Westerlund     }
1195e9cd1aeSAssar Westerlund     if(decrypt_flag) {
1205e9cd1aeSAssar Westerlund 	ret = hdb_unseal_keys_mkey(context, entry, mkey5);
1215e9cd1aeSAssar Westerlund 	if (ret) {
1225e9cd1aeSAssar Westerlund 	    krb5_warn(context, ret, "hdb_unseal_keys_mkey");
1235e9cd1aeSAssar Westerlund 	    return ret;
1245e9cd1aeSAssar Westerlund 	}
1255e9cd1aeSAssar Westerlund     }
126b528cefcSMark Murray 
127b528cefcSMark Murray     ret = hdb_entry2value(context, entry, &data);
1285e9cd1aeSAssar Westerlund     if(ret) {
1295e9cd1aeSAssar Westerlund 	krb5_warn(context, ret, "hdb_entry2value");
1305e9cd1aeSAssar Westerlund 	return ret;
1315e9cd1aeSAssar Westerlund     }
132b528cefcSMark Murray 
133b528cefcSMark Murray     if(to_stdout)
1345e9cd1aeSAssar Westerlund 	ret = krb5_write_message(context, &pd->sock, &data);
135b528cefcSMark Murray     else
1365e9cd1aeSAssar Westerlund 	ret = krb5_write_priv_message(context, pd->auth_context,
1375e9cd1aeSAssar Westerlund 				      &pd->sock, &data);
138b528cefcSMark Murray     krb5_data_free(&data);
139b528cefcSMark Murray     return ret;
140b528cefcSMark Murray }
141b528cefcSMark Murray 
142b528cefcSMark Murray #ifdef KRB4
1435e9cd1aeSAssar Westerlund 
144b528cefcSMark Murray static char realm_buf[REALM_SZ];
145b528cefcSMark Murray 
146b528cefcSMark Murray static int
1475e9cd1aeSAssar Westerlund kdb_prop(void *arg, Principal *p)
1485e9cd1aeSAssar Westerlund {
1495e9cd1aeSAssar Westerlund     int ret;
1505e9cd1aeSAssar Westerlund     struct v4_principal pr;
1515e9cd1aeSAssar Westerlund 
1525e9cd1aeSAssar Westerlund     memset(&pr, 0, sizeof(pr));
1535e9cd1aeSAssar Westerlund 
1545e9cd1aeSAssar Westerlund     if(p->attributes != 0) {
1555e9cd1aeSAssar Westerlund 	warnx("%s.%s has non-zero attributes - skipping",
1565e9cd1aeSAssar Westerlund 	      p->name, p->instance);
1575e9cd1aeSAssar Westerlund 	    return 0;
1585e9cd1aeSAssar Westerlund     }
1595e9cd1aeSAssar Westerlund     strlcpy(pr.name, p->name, sizeof(pr.name));
1605e9cd1aeSAssar Westerlund     strlcpy(pr.instance, p->instance, sizeof(pr.instance));
1615e9cd1aeSAssar Westerlund 
1625e9cd1aeSAssar Westerlund     copy_to_key(&p->key_low, &p->key_high, pr.key);
1635e9cd1aeSAssar Westerlund     kdb_encrypt_key(&pr.key, &pr.key, &mkey4, msched4, DES_DECRYPT);
1645e9cd1aeSAssar Westerlund     pr.exp_date = p->exp_date;
1655e9cd1aeSAssar Westerlund     pr.mod_date = p->mod_date;
1665e9cd1aeSAssar Westerlund     strlcpy(pr.mod_name, p->mod_name, sizeof(pr.mod_name));
1675e9cd1aeSAssar Westerlund     strlcpy(pr.mod_instance, p->mod_instance, sizeof(pr.mod_instance));
1685e9cd1aeSAssar Westerlund     pr.max_life = p->max_life;
1695e9cd1aeSAssar Westerlund     pr.mkvno = -1; /* p->kdc_key_ver; */
1705e9cd1aeSAssar Westerlund     pr.kvno = p->key_version;
1715e9cd1aeSAssar Westerlund 
1725e9cd1aeSAssar Westerlund     ret = v4_prop(arg, &pr);
1735e9cd1aeSAssar Westerlund     memset(&pr, 0, sizeof(pr));
1745e9cd1aeSAssar Westerlund     return ret;
1755e9cd1aeSAssar Westerlund }
1765e9cd1aeSAssar Westerlund 
1775e9cd1aeSAssar Westerlund #endif /* KRB4 */
1785e9cd1aeSAssar Westerlund 
1795e9cd1aeSAssar Westerlund #ifndef KRB4
1805e9cd1aeSAssar Westerlund static time_t
1815e9cd1aeSAssar Westerlund krb_life_to_time(time_t start, int life)
1825e9cd1aeSAssar Westerlund {
1835e9cd1aeSAssar Westerlund     static int lifetimes[] = {
1845e9cd1aeSAssar Westerlund 	  38400,   41055,   43894,   46929,   50174,   53643,   57352,   61318,
1855e9cd1aeSAssar Westerlund 	  65558,   70091,   74937,   80119,   85658,   91581,   97914,  104684,
1865e9cd1aeSAssar Westerlund 	 111922,  119661,  127935,  136781,  146239,  156350,  167161,  178720,
1875e9cd1aeSAssar Westerlund 	 191077,  204289,  218415,  233517,  249664,  266926,  285383,  305116,
1885e9cd1aeSAssar Westerlund 	 326213,  348769,  372885,  398668,  426234,  455705,  487215,  520904,
1895e9cd1aeSAssar Westerlund 	 556921,  595430,  636601,  680618,  727680,  777995,  831789,  889303,
1905e9cd1aeSAssar Westerlund 	 950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247,
1915e9cd1aeSAssar Westerlund 	1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000
1925e9cd1aeSAssar Westerlund     };
1935e9cd1aeSAssar Westerlund 
1945e9cd1aeSAssar Westerlund #if 0
1955e9cd1aeSAssar Westerlund     int i;
1965e9cd1aeSAssar Westerlund     double q = exp((log(2592000.0) - log(38400.0)) / 63);
1975e9cd1aeSAssar Westerlund     double x = 38400;
1985e9cd1aeSAssar Westerlund     for(i = 0; i < 64; i++) {
1995e9cd1aeSAssar Westerlund 	lifetimes[i] = (int)x;
2005e9cd1aeSAssar Westerlund 	x *= q;
2015e9cd1aeSAssar Westerlund     }
2025e9cd1aeSAssar Westerlund #endif
2035e9cd1aeSAssar Westerlund 
2045e9cd1aeSAssar Westerlund     if(life == 0xff)
2055e9cd1aeSAssar Westerlund 	return NEVERDATE;
2065e9cd1aeSAssar Westerlund     if(life < 0x80)
2075e9cd1aeSAssar Westerlund 	return start + life * 5 * 60;
2085e9cd1aeSAssar Westerlund     if(life > 0xbf)
2095e9cd1aeSAssar Westerlund 	life = 0xbf;
2105e9cd1aeSAssar Westerlund     return start + lifetimes[life - 0x80];
2115e9cd1aeSAssar Westerlund }
2125e9cd1aeSAssar Westerlund #endif /* !KRB4 */
2135e9cd1aeSAssar Westerlund 
2145e9cd1aeSAssar Westerlund int
2155e9cd1aeSAssar Westerlund v4_prop(void *arg, struct v4_principal *p)
216b528cefcSMark Murray {
217b528cefcSMark Murray     struct prop_data *pd = arg;
218b528cefcSMark Murray     hdb_entry ent;
219b528cefcSMark Murray     krb5_error_code ret;
220b528cefcSMark Murray 
221b528cefcSMark Murray     memset(&ent, 0, sizeof(ent));
222b528cefcSMark Murray 
223b528cefcSMark Murray     ret = krb5_425_conv_principal(pd->context, p->name, p->instance, realm,
224b528cefcSMark Murray 				  &ent.principal);
225b528cefcSMark Murray     if(ret){
226b528cefcSMark Murray 	krb5_warn(pd->context, ret,
227b528cefcSMark Murray 		  "krb5_425_conv_principal %s.%s@%s",
228b528cefcSMark Murray 		  p->name, p->instance, realm);
229b528cefcSMark Murray 	return 0;
230b528cefcSMark Murray     }
231b528cefcSMark Murray 
232b528cefcSMark Murray     if(verbose_flag) {
233b528cefcSMark Murray 	char *s;
234b528cefcSMark Murray 	krb5_unparse_name_short(pd->context, ent.principal, &s);
235b528cefcSMark Murray 	krb5_warnx(pd->context, "%s.%s -> %s", p->name, p->instance, s);
236b528cefcSMark Murray 	free(s);
237b528cefcSMark Murray     }
238b528cefcSMark Murray 
2395e9cd1aeSAssar Westerlund     ent.kvno = p->kvno;
240b528cefcSMark Murray     ent.keys.len = 3;
241b528cefcSMark Murray     ent.keys.val = malloc(ent.keys.len * sizeof(*ent.keys.val));
2425e9cd1aeSAssar Westerlund     if(p->mkvno != -1) {
243b528cefcSMark Murray 	ent.keys.val[0].mkvno = malloc (sizeof(*ent.keys.val[0].mkvno));
2445e9cd1aeSAssar Westerlund #if 0
2455e9cd1aeSAssar Westerlund 	*(ent.keys.val[0].mkvno) = p->mkvno; /* XXX */
2465e9cd1aeSAssar Westerlund #else
2475e9cd1aeSAssar Westerlund 	*(ent.keys.val[0].mkvno) = 0;
248b528cefcSMark Murray #endif
2495e9cd1aeSAssar Westerlund     } else
2505e9cd1aeSAssar Westerlund 	ent.keys.val[0].mkvno = NULL;
251b528cefcSMark Murray     ent.keys.val[0].salt = calloc(1, sizeof(*ent.keys.val[0].salt));
2525e9cd1aeSAssar Westerlund     ent.keys.val[0].salt->type = KRB5_PADATA_PW_SALT;
253b528cefcSMark Murray     ent.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
254b528cefcSMark Murray     krb5_data_alloc(&ent.keys.val[0].key.keyvalue, sizeof(des_cblock));
2555e9cd1aeSAssar Westerlund     memcpy(ent.keys.val[0].key.keyvalue.data, p->key, 8);
256b528cefcSMark Murray 
257b528cefcSMark Murray     copy_Key(&ent.keys.val[0], &ent.keys.val[1]);
258b528cefcSMark Murray     ent.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
259b528cefcSMark Murray     copy_Key(&ent.keys.val[0], &ent.keys.val[2]);
260b528cefcSMark Murray     ent.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;
261b528cefcSMark Murray 
2625e9cd1aeSAssar Westerlund     {
2635e9cd1aeSAssar Westerlund 	int life = krb_life_to_time(0, p->max_life);
2645e9cd1aeSAssar Westerlund 	if(life == NEVERDATE){
265b528cefcSMark Murray 	    ent.max_life = NULL;
2665e9cd1aeSAssar Westerlund 	} else {
2675e9cd1aeSAssar Westerlund 	    /* clean up lifetime a bit */
2685e9cd1aeSAssar Westerlund 	    if(life > 86400)
2695e9cd1aeSAssar Westerlund 		life = (life + 86399) / 86400 * 86400;
2705e9cd1aeSAssar Westerlund 	    else if(life > 3600)
2715e9cd1aeSAssar Westerlund 		life = (life + 3599) / 3600 * 3600;
2725e9cd1aeSAssar Westerlund 	    ALLOC(ent.max_life);
2735e9cd1aeSAssar Westerlund 	    *ent.max_life = life;
2745e9cd1aeSAssar Westerlund 	}
275b528cefcSMark Murray     }
276b528cefcSMark Murray 
2775e9cd1aeSAssar Westerlund     ALLOC(ent.valid_end);
2785e9cd1aeSAssar Westerlund     *ent.valid_end = p->exp_date;
2795e9cd1aeSAssar Westerlund 
280b528cefcSMark Murray     ret = krb5_make_principal(pd->context, &ent.created_by.principal,
281b528cefcSMark Murray 			      realm,
282b528cefcSMark Murray 			      "kadmin",
283b528cefcSMark Murray 			      "hprop",
284b528cefcSMark Murray 			      NULL);
285b528cefcSMark Murray     if(ret){
286b528cefcSMark Murray 	krb5_warn(pd->context, ret, "krb5_make_principal");
287b528cefcSMark Murray 	ret = 0;
288b528cefcSMark Murray 	goto out;
289b528cefcSMark Murray     }
290b528cefcSMark Murray     ent.created_by.time = time(NULL);
291b528cefcSMark Murray     ALLOC(ent.modified_by);
292b528cefcSMark Murray     ret = krb5_425_conv_principal(pd->context, p->mod_name, p->mod_instance,
293b528cefcSMark Murray 				  realm, &ent.modified_by->principal);
294b528cefcSMark Murray     if(ret){
295b528cefcSMark Murray 	krb5_warn(pd->context, ret, "%s.%s@%s", p->name, p->instance, realm);
296b528cefcSMark Murray 	ent.modified_by->principal = NULL;
297b528cefcSMark Murray 	ret = 0;
298b528cefcSMark Murray 	goto out;
299b528cefcSMark Murray     }
300b528cefcSMark Murray     ent.modified_by->time = p->mod_date;
301b528cefcSMark Murray 
302b528cefcSMark Murray     ent.flags.forwardable = 1;
303b528cefcSMark Murray     ent.flags.renewable = 1;
304b528cefcSMark Murray     ent.flags.proxiable = 1;
305b528cefcSMark Murray     ent.flags.postdate = 1;
306b528cefcSMark Murray     ent.flags.client = 1;
307b528cefcSMark Murray     ent.flags.server = 1;
308b528cefcSMark Murray 
309b528cefcSMark Murray     /* special case password changing service */
310b528cefcSMark Murray     if(strcmp(p->name, "changepw") == 0 &&
311b528cefcSMark Murray        strcmp(p->instance, "kerberos") == 0) {
312b528cefcSMark Murray 	ent.flags.forwardable = 0;
313b528cefcSMark Murray 	ent.flags.renewable = 0;
314b528cefcSMark Murray 	ent.flags.proxiable = 0;
315b528cefcSMark Murray 	ent.flags.postdate = 0;
316b528cefcSMark Murray 	ent.flags.initial = 1;
317b528cefcSMark Murray 	ent.flags.change_pw = 1;
318b528cefcSMark Murray     }
319b528cefcSMark Murray 
320b528cefcSMark Murray     ret = v5_prop(pd->context, NULL, &ent, pd);
321b528cefcSMark Murray 
322b528cefcSMark Murray     if (strcmp (p->name, "krbtgt") == 0
323b528cefcSMark Murray 	&& strcmp (realm, p->instance) != 0) {
324b528cefcSMark Murray 	krb5_free_principal (pd->context, ent.principal);
325b528cefcSMark Murray 	ret = krb5_425_conv_principal (pd->context, p->name,
326b528cefcSMark Murray 				       realm, p->instance,
327b528cefcSMark Murray 				       &ent.principal);
328b528cefcSMark Murray 	if (ret == 0)
329b528cefcSMark Murray 	    ret = v5_prop (pd->context, NULL, &ent, pd);
330b528cefcSMark Murray     }
331b528cefcSMark Murray 
332b528cefcSMark Murray   out:
333b528cefcSMark Murray     hdb_free_entry(pd->context, &ent);
334b528cefcSMark Murray     return ret;
335b528cefcSMark Murray }
336b528cefcSMark Murray 
3375e9cd1aeSAssar Westerlund #ifdef KRB4
338b528cefcSMark Murray #ifdef KASERVER_DB
339b528cefcSMark Murray 
340b528cefcSMark Murray #include "kadb.h"
341b528cefcSMark Murray 
342b528cefcSMark Murray /* read a `ka_entry' from `fd' at offset `pos' */
343b528cefcSMark Murray static void
344b528cefcSMark Murray read_block(krb5_context context, int fd, int32_t pos, void *buf, size_t len)
345b528cefcSMark Murray {
346b528cefcSMark Murray     krb5_error_code ret;
347b528cefcSMark Murray     if(lseek(fd, 64 + pos, SEEK_SET) == (off_t)-1)
348b528cefcSMark Murray 	krb5_err(context, 1, errno, "lseek(%u)", 64 + pos);
349b528cefcSMark Murray     ret = read(fd, buf, len);
350b528cefcSMark Murray     if(ret < 0)
351b528cefcSMark Murray 	krb5_err(context, 1, errno, "read(%u)", len);
352b528cefcSMark Murray     if(ret != len)
353b528cefcSMark Murray 	krb5_errx(context, 1, "read(%u) = %u", len, ret);
354b528cefcSMark Murray }
355b528cefcSMark Murray 
356b528cefcSMark Murray static int
357b528cefcSMark Murray ka_convert(struct prop_data *pd, int fd, struct ka_entry *ent,
358b528cefcSMark Murray 	   const char *cell)
359b528cefcSMark Murray {
360b528cefcSMark Murray     int32_t flags = ntohl(ent->flags);
361b528cefcSMark Murray     krb5_error_code ret;
362b528cefcSMark Murray     hdb_entry hdb;
363b528cefcSMark Murray 
364b528cefcSMark Murray     if(!kaspecials_flag
365b528cefcSMark Murray        && (flags & KAFNORMAL) == 0) /* remove special entries */
366b528cefcSMark Murray 	return 0;
367b528cefcSMark Murray     memset(&hdb, 0, sizeof(hdb));
368b528cefcSMark Murray     ret = krb5_425_conv_principal(pd->context, ent->name, ent->instance, realm,
369b528cefcSMark Murray 				  &hdb.principal);
370b528cefcSMark Murray     if(ret) {
371b528cefcSMark Murray 	krb5_warn(pd->context, ret,
372b528cefcSMark Murray 		  "krb5_425_conv_principal (%s.%s@%s)",
373b528cefcSMark Murray 		  ent->name, ent->instance, realm);
374b528cefcSMark Murray 	return 0;
375b528cefcSMark Murray     }
376b528cefcSMark Murray     hdb.kvno = ntohl(ent->kvno);
377b528cefcSMark Murray     hdb.keys.len = 3;
378b528cefcSMark Murray     hdb.keys.val = malloc(hdb.keys.len * sizeof(*hdb.keys.val));
379b528cefcSMark Murray     hdb.keys.val[0].mkvno = NULL;
380b528cefcSMark Murray     hdb.keys.val[0].salt = calloc(1, sizeof(*hdb.keys.val[0].salt));
3815e9cd1aeSAssar Westerlund     if (ka_use_null_salt) {
3825e9cd1aeSAssar Westerlund 	hdb.keys.val[0].salt->type = hdb_pw_salt;
3835e9cd1aeSAssar Westerlund 	hdb.keys.val[0].salt->salt.data = NULL;
3845e9cd1aeSAssar Westerlund 	hdb.keys.val[0].salt->salt.length = 0;
3855e9cd1aeSAssar Westerlund     } else {
386b528cefcSMark Murray 	hdb.keys.val[0].salt->type = hdb_afs3_salt;
387b528cefcSMark Murray 	hdb.keys.val[0].salt->salt.data = strdup(cell);
388b528cefcSMark Murray 	hdb.keys.val[0].salt->salt.length = strlen(cell);
3895e9cd1aeSAssar Westerlund     }
390b528cefcSMark Murray 
391b528cefcSMark Murray     hdb.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
392b528cefcSMark Murray     krb5_data_copy(&hdb.keys.val[0].key.keyvalue, ent->key, sizeof(ent->key));
393b528cefcSMark Murray     copy_Key(&hdb.keys.val[0], &hdb.keys.val[1]);
394b528cefcSMark Murray     hdb.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
395b528cefcSMark Murray     copy_Key(&hdb.keys.val[0], &hdb.keys.val[2]);
396b528cefcSMark Murray     hdb.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;
397b528cefcSMark Murray 
398b528cefcSMark Murray     ALLOC(hdb.max_life);
399b528cefcSMark Murray     *hdb.max_life = ntohl(ent->max_life);
400b528cefcSMark Murray 
4015e9cd1aeSAssar Westerlund     if(ntohl(ent->valid_end) != NEVERDATE && ntohl(ent->valid_end) != -1){
4025e9cd1aeSAssar Westerlund 	ALLOC(hdb.valid_end);
4035e9cd1aeSAssar Westerlund 	*hdb.valid_end = ntohl(ent->valid_end);
4045e9cd1aeSAssar Westerlund     }
4055e9cd1aeSAssar Westerlund 
4065e9cd1aeSAssar Westerlund     if (ntohl(ent->pw_change) != NEVERDATE &&
4075e9cd1aeSAssar Westerlund 	ent->pw_expire != 255 &&
4085e9cd1aeSAssar Westerlund 	ent->pw_expire != 0) {
409b528cefcSMark Murray 	ALLOC(hdb.pw_end);
4105e9cd1aeSAssar Westerlund 	*hdb.pw_end = ntohl(ent->pw_change)
4115e9cd1aeSAssar Westerlund 	    + 24 * 60 * 60 * ent->pw_expire;
412b528cefcSMark Murray     }
413b528cefcSMark Murray 
414b528cefcSMark Murray     ret = krb5_make_principal(pd->context, &hdb.created_by.principal,
415b528cefcSMark Murray 			      realm,
416b528cefcSMark Murray 			      "kadmin",
417b528cefcSMark Murray 			      "hprop",
418b528cefcSMark Murray 			      NULL);
419b528cefcSMark Murray     hdb.created_by.time = time(NULL);
420b528cefcSMark Murray 
421b528cefcSMark Murray     if(ent->mod_ptr){
422b528cefcSMark Murray 	struct ka_entry mod;
423b528cefcSMark Murray 	ALLOC(hdb.modified_by);
424b528cefcSMark Murray 	read_block(pd->context, fd, ntohl(ent->mod_ptr), &mod, sizeof(mod));
425b528cefcSMark Murray 
426b528cefcSMark Murray 	krb5_425_conv_principal(pd->context, mod.name, mod.instance, realm,
427b528cefcSMark Murray 				&hdb.modified_by->principal);
428b528cefcSMark Murray 	hdb.modified_by->time = ntohl(ent->mod_time);
429b528cefcSMark Murray 	memset(&mod, 0, sizeof(mod));
430b528cefcSMark Murray     }
431b528cefcSMark Murray 
432b528cefcSMark Murray     hdb.flags.forwardable = 1;
433b528cefcSMark Murray     hdb.flags.renewable = 1;
434b528cefcSMark Murray     hdb.flags.proxiable = 1;
435b528cefcSMark Murray     hdb.flags.postdate = 1;
436b528cefcSMark Murray     /* XXX - AFS 3.4a creates krbtgt.REALMOFCELL as NOTGS+NOSEAL */
437b528cefcSMark Murray     if (strcmp(ent->name, "krbtgt") == 0 &&
438b528cefcSMark Murray 	(flags & (KAFNOTGS|KAFNOSEAL)) == (KAFNOTGS|KAFNOSEAL))
439b528cefcSMark Murray 	flags &= ~(KAFNOTGS|KAFNOSEAL);
440b528cefcSMark Murray 
441b528cefcSMark Murray     hdb.flags.client = (flags & KAFNOTGS) == 0;
442b528cefcSMark Murray     hdb.flags.server = (flags & KAFNOSEAL) == 0;
443b528cefcSMark Murray 
444b528cefcSMark Murray     ret = v5_prop(pd->context, NULL, &hdb, pd);
445b528cefcSMark Murray     hdb_free_entry(pd->context, &hdb);
446b528cefcSMark Murray     return ret;
447b528cefcSMark Murray }
448b528cefcSMark Murray 
449b528cefcSMark Murray static int
450b528cefcSMark Murray ka_dump(struct prop_data *pd, const char *file, const char *cell)
451b528cefcSMark Murray {
452b528cefcSMark Murray     struct ka_header header;
453b528cefcSMark Murray     int i;
454b528cefcSMark Murray     int fd = open(file, O_RDONLY);
455b528cefcSMark Murray 
456b528cefcSMark Murray     if(fd < 0)
457b528cefcSMark Murray 	krb5_err(pd->context, 1, errno, "open(%s)", file);
458b528cefcSMark Murray     read_block(pd->context, fd, 0, &header, sizeof(header));
459b528cefcSMark Murray     if(header.version1 != header.version2)
460b528cefcSMark Murray 	krb5_errx(pd->context, 1, "Version mismatch in header: %d/%d",
461b528cefcSMark Murray 		  ntohl(header.version1), ntohl(header.version2));
462b528cefcSMark Murray     if(ntohl(header.version1) != 5)
463b528cefcSMark Murray 	krb5_errx(pd->context, 1, "Unknown database version %d (expected 5)",
464b528cefcSMark Murray 		  ntohl(header.version1));
465b528cefcSMark Murray     for(i = 0; i < ntohl(header.hashsize); i++){
466b528cefcSMark Murray 	int32_t pos = ntohl(header.hash[i]);
467b528cefcSMark Murray 	while(pos){
468b528cefcSMark Murray 	    struct ka_entry ent;
469b528cefcSMark Murray 	    read_block(pd->context, fd, pos, &ent, sizeof(ent));
470b528cefcSMark Murray 	    ka_convert(pd, fd, &ent, cell);
471b528cefcSMark Murray 	    pos = ntohl(ent.next);
472b528cefcSMark Murray 	}
473b528cefcSMark Murray     }
474b528cefcSMark Murray     return 0;
475b528cefcSMark Murray }
476b528cefcSMark Murray 
477b528cefcSMark Murray #endif /* KASERVER_DB */
478b528cefcSMark Murray 
479b528cefcSMark Murray #endif /* KRB4 */
480b528cefcSMark Murray 
481b528cefcSMark Murray 
482b528cefcSMark Murray struct getargs args[] = {
483b528cefcSMark Murray     { "master-key", 'm', arg_string, &mkeyfile, "v5 master key file", "file" },
484b528cefcSMark Murray     { "database", 'd',	arg_string, &database, "database", "file" },
4855e9cd1aeSAssar Westerlund     { "source",   0,	arg_string, &source_type, "type of database to read",
4865e9cd1aeSAssar Westerlund       "heimdal"
4875e9cd1aeSAssar Westerlund       "|mit-dump"
4885e9cd1aeSAssar Westerlund       "|krb4-dump"
489b528cefcSMark Murray #ifdef KRB4
4905e9cd1aeSAssar Westerlund       "|krb4-db"
491b528cefcSMark Murray #ifdef KASERVER_DB
4925e9cd1aeSAssar Westerlund       "|kaserver"
4935e9cd1aeSAssar Westerlund #endif
4945e9cd1aeSAssar Westerlund #endif
4955e9cd1aeSAssar Westerlund     },
4965e9cd1aeSAssar Westerlund 
4975e9cd1aeSAssar Westerlund #ifdef KRB4
4985e9cd1aeSAssar Westerlund     { "v4-db",    '4',	arg_flag, &v4_db },
4995e9cd1aeSAssar Westerlund #endif
5005e9cd1aeSAssar Westerlund     { "v4-realm", 'r',  arg_string, &realm, "v4 realm to use" },
5015e9cd1aeSAssar Westerlund #ifdef KASERVER_DB
5025e9cd1aeSAssar Westerlund     { "ka-db",	  'K',  arg_flag, &ka_db },
503b528cefcSMark Murray     { "cell",	  'c',  arg_string, &afs_cell, "name of AFS cell" },
504b528cefcSMark Murray     { "kaspecials", 'S', arg_flag,   &kaspecials_flag, "dump KASPECIAL keys"},
505b528cefcSMark Murray #endif
506b528cefcSMark Murray     { "keytab",   'k',	arg_string, &ktname, "keytab to use for authentication", "keytab" },
5075e9cd1aeSAssar Westerlund     { "v5-realm", 'R',  arg_string, &local_realm, "v5 realm to use" },
508b528cefcSMark Murray     { "decrypt",  'D',  arg_flag,   &decrypt_flag,   "decrypt keys" },
509b528cefcSMark Murray     { "encrypt",  'E',  arg_flag,   &encrypt_flag,   "encrypt keys" },
510b528cefcSMark Murray     { "stdout",	  'n',  arg_flag,   &to_stdout, "dump to stdout" },
511b528cefcSMark Murray     { "verbose",  'v',	arg_flag, &verbose_flag },
512b528cefcSMark Murray     { "version",   0,	arg_flag, &version_flag },
513b528cefcSMark Murray     { "help",     'h',	arg_flag, &help_flag }
514b528cefcSMark Murray };
515b528cefcSMark Murray 
516b528cefcSMark Murray static int num_args = sizeof(args) / sizeof(args[0]);
517b528cefcSMark Murray 
518b528cefcSMark Murray static void
519b528cefcSMark Murray usage(int ret)
520b528cefcSMark Murray {
521b528cefcSMark Murray     arg_printusage (args, num_args, NULL, "host ...");
522b528cefcSMark Murray     exit (ret);
523b528cefcSMark Murray }
524b528cefcSMark Murray 
525b528cefcSMark Murray static void
526b528cefcSMark Murray get_creds(krb5_context context, krb5_ccache *cache)
527b528cefcSMark Murray {
528b528cefcSMark Murray     krb5_keytab keytab;
529b528cefcSMark Murray     krb5_principal client;
530b528cefcSMark Murray     krb5_error_code ret;
531b528cefcSMark Murray     krb5_get_init_creds_opt init_opts;
532b528cefcSMark Murray     krb5_preauthtype preauth = KRB5_PADATA_ENC_TIMESTAMP;
533b528cefcSMark Murray     krb5_creds creds;
534b528cefcSMark Murray 
5355e9cd1aeSAssar Westerlund     ret = krb5_kt_register(context, &hdb_kt_ops);
5365e9cd1aeSAssar Westerlund     if(ret) krb5_err(context, 1, ret, "krb5_kt_register");
5375e9cd1aeSAssar Westerlund 
538b528cefcSMark Murray     ret = krb5_kt_resolve(context, ktname, &keytab);
539b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve");
540b528cefcSMark Murray 
541b528cefcSMark Murray     ret = krb5_make_principal(context, &client, NULL,
542b528cefcSMark Murray 			      "kadmin", HPROP_NAME, NULL);
543b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_make_principal");
544b528cefcSMark Murray 
545b528cefcSMark Murray     krb5_get_init_creds_opt_init(&init_opts);
546b528cefcSMark Murray     krb5_get_init_creds_opt_set_preauth_list(&init_opts, &preauth, 1);
547b528cefcSMark Murray 
548b528cefcSMark Murray     ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, NULL, &init_opts);
549b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds");
550b528cefcSMark Murray 
551b528cefcSMark Murray     ret = krb5_kt_close(context, keytab);
552b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_kt_close");
553b528cefcSMark Murray 
554b528cefcSMark Murray     ret = krb5_cc_gen_new(context, &krb5_mcc_ops, cache);
555b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_cc_gen_new");
556b528cefcSMark Murray 
557b528cefcSMark Murray     ret = krb5_cc_initialize(context, *cache, client);
558b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize");
559b528cefcSMark Murray 
560b528cefcSMark Murray     ret = krb5_cc_store_cred(context, *cache, &creds);
561b528cefcSMark Murray     if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred");
562b528cefcSMark Murray }
563b528cefcSMark Murray 
5645e9cd1aeSAssar Westerlund enum hprop_source {
5655e9cd1aeSAssar Westerlund     HPROP_HEIMDAL = 1,
5665e9cd1aeSAssar Westerlund     HPROP_KRB4_DB,
5675e9cd1aeSAssar Westerlund     HPROP_KRB4_DUMP,
5685e9cd1aeSAssar Westerlund     HPROP_KASERVER,
5695e9cd1aeSAssar Westerlund     HPROP_MIT_DUMP
5705e9cd1aeSAssar Westerlund };
5715e9cd1aeSAssar Westerlund 
5725e9cd1aeSAssar Westerlund #define IS_TYPE_V4(X) ((X) == HPROP_KRB4_DB || (X) == HPROP_KRB4_DUMP || (X) == HPROP_KASERVER)
5735e9cd1aeSAssar Westerlund 
5745e9cd1aeSAssar Westerlund struct {
5755e9cd1aeSAssar Westerlund     int type;
5765e9cd1aeSAssar Westerlund     const char *name;
5775e9cd1aeSAssar Westerlund } types[] = {
5785e9cd1aeSAssar Westerlund     { HPROP_HEIMDAL,	"heimdal" },
5795e9cd1aeSAssar Westerlund     { HPROP_KRB4_DUMP,	"krb4-dump" },
5805e9cd1aeSAssar Westerlund #ifdef KRB4
5815e9cd1aeSAssar Westerlund     { HPROP_KRB4_DB,	"krb4-db" },
5825e9cd1aeSAssar Westerlund #ifdef KASERVER_DB
5835e9cd1aeSAssar Westerlund     { HPROP_KASERVER, 	"kaserver" },
5845e9cd1aeSAssar Westerlund #endif
5855e9cd1aeSAssar Westerlund #endif
5865e9cd1aeSAssar Westerlund     { HPROP_MIT_DUMP,	"mit-dump" }
5875e9cd1aeSAssar Westerlund };
5885e9cd1aeSAssar Westerlund 
5895e9cd1aeSAssar Westerlund static int
5905e9cd1aeSAssar Westerlund parse_source_type(const char *s)
5915e9cd1aeSAssar Westerlund {
5925e9cd1aeSAssar Westerlund     int i;
5935e9cd1aeSAssar Westerlund     for(i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
5945e9cd1aeSAssar Westerlund 	if(strstr(types[i].name, s) == types[i].name)
5955e9cd1aeSAssar Westerlund 	    return types[i].type;
5965e9cd1aeSAssar Westerlund     }
5975e9cd1aeSAssar Westerlund     return 0;
5985e9cd1aeSAssar Westerlund }
5995e9cd1aeSAssar Westerlund 
600b528cefcSMark Murray static void
601b528cefcSMark Murray iterate (krb5_context context,
602b528cefcSMark Murray 	 const char *database,
603b528cefcSMark Murray 	 const char *afs_cell,
604b528cefcSMark Murray 	 HDB *db,
6055e9cd1aeSAssar Westerlund 	 int type,
606b528cefcSMark Murray 	 struct prop_data *pd)
607b528cefcSMark Murray {
6085e9cd1aeSAssar Westerlund     int ret;
6095e9cd1aeSAssar Westerlund 
6105e9cd1aeSAssar Westerlund     switch(type) {
6115e9cd1aeSAssar Westerlund     case HPROP_KRB4_DUMP:
6125e9cd1aeSAssar Westerlund 	ret = v4_prop_dump(pd, database);
6135e9cd1aeSAssar Westerlund 	break;
614b528cefcSMark Murray #ifdef KRB4
6155e9cd1aeSAssar Westerlund     case HPROP_KRB4_DB:
6165e9cd1aeSAssar Westerlund 	ret = kerb_db_iterate ((k_iter_proc_t)kdb_prop, pd);
6175e9cd1aeSAssar Westerlund 	if(ret)
618b528cefcSMark Murray 	    krb5_errx(context, 1, "kerb_db_iterate: %s",
6195e9cd1aeSAssar Westerlund 		      krb_get_err_text(ret));
6205e9cd1aeSAssar Westerlund 	break;
621b528cefcSMark Murray #ifdef KASERVER_DB
6225e9cd1aeSAssar Westerlund     case HPROP_KASERVER:
6235e9cd1aeSAssar Westerlund 	ret = ka_dump(pd, database, afs_cell);
6245e9cd1aeSAssar Westerlund 	if(ret)
6255e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "ka_dump: %s", krb_get_err_text(ret));
6265e9cd1aeSAssar Westerlund 	break;
627b528cefcSMark Murray #endif
6285e9cd1aeSAssar Westerlund #endif /* KRB4 */
6295e9cd1aeSAssar Westerlund     case HPROP_MIT_DUMP:
6305e9cd1aeSAssar Westerlund 	ret = mit_prop_dump(pd, database);
6315e9cd1aeSAssar Westerlund 	if (ret)
6325e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "mit_prop_dump: %s",
6335e9cd1aeSAssar Westerlund 		      krb5_get_err_text(context, ret));
6345e9cd1aeSAssar Westerlund 	break;
6355e9cd1aeSAssar Westerlund     case HPROP_HEIMDAL:
6365e9cd1aeSAssar Westerlund 	ret = hdb_foreach(context, db, HDB_F_DECRYPT, v5_prop, pd);
637b528cefcSMark Murray 	if(ret)
638b528cefcSMark Murray 	    krb5_err(context, 1, ret, "hdb_foreach");
6395e9cd1aeSAssar Westerlund 	break;
640b528cefcSMark Murray     }
641b528cefcSMark Murray }
642b528cefcSMark Murray 
643b528cefcSMark Murray static int
6445e9cd1aeSAssar Westerlund dump_database (krb5_context context, int type,
645b528cefcSMark Murray 	       const char *database, const char *afs_cell,
646b528cefcSMark Murray 	       HDB *db)
647b528cefcSMark Murray {
6485e9cd1aeSAssar Westerlund     krb5_error_code ret;
649b528cefcSMark Murray     struct prop_data pd;
6505e9cd1aeSAssar Westerlund     krb5_data data;
651b528cefcSMark Murray 
652b528cefcSMark Murray     pd.context      = context;
653b528cefcSMark Murray     pd.auth_context = NULL;
654b528cefcSMark Murray     pd.sock         = STDOUT_FILENO;
655b528cefcSMark Murray 
6565e9cd1aeSAssar Westerlund     iterate (context, database, afs_cell, db, type, &pd);
6575e9cd1aeSAssar Westerlund     krb5_data_zero (&data);
6585e9cd1aeSAssar Westerlund     ret = krb5_write_message (context, &pd.sock, &data);
6595e9cd1aeSAssar Westerlund     if (ret)
6605e9cd1aeSAssar Westerlund 	krb5_err(context, 1, ret, "krb5_write_message");
6615e9cd1aeSAssar Westerlund 
662b528cefcSMark Murray     return 0;
663b528cefcSMark Murray }
664b528cefcSMark Murray 
665b528cefcSMark Murray static int
6665e9cd1aeSAssar Westerlund propagate_database (krb5_context context, int type,
667b528cefcSMark Murray 		    const char *database, const char *afs_cell,
668b528cefcSMark Murray 		    HDB *db, krb5_ccache ccache,
669b528cefcSMark Murray 		    int optind, int argc, char **argv)
670b528cefcSMark Murray {
671b528cefcSMark Murray     krb5_principal server;
672b528cefcSMark Murray     krb5_error_code ret;
673b528cefcSMark Murray     int i;
674b528cefcSMark Murray 
675b528cefcSMark Murray     for(i = optind; i < argc; i++){
676b528cefcSMark Murray 	krb5_auth_context auth_context;
677b528cefcSMark Murray 	int fd;
678b528cefcSMark Murray 	struct prop_data pd;
679b528cefcSMark Murray 	krb5_data data;
680b528cefcSMark Murray 
6815e9cd1aeSAssar Westerlund 	char *port, portstr[NI_MAXSERV];
6825e9cd1aeSAssar Westerlund 
6835e9cd1aeSAssar Westerlund 	port = strchr(argv[i], ':');
6845e9cd1aeSAssar Westerlund 	if(port == NULL) {
6855e9cd1aeSAssar Westerlund 	    snprintf(portstr, sizeof(portstr), "%u",
6865e9cd1aeSAssar Westerlund 		     ntohs(krb5_getportbyname (context, "hprop", "tcp",
6875e9cd1aeSAssar Westerlund 					       HPROP_PORT)));
6885e9cd1aeSAssar Westerlund 	    port = portstr;
6895e9cd1aeSAssar Westerlund 	} else
6905e9cd1aeSAssar Westerlund 	    *port++ = '\0';
6915e9cd1aeSAssar Westerlund 
6925e9cd1aeSAssar Westerlund 	fd = open_socket(context, argv[i], port);
693b528cefcSMark Murray 	if(fd < 0) {
694b528cefcSMark Murray 	    krb5_warn (context, errno, "connect %s", argv[i]);
695b528cefcSMark Murray 	    continue;
696b528cefcSMark Murray 	}
697b528cefcSMark Murray 
698b528cefcSMark Murray 	ret = krb5_sname_to_principal(context, argv[i],
699b528cefcSMark Murray 				      HPROP_NAME, KRB5_NT_SRV_HST, &server);
700b528cefcSMark Murray 	if(ret) {
701b528cefcSMark Murray 	    krb5_warn(context, ret, "krb5_sname_to_principal(%s)", argv[i]);
702b528cefcSMark Murray 	    close(fd);
703b528cefcSMark Murray 	    continue;
704b528cefcSMark Murray 	}
705b528cefcSMark Murray 
7065e9cd1aeSAssar Westerlund         if (local_realm) {
7075e9cd1aeSAssar Westerlund             krb5_realm my_realm;
7085e9cd1aeSAssar Westerlund             krb5_get_default_realm(context,&my_realm);
7095e9cd1aeSAssar Westerlund 
7105e9cd1aeSAssar Westerlund             krb5_princ_set_realm(context,server,&my_realm);
7115e9cd1aeSAssar Westerlund         }
7125e9cd1aeSAssar Westerlund 
713b528cefcSMark Murray 	auth_context = NULL;
714b528cefcSMark Murray 	ret = krb5_sendauth(context,
715b528cefcSMark Murray 			    &auth_context,
716b528cefcSMark Murray 			    &fd,
717b528cefcSMark Murray 			    HPROP_VERSION,
718b528cefcSMark Murray 			    NULL,
719b528cefcSMark Murray 			    server,
720b528cefcSMark Murray 			    AP_OPTS_MUTUAL_REQUIRED,
721b528cefcSMark Murray 			    NULL, /* in_data */
722b528cefcSMark Murray 			    NULL, /* in_creds */
723b528cefcSMark Murray 			    ccache,
724b528cefcSMark Murray 			    NULL,
725b528cefcSMark Murray 			    NULL,
726b528cefcSMark Murray 			    NULL);
727b528cefcSMark Murray 
728b528cefcSMark Murray 	if(ret) {
729b528cefcSMark Murray 	    krb5_warn(context, ret, "krb5_sendauth");
730b528cefcSMark Murray 	    close(fd);
731b528cefcSMark Murray 	    continue;
732b528cefcSMark Murray 	}
733b528cefcSMark Murray 
734b528cefcSMark Murray 	pd.context      = context;
735b528cefcSMark Murray 	pd.auth_context = auth_context;
736b528cefcSMark Murray 	pd.sock         = fd;
737b528cefcSMark Murray 
7385e9cd1aeSAssar Westerlund 	iterate (context, database, afs_cell, db, type, &pd);
739b528cefcSMark Murray 
7405e9cd1aeSAssar Westerlund 	krb5_data_zero (&data);
7415e9cd1aeSAssar Westerlund 	ret = krb5_write_priv_message(context, auth_context, &fd, &data);
742b528cefcSMark Murray 	if(ret)
7435e9cd1aeSAssar Westerlund 	    krb5_warn(context, ret, "krb5_write_priv_message");
744b528cefcSMark Murray 
7455e9cd1aeSAssar Westerlund 	ret = krb5_read_priv_message(context, auth_context, &fd, &data);
746b528cefcSMark Murray 	if(ret)
7475e9cd1aeSAssar Westerlund 	    krb5_warn(context, ret, "krb5_read_priv_message");
748b528cefcSMark Murray 	else
749b528cefcSMark Murray 	    krb5_data_free (&data);
750b528cefcSMark Murray 
751b528cefcSMark Murray 	krb5_auth_con_free(context, auth_context);
752b528cefcSMark Murray 	close(fd);
753b528cefcSMark Murray     }
754b528cefcSMark Murray     return 0;
755b528cefcSMark Murray }
756b528cefcSMark Murray 
7575e9cd1aeSAssar Westerlund #ifdef KRB4
7585e9cd1aeSAssar Westerlund 
7595e9cd1aeSAssar Westerlund static void
7605e9cd1aeSAssar Westerlund v4_get_masterkey (krb5_context context, char *database)
7615e9cd1aeSAssar Westerlund {
7625e9cd1aeSAssar Westerlund     int e;
7635e9cd1aeSAssar Westerlund 
7645e9cd1aeSAssar Westerlund     e = kerb_db_set_name (database);
7655e9cd1aeSAssar Westerlund     if(e)
7665e9cd1aeSAssar Westerlund 	krb5_errx(context, 1, "kerb_db_set_name: %s",
7675e9cd1aeSAssar Westerlund 		  krb_get_err_text(e));
7685e9cd1aeSAssar Westerlund     e = kdb_get_master_key(0, &mkey4, msched4);
7695e9cd1aeSAssar Westerlund     if(e)
7705e9cd1aeSAssar Westerlund 	krb5_errx(context, 1, "kdb_get_master_key: %s",
7715e9cd1aeSAssar Westerlund 		  krb_get_err_text(e));
7725e9cd1aeSAssar Westerlund     e = kdb_verify_master_key(&mkey4, msched4, NULL);
7735e9cd1aeSAssar Westerlund     if (e < 0)
7745e9cd1aeSAssar Westerlund 	krb5_errx(context, 1, "kdb_verify_master_key failed");
7755e9cd1aeSAssar Westerlund }
7765e9cd1aeSAssar Westerlund 
7775e9cd1aeSAssar Westerlund #endif
7785e9cd1aeSAssar Westerlund 
779b528cefcSMark Murray int
780b528cefcSMark Murray main(int argc, char **argv)
781b528cefcSMark Murray {
782b528cefcSMark Murray     krb5_error_code ret;
783b528cefcSMark Murray     krb5_context context;
784b528cefcSMark Murray     krb5_ccache ccache;
785b528cefcSMark Murray     HDB *db;
786b528cefcSMark Murray     int optind = 0;
787b528cefcSMark Murray 
7885e9cd1aeSAssar Westerlund     int type = 0;
7895e9cd1aeSAssar Westerlund 
790b528cefcSMark Murray     set_progname(argv[0]);
791b528cefcSMark Murray 
792b528cefcSMark Murray     if(getarg(args, num_args, argc, argv, &optind))
793b528cefcSMark Murray 	usage(1);
794b528cefcSMark Murray 
795b528cefcSMark Murray     if(help_flag)
796b528cefcSMark Murray 	usage(0);
797b528cefcSMark Murray 
798b528cefcSMark Murray     if(version_flag){
799b528cefcSMark Murray 	print_version(NULL);
800b528cefcSMark Murray 	exit(0);
801b528cefcSMark Murray     }
802b528cefcSMark Murray 
803b528cefcSMark Murray     ret = krb5_init_context(&context);
804b528cefcSMark Murray     if(ret)
805b528cefcSMark Murray 	exit(1);
806b528cefcSMark Murray 
8075e9cd1aeSAssar Westerlund     if(local_realm)
8085e9cd1aeSAssar Westerlund 	krb5_set_default_realm(context, local_realm);
8095e9cd1aeSAssar Westerlund 
8105e9cd1aeSAssar Westerlund 
811b528cefcSMark Murray     if(encrypt_flag && decrypt_flag)
812b528cefcSMark Murray 	krb5_errx(context, 1,
8135e9cd1aeSAssar Westerlund 		  "only one of `--encrypt' and `--decrypt' is meaningful");
8145e9cd1aeSAssar Westerlund 
8155e9cd1aeSAssar Westerlund #ifdef KRB4
8165e9cd1aeSAssar Westerlund     if(v4_db) {
8175e9cd1aeSAssar Westerlund 	if(type != 0)
8185e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "more than one database type specified");
8195e9cd1aeSAssar Westerlund 	type = HPROP_KRB4_DB;
8205e9cd1aeSAssar Westerlund     }
8215e9cd1aeSAssar Westerlund #ifdef KASERVER_DB
8225e9cd1aeSAssar Westerlund     if(ka_db) {
8235e9cd1aeSAssar Westerlund 	if(type != 0)
8245e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "more than one database type specified");
8255e9cd1aeSAssar Westerlund 	type = HPROP_KASERVER;
8265e9cd1aeSAssar Westerlund     }
8275e9cd1aeSAssar Westerlund #endif
8285e9cd1aeSAssar Westerlund #endif
8295e9cd1aeSAssar Westerlund 
8305e9cd1aeSAssar Westerlund     if(source_type != NULL) {
8315e9cd1aeSAssar Westerlund 	if(type != 0)
8325e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "more than one database type specified");
8335e9cd1aeSAssar Westerlund 	type = parse_source_type(source_type);
8345e9cd1aeSAssar Westerlund 	if(type == 0)
8355e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "unknown source type `%s'", source_type);
8365e9cd1aeSAssar Westerlund     } else if(type == 0)
8375e9cd1aeSAssar Westerlund 	type = HPROP_HEIMDAL;
838b528cefcSMark Murray 
839b528cefcSMark Murray     if(!to_stdout)
840b528cefcSMark Murray 	get_creds(context, &ccache);
841b528cefcSMark Murray 
8425e9cd1aeSAssar Westerlund     if(decrypt_flag || encrypt_flag) {
843b528cefcSMark Murray 	ret = hdb_read_master_key(context, mkeyfile, &mkey5);
844b528cefcSMark Murray 	if(ret && ret != ENOENT)
845b528cefcSMark Murray 	    krb5_err(context, 1, ret, "hdb_read_master_key");
846b528cefcSMark Murray 	if(ret)
8475e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "No master key file found");
848b528cefcSMark Murray     }
849b528cefcSMark Murray 
850b528cefcSMark Murray #ifdef KRB4
8515e9cd1aeSAssar Westerlund     if (IS_TYPE_V4(type)) {
852b528cefcSMark Murray 	int e;
853b528cefcSMark Murray 
854b528cefcSMark Murray 	if (realm == NULL) {
855b528cefcSMark Murray 	    e = krb_get_lrealm(realm_buf, 1);
856b528cefcSMark Murray 	    if(e)
857b528cefcSMark Murray 		krb5_errx(context, 1, "krb_get_lrealm: %s",
858b528cefcSMark Murray 			  krb_get_err_text(e));
859b528cefcSMark Murray 	    realm = realm_buf;
860b528cefcSMark Murray 	}
861b528cefcSMark Murray     }
8625e9cd1aeSAssar Westerlund #endif
863b528cefcSMark Murray 
8645e9cd1aeSAssar Westerlund     switch(type) {
8655e9cd1aeSAssar Westerlund #ifdef KRB4
8665e9cd1aeSAssar Westerlund     case HPROP_KRB4_DB:
8675e9cd1aeSAssar Westerlund 	if (database == NULL)
8685e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "no database specified");
8695e9cd1aeSAssar Westerlund 	v4_get_masterkey (context, database);
8705e9cd1aeSAssar Westerlund 	break;
871b528cefcSMark Murray #ifdef KASERVER_DB
8725e9cd1aeSAssar Westerlund     case HPROP_KASERVER:
8735e9cd1aeSAssar Westerlund 	if (database == NULL)
8745e9cd1aeSAssar Westerlund 	    database = DEFAULT_DATABASE;
8755e9cd1aeSAssar Westerlund 	ka_use_null_salt = krb5_config_get_bool_default(context, NULL, FALSE,
8765e9cd1aeSAssar Westerlund 							"hprop",
8775e9cd1aeSAssar Westerlund 							"afs_uses_null_salt",
8785e9cd1aeSAssar Westerlund 							NULL);
8795e9cd1aeSAssar Westerlund 
8805e9cd1aeSAssar Westerlund 	break;
881b528cefcSMark Murray #endif
882b528cefcSMark Murray #endif /* KRB4 */
8835e9cd1aeSAssar Westerlund     case HPROP_KRB4_DUMP:
8845e9cd1aeSAssar Westerlund 	if (database == NULL)
8855e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "no dump file specified");
8865e9cd1aeSAssar Westerlund #ifdef KRB4
8875e9cd1aeSAssar Westerlund 	v4_get_masterkey (context, database);
8885e9cd1aeSAssar Westerlund #endif
8895e9cd1aeSAssar Westerlund 	break;
8905e9cd1aeSAssar Westerlund     case HPROP_MIT_DUMP:
8915e9cd1aeSAssar Westerlund 	if (database == NULL)
8925e9cd1aeSAssar Westerlund 	    krb5_errx(context, 1, "no dump file specified");
8935e9cd1aeSAssar Westerlund 	break;
8945e9cd1aeSAssar Westerlund     case HPROP_HEIMDAL:
895b528cefcSMark Murray 	ret = hdb_create (context, &db, database);
896b528cefcSMark Murray 	if(ret)
897b528cefcSMark Murray 	    krb5_err(context, 1, ret, "hdb_create: %s", database);
898b528cefcSMark Murray 	ret = db->open(context, db, O_RDONLY, 0);
899b528cefcSMark Murray 	if(ret)
900b528cefcSMark Murray 	    krb5_err(context, 1, ret, "db->open");
9015e9cd1aeSAssar Westerlund 	break;
9025e9cd1aeSAssar Westerlund     default:
9035e9cd1aeSAssar Westerlund 	krb5_errx(context, 1, "unknown dump type `%d'", type);
9045e9cd1aeSAssar Westerlund 	break;
905b528cefcSMark Murray     }
906b528cefcSMark Murray 
907b528cefcSMark Murray     if (to_stdout)
9085e9cd1aeSAssar Westerlund 	dump_database (context, type, database, afs_cell, db);
909b528cefcSMark Murray     else
9105e9cd1aeSAssar Westerlund 	propagate_database (context, type, database, afs_cell,
9115e9cd1aeSAssar Westerlund 			    db, ccache, optind, argc, argv);
912b528cefcSMark Murray     return 0;
913b528cefcSMark Murray }
914