From: Greg Hudson Date: Tue, 25 Jan 2011 05:20:07 +0000 (+0000) Subject: Make principal renaming work in libkadm5srv by converting to explicit X-Git-Tag: krb5-1.10-alpha1~610 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1f649490ad49642906a0ad6083059e35a24988e8;p=krb5.git Make principal renaming work in libkadm5srv by converting to explicit salts as necessary. Add a principal rename command to the client. (The RPC infrastructure was already present.) Adapted from patches submitted by mdw@umich.edu and lha@apple.com. ticket: 6323 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24604 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c index ecac1af4c..38244bed9 100644 --- a/src/kadmin/cli/kadmin.c +++ b/src/kadmin/cli/kadmin.c @@ -645,6 +645,69 @@ cleanup: free(canon); } +void +kadmin_renameprinc(int argc, char *argv[]) +{ + kadm5_ret_t retval; + krb5_principal oprinc = NULL, nprinc = NULL; + char *ocanon = NULL, *ncanon = NULL; + char reply[5]; + + if (!(argc == 3 || (argc == 4 && !strcmp("-force", argv[1])))) { + fprintf(stderr, "usage: rename_principal [-force] old_principal " + "new_principal\n"); + return; + } + retval = kadmin_parse_name(argv[argc - 2], &oprinc); + if (retval) { + com_err("rename_principal", retval, + "while parsing old principal name"); + goto cleanup; + } + retval = kadmin_parse_name(argv[argc - 1], &nprinc); + if (retval) { + com_err("rename_principal", retval, + "while parsing new principal name"); + goto cleanup; + } + retval = krb5_unparse_name(context, oprinc, &ocanon); + if (retval) { + com_err("rename_principal", retval, + "while canonicalizing old principal"); + goto cleanup; + } + retval = krb5_unparse_name(context, nprinc, &ncanon); + if (retval) { + com_err("rename_principal", retval, + "while canonicalizing new principal"); + goto cleanup; + } + if (argc == 3) { + printf("Are you sure you want to rename the principal \"%s\" " + "to \"%s\"? (yes/no): ", ocanon, ncanon); + fgets(reply, sizeof(reply), stdin); + if (strcmp("yes\n", reply)) { + fprintf(stderr, "Principal \"%s\" not renamed\n", ocanon); + goto cleanup; + } + } + retval = kadm5_rename_principal(handle, oprinc, nprinc); + if (retval) { + com_err("rename_principal", retval, + "while renaming principal \"%s\" to \"%s\"", ocanon, ncanon); + goto cleanup; + } + printf("Principal \"%s\" renamed to \"%s\".\n" + "Make sure that you have removed the old principal from all ACLs " + "before reusing.\n", ocanon, ncanon); + +cleanup: + krb5_free_principal(context, nprinc); + krb5_free_principal(context, oprinc); + free(ncanon); + free(ocanon); +} + static void cpw_usage(const char *str) { diff --git a/src/kadmin/cli/kadmin.h b/src/kadmin/cli/kadmin.h index 66496687d..92e5faa7b 100644 --- a/src/kadmin/cli/kadmin.h +++ b/src/kadmin/cli/kadmin.h @@ -37,6 +37,7 @@ extern int quit (void); extern void kadmin_lock(int argc, char *argv[]); extern void kadmin_unlock(int argc, char *argv[]); extern void kadmin_delprinc(int argc, char *argv[]); +extern void kadmin_renameprinc(int argc, char *argv[]); extern void kadmin_cpw(int argc, char *argv[]); extern void kadmin_addprinc(int argc, char *argv[]); extern void kadmin_modprinc(int argc, char *argv[]); diff --git a/src/kadmin/cli/kadmin_ct.ct b/src/kadmin/cli/kadmin_ct.ct index 6228f95ad..86ac96e70 100644 --- a/src/kadmin/cli/kadmin_ct.ct +++ b/src/kadmin/cli/kadmin_ct.ct @@ -35,6 +35,9 @@ request kadmin_delprinc, "Delete principal", request kadmin_modprinc, "Modify principal", modify_principal, modprinc; +request kadmin_renameprinc, "Rename principal", + rename_principal, renprinc; + request kadmin_cpw, "Change password", change_password, cpw; diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index 696362ac6..9abb4e6d6 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -4,21 +4,14 @@ * * $Header$ */ -#include -#include +#include "k5-int.h" #include -#include #include #include -#include -#include #include "server_internal.h" -#include -#include #ifdef USE_PASSWORD_SERVER #include #include - #endif #include @@ -730,10 +723,12 @@ kadm5_ret_t kadm5_rename_principal(void *server_handle, krb5_principal source, krb5_principal target) { - krb5_db_entry *kdb; - osa_princ_ent_rec adb; - int ret, i; + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + int ret, i; kadm5_server_handle_t handle = server_handle; + krb5_int32 stype; + krb5_data sdata; CHECK_HANDLE(server_handle); @@ -750,14 +745,53 @@ kadm5_rename_principal(void *server_handle, if ((ret = kdb_get_entry(handle, source, &kdb, &adb))) return ret; - /* this is kinda gross, but unavoidable */ + /* Transform salts as necessary. */ + for (i = 0; i < kdb->n_key_data; i++) { + sdata = empty_data(); + if (kdb->key_data[i].key_data_ver > 1) + stype = kdb->key_data[i].key_data_type[1]; + else + stype = KRB5_KDB_SALTTYPE_NORMAL; - for (i=0; in_key_data; i++) { - if ((kdb->key_data[i].key_data_ver == 1) || - (kdb->key_data[i].key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)) { + /* For salt types which compute a salt from the principal name, compute + * the salt based on the old principal name into sdata. */ + switch (stype) { + case KRB5_KDB_SALTTYPE_NORMAL: + ret = krb5_principal2salt(handle->context, kdb->princ, &sdata); + if (ret) + goto done; + break; + case KRB5_KDB_SALTTYPE_NOREALM: + krb5_principal2salt_norealm(handle->context, kdb->princ, &sdata); + if (ret) + goto done; + break; + case KRB5_KDB_SALTTYPE_ONLYREALM: + ret = alloc_data(&sdata, kdb->princ->realm.length); + if (ret) + goto done; + memcpy(sdata.data, kdb->princ->realm.data, + kdb->princ->realm.length); + break; + case KRB5_KDB_SALTTYPE_SPECIAL: + case KRB5_KDB_SALTTYPE_V4: + case KRB5_KDB_SALTTYPE_AFS3: + /* Don't compute a new salt. Assume the realm doesn't change for + * V4 and AFS3. */ + break; + default: + /* We don't recognize this salt type. Be conservative. */ ret = KADM5_NO_RENAME_SALT; goto done; } + /* If we computed a salt, store it as an explicit salt. */ + if (sdata.data != NULL) { + kdb->key_data[i].key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL; + free(kdb->key_data[i].key_data_contents[1]); + kdb->key_data[i].key_data_contents[1] = (krb5_octet *)sdata.data; + kdb->key_data[i].key_data_length[1] = sdata.length; + kdb->key_data[i].key_data_ver = 2; + } } kadm5_free_principal(handle->context, kdb->princ); diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index 964da6ee1..987238cfb 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -67,6 +67,7 @@ check-pytests:: $(RUNPYTEST) $(srcdir)/t_kadm5_hook.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_keyrollover.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_renew.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_renprinc.py $(PYTESTFLAGS) clean:: $(RM) kdc.conf diff --git a/src/tests/t_renprinc.py b/src/tests/t_renprinc.py new file mode 100644 index 000000000..d4ad902aa --- /dev/null +++ b/src/tests/t_renprinc.py @@ -0,0 +1,46 @@ +# Copyright (C) 2011 by the Massachusetts Institute of Technology. +# All rights reserved. + +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +#!/usr/bin/python +from k5test import * + +enctype = "aes128-cts" + +realm = K5Realm(create_host=False, create_user=False, start_kadmind=False) +salttypes = ('normal', 'v4', 'norealm', 'onlyrealm') + +# For a variety of salt types, test that we can rename a principal and +# still get tickets with the same password. +for st in salttypes: + realm.run_kadminl('addprinc -e %s:%s -pw %s %s' % + (enctype, st, password(st), st)) + realm.kinit(st, password(st)) + newprinc = 'new' + st + realm.run_kadminl('renprinc -force %s %s' % (st, newprinc)) + realm.kinit(newprinc, password(st)) + +# Rename the normal salt again to test renaming a principal with +# special salt type (which it will have after the first rename). +realm.run_kadminl('renprinc -force newnormal newnormal2') +realm.kinit('newnormal2', password('normal')) + +success('Principal renaming tests.')