2 * Copyright (c) 1997 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #define Principal Principal4
48 static int version_flag
;
50 static char *ktname
= HPROP_KEYTAB
;
51 static char *database
;
52 static char *mkeyfile
;
54 static int verbose_flag
;
55 static int encrypt_flag
;
56 static int decrypt_flag
;
57 static EncryptionKey mkey5
;
58 static krb5_data msched5
;
65 open_socket(krb5_context context
, const char *hostname
)
69 struct sockaddr_in sin
;
70 s
= socket(AF_INET
, SOCK_STREAM
, 0);
75 hp
= roken_gethostbyname(hostname
);
77 warnx("%s: %s", hostname
, hstrerror(h_errno
));
81 memset(&sin
, 0, sizeof(sin
));
82 sin
.sin_family
= AF_INET
;
83 sin
.sin_port
= krb5_getportbyname (context
, "hprop", "tcp", HPROP_PORT
);
84 memcpy(&sin
.sin_addr
, hp
->h_addr
, hp
->h_length
);
85 if(connect(s
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0){
95 krb5_auth_context auth_context
;
99 int hdb_entry2value(krb5_context
, hdb_entry
*, krb5_data
*);
101 static krb5_error_code
102 v5_prop(krb5_context context
, HDB
*db
, hdb_entry
*entry
, void *appdata
)
105 struct prop_data
*pd
= appdata
;
109 hdb_seal_keys(entry
, msched5
);
111 hdb_unseal_keys(entry
, msched5
);
113 ret
= hdb_entry2value(context
, entry
, &data
);
117 ret
= send_clear(context
, STDOUT_FILENO
, data
);
119 ret
= send_priv(context
, pd
->auth_context
, &data
, pd
->sock
);
120 krb5_data_free(&data
);
125 static des_cblock mkey4
;
126 static des_key_schedule msched4
;
127 static char realm
[REALM_SZ
];
130 v4_prop(void *arg
, Principal
*p
)
132 struct prop_data
*pd
= arg
;
136 memset(&ent
, 0, sizeof(ent
));
138 ret
= krb5_425_conv_principal(pd
->context
, p
->name
, p
->instance
, realm
,
141 krb5_warn(pd
->context
, ret
, "%s.%s@%s", p
->name
, p
->instance
, realm
);
147 krb5_unparse_name(pd
->context
, ent
.principal
, &s
);
148 krb5_warnx(pd
->context
, "%s.%s -> %s", p
->name
, p
->instance
, s
);
154 ent
.keys
.val
[0].mkvno
= p
->kdc_key_ver
;
155 ent
.keys
.val
[0].salt
= calloc(1, sizeof(*ent
.keys
.val
[0].salt
));
156 ent
.keys
.val
[0].salt
->type
= pa_pw_salt
;
157 ent
.kvno
= p
->key_version
;
158 ent
.keys
.val
[0].key
.keytype
= KEYTYPE_DES
;
159 krb5_data_alloc(&ent
.keys
.val
[0].key
.keyvalue
, sizeof(des_cblock
));
162 unsigned char *key
= ent
.keys
.val
[0].key
.keyvalue
.data
;
163 memcpy(key
, &p
->key_low
, 4);
164 memcpy(key
+ 4, &p
->key_high
, 4);
165 kdb_encrypt_key((des_cblock
*)key
, (des_cblock
*)key
, &mkey4
, msched4
, 0);
169 *ent
.max_life
= krb_life_to_time(0, p
->max_life
);
170 if(*ent
.max_life
== NEVERDATE
){
176 *ent
.pw_end
= p
->exp_date
;
177 ret
= krb5_make_principal(pd
->context
, &ent
.created_by
.principal
,
183 krb5_warn(pd
->context
, ret
, "krb5_make_principal");
187 ent
.created_by
.time
= time(NULL
);
188 ALLOC(ent
.modified_by
);
189 ret
= krb5_425_conv_principal(pd
->context
, p
->mod_name
, p
->mod_instance
,
190 realm
, &ent
.modified_by
->principal
);
192 krb5_warn(pd
->context
, ret
, "%s.%s@%s", p
->name
, p
->instance
, realm
);
193 ent
.modified_by
->principal
= NULL
;
197 ent
.modified_by
->time
= p
->mod_date
;
199 ent
.flags
.forwardable
= 1;
200 ent
.flags
.renewable
= 1;
201 ent
.flags
.proxiable
= 1;
202 ent
.flags
.postdate
= 1;
203 ent
.flags
.client
= 1;
204 ent
.flags
.server
= 1;
206 ret
= v5_prop(pd
->context
, NULL
, &ent
, pd
);
208 hdb_free_entry(pd
->context
, &ent
);
215 struct getargs args
[] = {
216 { "master-key", 'm', arg_string
, &mkeyfile
, "v5 master key file", "file" },
219 { "database", 'd', arg_string
, &database
, "database", "file" },
221 { "v4-db", '4', arg_flag
, &v4_db
, "use version 4 database" },
223 { "keytab", 'k', arg_string
, &ktname
, "keytab to use for authentication", "keytab" },
224 { "decrypt", 'D', arg_flag
, &decrypt_flag
, "decrypt keys" },
225 { "encrypt", 'E', arg_flag
, &encrypt_flag
, "encrypt keys" },
226 { "stdout", 'n', arg_flag
, &to_stdout
, "dump to stdout" },
227 { "verbose", 'v', arg_flag
, &verbose_flag
},
228 { "version", 0, arg_flag
, &version_flag
},
229 { "help", 'h', arg_flag
, &help_flag
}
232 static int num_args
= sizeof(args
) / sizeof(args
[0]);
237 arg_printusage (args
, num_args
, "host ...");
242 get_creds(krb5_context context
, krb5_ccache
*cache
)
245 krb5_principal client
;
247 krb5_get_init_creds_opt init_opts
;
248 krb5_preauthtype preauth
= KRB5_PADATA_ENC_TIMESTAMP
;
251 ret
= krb5_kt_resolve(context
, ktname
, &keytab
);
252 if(ret
) krb5_err(context
, 1, ret
, "krb5_kt_resolve");
254 ret
= krb5_make_principal(context
, &client
, NULL
,
255 "kadmin", HPROP_NAME
, NULL
);
256 if(ret
) krb5_err(context
, 1, ret
, "krb5_make_principal");
258 krb5_get_init_creds_opt_init(&init_opts
);
259 krb5_get_init_creds_opt_set_preauth_list(&init_opts
, &preauth
, 1);
261 ret
= krb5_get_init_creds_keytab(context
, &creds
, client
, keytab
, 0, NULL
, &init_opts
);
262 if(ret
) krb5_err(context
, 1, ret
, "krb5_get_init_creds");
264 ret
= krb5_kt_close(context
, keytab
);
265 if(ret
) krb5_err(context
, 1, ret
, "krb5_kt_close");
267 ret
= krb5_cc_gen_new(context
, &krb5_mcc_ops
, cache
);
268 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_gen_new");
270 ret
= krb5_cc_initialize(context
, *cache
, client
);
271 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_initialize");
273 ret
= krb5_cc_store_cred(context
, *cache
, &creds
);
274 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_store_cred");
277 int main(int argc
, char **argv
)
280 krb5_context context
;
281 krb5_auth_context ac
;
282 krb5_principal server
;
293 set_progname(argv
[0]);
295 if(getarg(args
, num_args
, argc
, argv
, &optind
))
302 fprintf(stderr
, "%s (%s)\n", __progname
, heimdal_version
);
306 ret
= krb5_init_context(&context
);
310 if(encrypt_flag
&& decrypt_flag
)
311 krb5_errx(context
, 1,
312 "Only one of `--encrypt' and `--decrypt' is meaningful");
315 get_creds(context
, &ccache
);
317 ret
= hdb_read_master_key(context
, mkeyfile
, &mkey5
);
318 if(ret
&& ret
!= ENOENT
)
319 krb5_err(context
, 1, ret
, "hdb_read_master_key");
321 if(encrypt_flag
|| decrypt_flag
)
322 krb5_errx(context
, 1, "No master key file found");
324 ret
= hdb_process_master_key(context
, mkey5
, &msched5
);
326 krb5_err(context
, 1, ret
, "hdb_process_master_key");
331 e
= kerb_db_set_name (database
);
332 if(e
) krb5_errx(context
, 1, "kerb_db_set_name: %s", krb_get_err_text(e
));
333 e
= kdb_get_master_key(0, &mkey4
, msched4
);
334 if(e
) krb5_errx(context
, 1, "kdb_get_master_key: %s", krb_get_err_text(e
));
335 e
= krb_get_lrealm(realm
, 1);
336 if(e
) krb5_errx(context
, 1, "krb_get_lrealm: %s", krb_get_err_text(e
));
340 ret
= hdb_create (context
, &db
, database
);
342 krb5_err(context
, 1, ret
, "hdb_create: %s", database
);
343 ret
= db
->open(context
, db
, O_RDONLY
, 0);
345 krb5_err(context
, 1, ret
, "db->open");
350 pd
.context
= context
;
351 pd
.auth_context
= ac
;
356 e
= kerb_db_iterate ((k_iter_proc_t
)v4_prop
, &pd
);
358 krb5_errx(context
, 1, "kerb_db_iterate: %s",
359 krb_get_err_text(e
));
363 ret
= hdb_foreach(context
, db
, v5_prop
, &pd
);
365 krb5_err(context
, 1, ret
, "hdb_foreach");
369 for(i
= optind
; i
< argc
; i
++){
370 fd
= open_socket(context
, argv
[i
]);
374 ret
= krb5_sname_to_principal(context
, argv
[i
],
375 HPROP_NAME
, KRB5_NT_SRV_HST
, &server
);
377 krb5_warn(context
, ret
, "krb5_sname_to_principal(%s)", argv
[i
]);
383 ret
= krb5_sendauth(context
,
389 AP_OPTS_MUTUAL_REQUIRED
,
398 krb5_warn(context
, ret
, "krb5_sendauth");
405 pd
.context
= context
;
406 pd
.auth_context
= ac
;
411 e
= kerb_db_iterate ((k_iter_proc_t
)v4_prop
, &pd
);
414 ret
= hdb_foreach(context
, db
, v5_prop
, &pd
);
417 krb5_warn(context
, ret
, "krb5_sendauth");
422 ret
= send_priv(context
, ac
, &data
, fd
);
427 ret
= recv_priv(context
, ac
, fd
, &data
);
428 if(ret
) krb5_warn(context
, ret
, "recv_priv");
430 krb5_data_free(&data
); /* XXX */
433 if(ret
) krb5_warn(context
, ret
, "send_priv");
434 krb5_auth_con_free(context
, ac
);