diff --git a/kdc/hprop.c b/kdc/hprop.c index e299ad5c4..aec31669f 100644 --- a/kdc/hprop.c +++ b/kdc/hprop.c @@ -32,6 +32,7 @@ */ #include "hprop.h" +#include "hdb-private.h" RCSID("$Id$"); @@ -47,35 +48,33 @@ static int decrypt_flag; static EncryptionKey mkey5; static krb5_data msched5; -static int v4_db; -static int ka_db; +static char *source_type; + static char *afs_cell; #ifdef KRB4 static char *realm; +static int v4_db; +static char *local_realm=NULL; #ifdef KASERVER_DB static int kaspecials_flag; +static int ka_db; #endif #endif static int -open_socket(krb5_context context, const char *hostname) +open_socket(krb5_context context, const char *hostname, const char *port) { struct addrinfo *ai, *a; struct addrinfo hints; int error; - char portstr[NI_MAXSERV]; memset (&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - snprintf (portstr, sizeof(portstr), - "%u", - ntohs(krb5_getportbyname (context, "hprop", "tcp", HPROP_PORT))); - - error = getaddrinfo (hostname, portstr, &hints, &ai); + error = getaddrinfo (hostname, port, &hints, &ai); if (error) { warnx ("%s: %s", hostname, gai_strerror(error)); return -1; @@ -121,7 +120,10 @@ v5_prop(krb5_context context, HDB *db, hdb_entry *entry, void *appdata) _hdb_unseal_keys_int(entry, 0, msched5); ret = hdb_entry2value(context, entry, &data); - if(ret) return ret; + if(ret) { + krb5_warn(context, ret, "hdb_entry2value"); + return ret; + } if(to_stdout) ret = send_clear(context, STDOUT_FILENO, data); @@ -136,7 +138,7 @@ static des_cblock mkey4; static des_key_schedule msched4; static char realm_buf[REALM_SZ]; -static int +int v4_prop(void *arg, Principal *p) { struct prop_data *pd = arg; @@ -170,7 +172,7 @@ v4_prop(void *arg, Principal *p) *(ent.keys.val[0].mkvno) = p->kdc_key_ver; /* XXX */ #endif ent.keys.val[0].salt = calloc(1, sizeof(*ent.keys.val[0].salt)); - ent.keys.val[0].salt->type = pa_pw_salt; + ent.keys.val[0].salt->type = KRB5_PADATA_PW_SALT; ent.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5; krb5_data_alloc(&ent.keys.val[0].key.keyvalue, sizeof(des_cblock)); @@ -397,19 +399,31 @@ ka_dump(struct prop_data *pd, const char *file, const char *cell) struct getargs args[] = { { "master-key", 'm', arg_string, &mkeyfile, "v5 master key file", "file" }, -#ifdef KRB4 -#endif { "database", 'd', arg_string, &database, "database", "file" }, + { "source", 0, arg_string, &source_type, "type of database to read", + "heimdal" +#if 0 + "|mit-dump" +#endif #ifdef KRB4 - { "v4-db", '4', arg_flag, &v4_db, "use version 4 database" }, + "|krb4-db|krb4-dump" +#ifdef KASERVER_DB + "|kaserver" +#endif +#endif + }, + +#ifdef KRB4 + { "v4-db", '4', arg_flag, &v4_db }, { "v4-realm", 'r', arg_string, &realm, "v4 realm to use" }, #endif #ifdef KASERVER_DB - { "ka-db", 'K', arg_flag, &ka_db, "use kaserver database" }, + { "ka-db", 'K', arg_flag, &ka_db }, { "cell", 'c', arg_string, &afs_cell, "name of AFS cell" }, { "kaspecials", 'S', arg_flag, &kaspecials_flag, "dump KASPECIAL keys"}, #endif { "keytab", 'k', arg_string, &ktname, "keytab to use for authentication", "keytab" }, + { "v5-realm", 'R', arg_string, &local_realm, "v5 realm to use" }, { "decrypt", 'D', arg_flag, &decrypt_flag, "decrypt keys" }, { "encrypt", 'E', arg_flag, &encrypt_flag, "encrypt keys" }, { "stdout", 'n', arg_flag, &to_stdout, "dump to stdout" }, @@ -463,38 +477,83 @@ get_creds(krb5_context context, krb5_ccache *cache) if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); } +enum hprop_source { + HPROP_HEIMDAL = 1, + HPROP_KRB4_DB, + HPROP_KRB4_DUMP, + HPROP_KASERVER, + HPROP_MIT_DUMP +}; + +#define IS_TYPE_V4(X) ((X) == HPROP_KRB4_DB || (X) == HPROP_KRB4_DUMP || (X) == HPROP_KASERVER) + +struct { + int type; + const char *name; +} types[] = { + { HPROP_HEIMDAL, "heimdal" }, +#ifdef KRB4 + { HPROP_KRB4_DB, "krb4-db" }, + { HPROP_KRB4_DUMP, "krb4-dump" }, +#ifdef KASERVER_DB + { HPROP_KASERVER, "kaserver" }, +#endif +#endif + { HPROP_MIT_DUMP, "mit-dump" } +}; + +static int +parse_source_type(const char *s) +{ + int i; + for(i = 0; i < sizeof(types) / sizeof(types[0]); i++) { + if(strstr(types[i].name, s) == types[i].name) + return types[i].type; + } + return 0; +} + static void iterate (krb5_context context, const char *database, const char *afs_cell, HDB *db, - int v4_db, int ka_db, + int type, struct prop_data *pd) { + switch(type) { #ifdef KRB4 - if(v4_db) { + case HPROP_KRB4_DB: { int e = kerb_db_iterate ((k_iter_proc_t)v4_prop, pd); if(e) krb5_errx(context, 1, "kerb_db_iterate: %s", krb_get_err_text(e)); + break; + } + case HPROP_KRB4_DUMP: + v4_prop_dump(pd, database); + break; #ifdef KASERVER_DB - } else if(ka_db) { + case HPROP_KASERVER: { int e = ka_dump(pd, database, afs_cell); if(e) krb5_errx(context, 1, "ka_dump: %s", krb_get_err_text(e)); + break; + } #endif - } else -#endif - { +#endif /* KRB4 */ + case HPROP_HEIMDAL: { krb5_error_code ret = hdb_foreach(context, db, HDB_F_DECRYPT, v5_prop, pd); if(ret) krb5_err(context, 1, ret, "hdb_foreach"); + break; + } } } static int -dump_database (krb5_context context, int v4_db, int ka_db, +dump_database (krb5_context context, int type, const char *database, const char *afs_cell, HDB *db) { @@ -504,12 +563,12 @@ dump_database (krb5_context context, int v4_db, int ka_db, pd.auth_context = NULL; pd.sock = STDOUT_FILENO; - iterate (context, database, afs_cell, db, v4_db, ka_db, &pd); + iterate (context, database, afs_cell, db, type, &pd); return 0; } static int -propagate_database (krb5_context context, int v4_db, int ka_db, +propagate_database (krb5_context context, int type, const char *database, const char *afs_cell, HDB *db, krb5_ccache ccache, int optind, int argc, char **argv) @@ -524,7 +583,18 @@ propagate_database (krb5_context context, int v4_db, int ka_db, struct prop_data pd; krb5_data data; - fd = open_socket(context, argv[i]); + char *port, portstr[NI_MAXSERV]; + + port = strchr(argv[i], ':'); + if(port == NULL) { + snprintf(portstr, sizeof(portstr), "%u", + ntohs(krb5_getportbyname (context, "hprop", "tcp", + HPROP_PORT))); + port = portstr; + } else + *port++ = '\0'; + + fd = open_socket(context, argv[i], port); if(fd < 0) { krb5_warn (context, errno, "connect %s", argv[i]); continue; @@ -537,6 +607,13 @@ propagate_database (krb5_context context, int v4_db, int ka_db, close(fd); continue; } + + if (local_realm) { + krb5_realm my_realm; + krb5_get_default_realm(context,&my_realm); + + krb5_princ_set_realm(context,server,&my_realm); + } auth_context = NULL; ret = krb5_sendauth(context, @@ -563,8 +640,7 @@ propagate_database (krb5_context context, int v4_db, int ka_db, pd.auth_context = auth_context; pd.sock = fd; - iterate (context, database, afs_cell, db, - v4_db, ka_db, &pd); + iterate (context, database, afs_cell, db, type, &pd); data.data = NULL; data.length = 0; @@ -593,6 +669,8 @@ main(int argc, char **argv) HDB *db; int optind = 0; + int type = 0; + set_progname(argv[0]); if(getarg(args, num_args, argc, argv, &optind)) @@ -610,9 +688,37 @@ main(int argc, char **argv) if(ret) exit(1); + if(local_realm) + krb5_set_default_realm(context, local_realm); + + if(encrypt_flag && decrypt_flag) krb5_errx(context, 1, - "Only one of `--encrypt' and `--decrypt' is meaningful"); + "only one of `--encrypt' and `--decrypt' is meaningful"); + +#ifdef KRB4 + if(v4_db) { + if(type != 0) + krb5_errx(context, 1, "more than one database type specified"); + type = HPROP_KRB4_DB; + } +#ifdef KASERVER_DB + if(ka_db) { + if(type != 0) + krb5_errx(context, 1, "more than one database type specified"); + type = HPROP_KRB4_DB; + } +#endif +#endif + + if(source_type != NULL) { + if(type != 0) + krb5_errx(context, 1, "more than one database type specified"); + type = parse_source_type(source_type); + if(type == 0) + krb5_errx(context, 1, "unknown source type `%s'", source_type); + } else if(type == 0) + type = HPROP_HEIMDAL; if(!to_stdout) get_creds(context, &ccache); @@ -630,11 +736,7 @@ main(int argc, char **argv) } #ifdef KRB4 - if (v4_db -#ifdef KASERVER_DB - || ka_db -#endif -) { + if (IS_TYPE_V4(type)) { int e; if (realm == NULL) { @@ -646,7 +748,7 @@ main(int argc, char **argv) } } - if(v4_db) { + if(type == HPROP_KRB4_DB) { int e = kerb_db_set_name (database); if(e) krb5_errx(context, 1, "kerb_db_set_name: %s", @@ -655,30 +757,29 @@ main(int argc, char **argv) if(e) krb5_errx(context, 1, "kdb_get_master_key: %s", krb_get_err_text(e)); + } else if(type == HPROP_KRB4_DUMP) { + /* nothing to do */ } else #ifdef KASERVER_DB - if (ka_db) { + if (type == HPROP_KASERVER) { if (database == NULL) database = DEFAULT_DATABASE; } else #endif #endif /* KRB4 */ - { - ret = hdb_create (context, &db, database); - if(ret) - krb5_err(context, 1, ret, "hdb_create: %s", database); - ret = db->open(context, db, O_RDONLY, 0); - if(ret) - krb5_err(context, 1, ret, "db->open"); - } + { + ret = hdb_create (context, &db, database); + if(ret) + krb5_err(context, 1, ret, "hdb_create: %s", database); + ret = db->open(context, db, O_RDONLY, 0); + if(ret) + krb5_err(context, 1, ret, "db->open"); + } if (to_stdout) - dump_database (context, v4_db, ka_db, - database, afs_cell, db); + dump_database (context, type, database, afs_cell, db); else - propagate_database (context, v4_db, ka_db, - database, afs_cell, - db, ccache, - optind, argc, argv); + propagate_database (context, type, database, afs_cell, + db, ccache, optind, argc, argv); return 0; }