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)
{
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[]);
request kadmin_modprinc, "Modify principal",
modify_principal, modprinc;
+request kadmin_renameprinc, "Rename principal",
+ rename_principal, renprinc;
+
request kadmin_cpw, "Change password",
change_password, cpw;
*
* $Header$
*/
-#include <assert.h>
-#include <sys/types.h>
+#include "k5-int.h"
#include <sys/time.h>
-#include <errno.h>
#include <kadm5/admin.h>
#include <kdb.h>
-#include <stdio.h>
-#include <string.h>
#include "server_internal.h"
-#include <stdarg.h>
-#include <stdlib.h>
#ifdef USE_PASSWORD_SERVER
#include <sys/wait.h>
#include <signal.h>
-
#endif
#include <krb5/kadm5_hook_plugin.h>
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);
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; i<kdb->n_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);
$(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
--- /dev/null
+# 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.')