2 * Copyright (c) 1997 - 2005 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. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #define KRB5_DEPRECATED /* uses v4 functions that will die */
38 static int version_flag
;
40 static const char *ktname
= HPROP_KEYTAB
;
41 static const char *database
;
42 static char *mkeyfile
;
44 static int verbose_flag
;
45 static int encrypt_flag
;
46 static int decrypt_flag
;
47 static hdb_master_key mkey5
;
49 static char *source_type
;
51 static char *local_realm
=NULL
;
54 open_socket(krb5_context context
, const char *hostname
, const char *port
)
56 struct addrinfo
*ai
, *a
;
57 struct addrinfo hints
;
60 memset (&hints
, 0, sizeof(hints
));
61 hints
.ai_socktype
= SOCK_STREAM
;
62 hints
.ai_protocol
= IPPROTO_TCP
;
64 if (krb5_config_get_bool(context
, NULL
, "libdefaults", "block_dns",
66 hints
.ai_flags
&= ~AI_CANONNAME
;
67 hints
.ai_flags
|= AI_NUMERICHOST
|AI_NUMERICSERV
;
69 error
= getaddrinfo (hostname
, port
, &hints
, &ai
);
71 warnx ("%s: %s", hostname
, gai_strerror(error
));
75 for (a
= ai
; a
!= NULL
; a
= a
->ai_next
) {
78 s
= socket (a
->ai_family
, a
->ai_socktype
, a
->ai_protocol
);
81 if (connect (s
, a
->ai_addr
, a
->ai_addrlen
) < 0) {
82 warn ("connect(%s)", hostname
);
89 warnx ("failed to contact %s", hostname
);
95 v5_prop(krb5_context context
, HDB
*db
, hdb_entry
*entry
, void *appdata
)
98 struct prop_data
*pd
= appdata
;
102 ret
= hdb_seal_keys_mkey(context
, entry
, mkey5
);
104 krb5_warn(context
, ret
, "hdb_seal_keys_mkey");
109 ret
= hdb_unseal_keys_mkey(context
, entry
, mkey5
);
111 krb5_warn(context
, ret
, "hdb_unseal_keys_mkey");
116 ret
= hdb_entry2value(context
, entry
, &data
);
118 krb5_warn(context
, ret
, "hdb_entry2value");
123 ret
= krb5_write_message(context
, &pd
->sock
, &data
);
125 ret
= krb5_write_priv_message(context
, pd
->auth_context
,
127 krb5_data_free(&data
);
131 struct getargs args
[] = {
132 { "master-key", 'm', arg_string
, &mkeyfile
, "v5 master key file", "file" },
133 { "database", 'd', arg_string
, rk_UNCONST(&database
), "database", "file" },
134 { "source", 0, arg_string
, &source_type
, "type of database to read",
139 { "keytab", 'k', arg_string
, rk_UNCONST(&ktname
),
140 "keytab to use for authentication", "keytab" },
141 { "v5-realm", 'R', arg_string
, &local_realm
, "v5 realm to use", NULL
},
142 { "decrypt", 'D', arg_flag
, &decrypt_flag
, "decrypt keys", NULL
},
143 { "encrypt", 'E', arg_flag
, &encrypt_flag
, "encrypt keys", NULL
},
144 { "stdout", 'n', arg_flag
, &to_stdout
, "dump to stdout", NULL
},
145 { "verbose", 'v', arg_flag
, &verbose_flag
, NULL
, NULL
},
146 { "version", 0, arg_flag
, &version_flag
, NULL
, NULL
},
147 { "help", 'h', arg_flag
, &help_flag
, NULL
, NULL
}
150 static int num_args
= sizeof(args
) / sizeof(args
[0]);
155 arg_printusage (args
, num_args
, NULL
, "[host[:port]] ...");
160 get_creds(krb5_context context
, krb5_ccache
*cache
)
163 krb5_principal client
;
165 krb5_get_init_creds_opt
*init_opts
;
166 krb5_preauthtype preauth
= KRB5_PADATA_ENC_TIMESTAMP
;
169 ret
= krb5_kt_register(context
, &hdb_get_kt_ops
);
170 if(ret
) krb5_err(context
, 1, ret
, "krb5_kt_register");
172 ret
= krb5_kt_resolve(context
, ktname
, &keytab
);
173 if(ret
) krb5_err(context
, 1, ret
, "krb5_kt_resolve");
175 ret
= krb5_make_principal(context
, &client
, NULL
,
176 "kadmin", HPROP_NAME
, NULL
);
177 if(ret
) krb5_err(context
, 1, ret
, "krb5_make_principal");
179 ret
= krb5_get_init_creds_opt_alloc(context
, &init_opts
);
180 if(ret
) krb5_err(context
, 1, ret
, "krb5_get_init_creds_opt_alloc");
181 krb5_get_init_creds_opt_set_preauth_list(init_opts
, &preauth
, 1);
183 ret
= krb5_get_init_creds_keytab(context
, &creds
, client
, keytab
, 0, NULL
, init_opts
);
184 if(ret
) krb5_err(context
, 1, ret
, "krb5_get_init_creds");
186 krb5_get_init_creds_opt_free(context
, init_opts
);
188 ret
= krb5_kt_close(context
, keytab
);
189 if(ret
) krb5_err(context
, 1, ret
, "krb5_kt_close");
191 ret
= krb5_cc_new_unique(context
, krb5_cc_type_memory
, NULL
, cache
);
192 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_new_unique");
194 ret
= krb5_cc_initialize(context
, *cache
, client
);
195 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_initialize");
197 krb5_free_principal(context
, client
);
199 ret
= krb5_cc_store_cred(context
, *cache
, &creds
);
200 if(ret
) krb5_err(context
, 1, ret
, "krb5_cc_store_cred");
202 krb5_free_cred_contents(context
, &creds
);
214 { HPROP_HEIMDAL
, "heimdal" },
215 { HPROP_MIT_DUMP
, "mit-dump" }
219 parse_source_type(const char *s
)
222 for(i
= 0; i
< sizeof(types
) / sizeof(types
[0]); i
++) {
223 if(strstr(types
[i
].name
, s
) == types
[i
].name
)
224 return types
[i
].type
;
230 iterate (krb5_context context
,
231 const char *database_name
,
234 struct prop_data
*pd
)
240 ret
= mit_prop_dump(pd
, database_name
);
242 krb5_warn(context
, ret
, "mit_prop_dump");
245 ret
= hdb_foreach(context
, db
, HDB_F_DECRYPT
, v5_prop
, pd
);
247 krb5_warn(context
, ret
, "hdb_foreach");
250 krb5_errx(context
, 1, "unknown prop type: %d", type
);
256 dump_database (krb5_context context
, int type
,
257 const char *database_name
, HDB
*db
)
263 pd
.context
= context
;
264 pd
.auth_context
= NULL
;
265 pd
.sock
= STDOUT_FILENO
;
267 ret
= iterate (context
, database_name
, db
, type
, &pd
);
269 krb5_errx(context
, 1, "iterate failure");
270 krb5_data_zero (&data
);
271 ret
= krb5_write_message (context
, &pd
.sock
, &data
);
273 krb5_err(context
, 1, ret
, "krb5_write_message");
279 propagate_database (krb5_context context
, int type
,
280 const char *database_name
,
281 HDB
*db
, krb5_ccache ccache
,
282 int optidx
, int argc
, char **argv
)
284 krb5_principal server
;
288 for(i
= optidx
; i
< argc
; i
++){
289 krb5_auth_context auth_context
;
294 char *port
, portstr
[NI_MAXSERV
];
295 char *host
= argv
[i
];
297 port
= strchr(host
, ':');
299 snprintf(portstr
, sizeof(portstr
), "%u",
300 ntohs(krb5_getportbyname (context
, "hprop", "tcp",
306 fd
= open_socket(context
, host
, port
);
309 krb5_warn (context
, errno
, "connect %s", host
);
313 ret
= krb5_sname_to_principal(context
, argv
[i
],
314 HPROP_NAME
, KRB5_NT_SRV_HST
, &server
);
317 krb5_warn(context
, ret
, "krb5_sname_to_principal(%s)", host
);
324 ret
= krb5_get_default_realm(context
,&my_realm
);
326 ret
= krb5_principal_set_realm(context
,server
,my_realm
);
327 krb5_xfree(my_realm
);
331 krb5_warn(context
, ret
, "unable to obtain default or set realm");
332 krb5_free_principal(context
, server
);
339 ret
= krb5_sendauth(context
,
345 AP_OPTS_MUTUAL_REQUIRED
| AP_OPTS_USE_SUBKEY
,
353 krb5_free_principal(context
, server
);
357 krb5_warn(context
, ret
, "krb5_sendauth (%s)", host
);
361 pd
.context
= context
;
362 pd
.auth_context
= auth_context
;
365 ret
= iterate (context
, database_name
, db
, type
, &pd
);
367 krb5_warnx(context
, "iterate to host %s failed", host
);
372 krb5_data_zero (&data
);
373 ret
= krb5_write_priv_message(context
, auth_context
, &fd
, &data
);
375 krb5_warn(context
, ret
, "krb5_write_priv_message");
380 ret
= krb5_read_priv_message(context
, auth_context
, &fd
, &data
);
382 krb5_warn(context
, ret
, "krb5_read_priv_message: %s", host
);
386 krb5_data_free (&data
);
389 krb5_auth_con_free(context
, auth_context
);
398 main(int argc
, char **argv
)
401 krb5_context context
;
402 krb5_ccache ccache
= NULL
;
408 setprogname(argv
[0]);
410 if(getarg(args
, num_args
, argc
, argv
, &optidx
))
421 ret
= krb5_init_context(&context
);
425 /* We may be reading an old database encrypted with a DES master key. */
426 ret
= krb5_allow_weak_crypto(context
, 1);
428 krb5_err(context
, 1, ret
, "krb5_allow_weak_crypto");
431 krb5_set_default_realm(context
, local_realm
);
433 if(encrypt_flag
&& decrypt_flag
)
434 krb5_errx(context
, 1,
435 "only one of `--encrypt' and `--decrypt' is meaningful");
437 if(source_type
!= NULL
) {
438 type
= parse_source_type(source_type
);
440 krb5_errx(context
, 1, "unknown source type `%s'", source_type
);
442 type
= HPROP_HEIMDAL
;
445 get_creds(context
, &ccache
);
447 if(decrypt_flag
|| encrypt_flag
) {
448 ret
= hdb_read_master_key(context
, mkeyfile
, &mkey5
);
449 if(ret
&& ret
!= ENOENT
)
450 krb5_err(context
, 1, ret
, "hdb_read_master_key");
452 krb5_errx(context
, 1, "No master key file found");
457 if (database
== NULL
)
458 krb5_errx(context
, 1, "no dump file specified");
461 ret
= hdb_create (context
, &db
, database
);
463 krb5_err(context
, 1, ret
, "hdb_create: %s", database
);
464 ret
= db
->hdb_open(context
, db
, O_RDONLY
, 0);
466 krb5_err(context
, 1, ret
, "db->hdb_open");
469 krb5_errx(context
, 1, "unknown dump type `%d'", type
);
474 exit_code
= dump_database (context
, type
, database
, db
);
476 exit_code
= propagate_database (context
, type
, database
,
477 db
, ccache
, optidx
, argc
, argv
);
480 krb5_cc_destroy(context
, ccache
);
483 (*db
->hdb_destroy
)(context
, db
);
485 krb5_free_context(context
);