summaryrefslogtreecommitdiffstats
path: root/src/kadmin/server/adm_funcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kadmin/server/adm_funcs.c')
-rw-r--r--src/kadmin/server/adm_funcs.c599
1 files changed, 599 insertions, 0 deletions
diff --git a/src/kadmin/server/adm_funcs.c b/src/kadmin/server/adm_funcs.c
new file mode 100644
index 000000000..b40a46938
--- /dev/null
+++ b/src/kadmin/server/adm_funcs.c
@@ -0,0 +1,599 @@
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America is assumed
+ * to 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. 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.
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ * Modify the Kerberos Database
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcsid_adm_funcs[] =
+"$Id$";
+#endif /* !lint & !SABER */
+
+#include <com_err.h>
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include <krb5/krb5.h>
+#include <krb5/ext-proto.h>
+#include <krb5/los-proto.h>
+#include <krb5/kdb.h>
+#include <krb5/kdb_dbm.h>
+#include <krb5/asn1.h>
+
+#include <krb5/adm_defs.h>
+#include "adm_extern.h"
+
+#include <krb5/adm_err.h>
+#include <krb5/errors.h>
+#include <krb5/kdb5_err.h>
+#include <krb5/krb5_err.h>
+
+struct saltblock {
+ int salttype;
+ krb5_data saltdata;
+};
+
+extern krb5_encrypt_block master_encblock;
+extern krb5_keyblock master_keyblock;
+
+#define norealm_salt(princ, retdata) krb5_principal2salt(&(princ)[1], retdata)
+
+struct mblock {
+ krb5_deltat max_life;
+ krb5_deltat max_rlife;
+ krb5_timestamp expiration;
+ krb5_flags flags;
+ krb5_kvno mkvno;
+} mblock = { /* XXX */
+ KRB5_KDB_MAX_LIFE,
+ KRB5_KDB_MAX_RLIFE,
+ KRB5_KDB_EXPIRATION,
+ KRB5_KDB_DEF_FLAGS,
+ 0
+};
+
+typedef unsigned char des_cblock[8];
+
+ /* krb5_kvno may be narrow */
+#include <krb5/widen.h>
+
+krb5_error_code adm_get_rnd_key PROTOTYPE((char *,
+ krb5_ticket *,
+ krb5_authenticator *,
+ krb5_principal,
+ int,
+ krb5_db_entry *));
+
+krb5_error_code adm_modify_kdb PROTOTYPE((char const *,
+ char const *,
+ krb5_const_principal,
+ const krb5_keyblock *,
+ const krb5_keyblock *,
+ int,
+ struct saltblock *,
+ struct saltblock *,
+ krb5_db_entry *));
+
+krb5_error_code adm_enter_pwd_key PROTOTYPE((char *,
+ char *,
+ krb5_const_principal,
+ krb5_const_principal,
+ int,
+ int,
+ char *,
+ krb5_db_entry *));
+
+krb5_error_code adm_negotiate_key PROTOTYPE((char const *,
+ krb5_ticket *,
+ char *));
+
+#include <krb5/narrow.h>
+
+
+krb5_kvno
+adm_princ_exists(cmdname, principal, entry, nprincs)
+char *cmdname;
+krb5_principal principal;
+krb5_db_entry *entry;
+int *nprincs;
+{
+ krb5_boolean more;
+ krb5_error_code retval;
+
+ if (retval = krb5_db_get_principal(principal, entry, nprincs, &more)) {
+ com_err("adm_princ_exists", retval,
+ "while attempting to verify principal's existence");
+ return(0);
+ }
+
+ if (! *nprincs) return(0);
+
+ return(*nprincs);
+}
+
+krb5_error_code
+adm_modify_kdb(DECLARG(char const *, cmdname),
+ DECLARG(char const *, newprinc),
+ DECLARG(krb5_const_principal, principal),
+ DECLARG(const krb5_keyblock *, key),
+ DECLARG(const krb5_keyblock *, alt_key),
+ DECLARG(int, req_type),
+ DECLARG(struct saltblock *, salt),
+ DECLARG(struct saltblock *, altsalt),
+ DECLARG(krb5_db_entry *, entry))
+OLDDECLARG(char const *, cmdname)
+OLDDECLARG(char const *, newprinc)
+OLDDECLARG(krb5_const_principal, principal)
+OLDDECLARG(const krb5_keyblock *, key)
+OLDDECLARG(const krb5_keyblock *, alt_key)
+OLDDECLARG(int, req_type)
+OLDDECLARG(struct saltblock *, salt)
+OLDDECLARG(struct saltblock *, altsalt)
+OLDDECLARG(krb5_db_entry *, entry)
+
+{
+ krb5_error_code retval;
+ int one = 1;
+
+ krb5_kvno KDB5_VERSION_NUM = 1;
+ krb5_deltat KDB5_MAX_TKT_LIFE = KRB5_KDB_MAX_LIFE;
+ krb5_deltat KDB5_MAX_REN_LIFE = KRB5_KDB_MAX_RLIFE;
+ krb5_timestamp KDB5_EXP_DATE = KRB5_KDB_EXPIRATION;
+ extern krb5_flags NEW_ATTRIBUTES;
+
+ if (key && key->length) {
+ retval = krb5_kdb_encrypt_key(&master_encblock,
+ key,
+ &entry->key);
+ if (retval) {
+ com_err("adm_modify_kdb", retval,
+ "while encrypting key for '%s'", newprinc);
+ return(KADM_NO_ENCRYPT);
+ }
+ }
+
+ if (alt_key && alt_key->length) {
+ retval = krb5_kdb_encrypt_key(&master_encblock,
+ alt_key,
+ &entry->alt_key);
+ if (retval) {
+ com_err("adm_modify_kdb", retval,
+ "while encrypting alt_key for '%s'", newprinc);
+ return(KADM_NO_ENCRYPT);
+ }
+ }
+
+ if (!req_type) { /* New entry - initialize */
+ memset((char *) &entry, 0, sizeof(entry));
+ entry->principal = (krb5_principal) principal;
+ entry->kvno = KDB5_VERSION_NUM;
+ entry->max_life = KDB5_MAX_TKT_LIFE;
+ entry->max_renewable_life = KDB5_MAX_REN_LIFE;
+ entry->mkvno = mblock.mkvno;
+ entry->expiration = KDB5_EXP_DATE;
+ entry->mod_name = master_princ;
+ } else { /* Modify existing entry */
+ entry->kvno++;
+#ifdef SANDIA
+ entry->attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+#endif
+ entry->mod_name = (krb5_principal) principal;
+ }
+
+ if (retval = krb5_timeofday(&entry->mod_date)) {
+ com_err("adm_modify_kdb", retval, "while fetching date");
+ memset((char *) entry->key.contents, 0, entry->key.length);
+ memset((char *) entry->alt_key.contents, 0, entry->alt_key.length);
+ if (entry->key.contents)
+ xfree(entry->key.contents);
+ if (entry->alt_key.contents)
+ xfree(entry->alt_key.contents);
+ return(KRB_ERR_GENERIC);
+ }
+
+ if (!req_type) {
+ if (salt->salttype == KRB5_KDB_SALTTYPE_V4) {
+ entry->attributes = (KRB5_KDB_DISALLOW_DUP_SKEY | NEW_ATTRIBUTES)
+#ifdef SANDIA
+ & ~KRB5_KDB_REQUIRES_PRE_AUTH & ~KRB5_KDB_REQUIRES_HW_AUTH
+#endif
+ ;
+ } else {
+ entry->attributes = NEW_ATTRIBUTES;
+ }
+
+#ifdef SANDIA
+ entry->last_pwd_change = entry->mod_date;
+ entry->last_success = entry->mod_date;
+ entry->fail_auth_count = 0;
+#endif
+
+ if (salt) {
+ entry->salt_type = salt->salttype;
+ entry->salt_length = salt->saltdata.length;
+ entry->salt = (krb5_octet *) salt->saltdata.data;
+ } else {
+ entry->salt_type = KRB5_KDB_SALTTYPE_NORMAL;
+ entry->salt_length = 0;
+ entry->salt = 0;
+ }
+
+ /* Set up version 4 alt key and alt salt info.....*/
+ if (altsalt) {
+ entry->alt_salt_type = altsalt->salttype;
+ entry->alt_salt_length = altsalt->saltdata.length;
+ entry->alt_salt = (krb5_octet *) altsalt->saltdata.data;
+ } else {
+ entry->alt_salt_type = KRB5_KDB_SALTTYPE_NORMAL;
+ entry->alt_salt_length = 0;
+ entry->alt_salt = 0;
+ }
+ } else {
+ if (retval = krb5_timeofday(&entry->last_pwd_change)) {
+ com_err("adm_modify_kdb", retval, "while fetching date");
+ memset((char *) entry->key.contents, 0, entry->key.length);
+ memset((char *) entry->alt_key.contents, 0, entry->alt_key.length);
+ if (entry->key.contents)
+ xfree(entry->key.contents);
+ if (entry->alt_key.contents)
+ xfree(entry->alt_key.contents);
+ return(5);
+ }
+ }
+
+ retval = krb5_db_put_principal(entry, &one);
+
+ memset((char *) entry->key.contents, 0, entry->key.length);
+ if (entry->key.contents)
+ xfree(entry->key.contents);
+
+ memset((char *) entry->alt_key.contents, 0, entry->alt_key.length);
+ if (entry->alt_key.contents)
+ xfree(entry->alt_key.contents);
+
+ if (retval) {
+ com_err("adm_modify_kdb", retval,
+ "while storing entry for '%s'\n", newprinc);
+ return(kdb5_err_base + retval);
+ }
+
+ if (one != 1)
+ com_err("adm_modify_kdb", 0, "entry not stored in database (unknown failure)");
+ return(0);
+}
+
+krb5_error_code
+adm_enter_pwd_key(DECLARG(char *, cmdname),
+ DECLARG(char *, newprinc),
+ DECLARG(krb5_const_principal, princ),
+ DECLARG(krb5_const_principal, string_princ),
+ DECLARG(int, req_type),
+ DECLARG(int, salttype),
+ DECLARG(char *, new_password),
+ DECLARG(krb5_db_entry *, entry))
+OLDDECLARG(char *, cmdname)
+OLDDECLARG(char *, newprinc)
+OLDDECLARG(krb5_const_principal, princ)
+OLDDECLARG(krb5_const_principal, string_princ)
+OLDDECLARG(int, req_type)
+OLDDECLARG(int, salttype)
+OLDDECLARG(char *, new_password)
+OLDDECLARG(krb5_db_entry *, entry)
+{
+ krb5_error_code retval;
+ krb5_keyblock tempkey;
+ krb5_data pwd;
+ struct saltblock salt;
+ struct saltblock altsalt;
+ krb5_keyblock alttempkey;
+ krb5_octet v4_keyptr[8];
+
+ pwd.data = new_password;
+ pwd.length = strlen((char *) new_password);
+
+ salt.salttype = salttype;
+
+ switch (salttype) {
+ case KRB5_KDB_SALTTYPE_NORMAL:
+ if (retval = krb5_principal2salt(string_princ, &salt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting principal to salt for '%s'", newprinc);
+ return(KRB_ERR_GENERIC);
+ }
+
+ altsalt.salttype = KRB5_KDB_SALTTYPE_V4;
+ altsalt.saltdata.data = 0;
+ altsalt.saltdata.length = 0;
+ break;
+
+ case KRB5_KDB_SALTTYPE_V4:
+ salt.saltdata.data = 0;
+ salt.saltdata.length = 0;
+ if (retval = krb5_principal2salt(string_princ, &altsalt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting principal to altsalt for '%s'", newprinc);
+ return(KRB_ERR_GENERIC);
+ }
+
+ altsalt.salttype = KRB5_KDB_SALTTYPE_NORMAL;
+ break;
+
+ case KRB5_KDB_SALTTYPE_NOREALM:
+ if (retval = norealm_salt(string_princ, &salt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting principal to salt for '%s'", newprinc);
+ return(KRB_ERR_GENERIC);
+ }
+
+ altsalt.salttype = KRB5_KDB_SALTTYPE_V4;
+ altsalt.saltdata.data = 0;
+ altsalt.saltdata.length = 0;
+ break;
+
+ case KRB5_KDB_SALTTYPE_ONLYREALM:
+ {
+ krb5_data *foo;
+ if (retval = krb5_copy_data(krb5_princ_realm(string_princ),
+ &foo)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting principal to salt for '%s'", newprinc);
+ return(KRB_ERR_GENERIC);
+ }
+
+ salt.saltdata = *foo;
+ xfree(foo);
+ altsalt.salttype = KRB5_KDB_SALTTYPE_V4;
+ altsalt.saltdata.data = 0;
+ altsalt.saltdata.length = 0;
+ break;
+ }
+
+ default:
+ com_err("adm_enter_pwd_key", 0,
+ "Don't know how to enter salt type %d", salttype);
+ return(KRB_ERR_GENERIC);
+ }
+
+ if (retval = krb5_string_to_key(&master_encblock,
+ master_keyblock.keytype,
+ &tempkey,
+ &pwd,
+ &salt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting password to alt_key for '%s'", newprinc);
+ memset((char *) new_password, 0, sizeof(new_password)); /* erase it */
+ xfree(salt.saltdata.data);
+ return(retval);
+ }
+
+ if (retval = krb5_string_to_key(&master_encblock,
+ master_keyblock.keytype,
+ &alttempkey,
+ &pwd,
+ &altsalt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting password to alt_key for '%s'", newprinc);
+ xfree(salt.saltdata.data);
+ free(entry->alt_key.contents);
+ memset((char *) new_password, 0, sizeof(new_password)); /* erase it */
+ return(retval);
+ }
+
+ memset((char *) new_password, 0, sizeof(new_password)); /* erase it */
+
+ retval = adm_modify_kdb("adm_enter_pwd_key",
+ newprinc,
+ princ,
+ &tempkey,
+ &alttempkey,
+ req_type,
+ &salt,
+ &altsalt,
+ entry);
+
+ memset((char *) tempkey.contents, 0, tempkey.length);
+ memset((char *) alttempkey.contents, 0, alttempkey.length);
+ if (entry->alt_key.contents)
+ free(entry->alt_key.contents);
+ return(retval);
+}
+
+krb5_error_code
+adm5_change(prog, newprinc, client_creds)
+char *prog;
+krb5_principal newprinc;
+krb5_ticket *client_creds;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+
+ krb5_error_code retval;
+ char *composite_name;
+ char new_passwd[ADM_MAX_PW_LENGTH + 1];
+
+ if (!(adm_princ_exists("adm5_change", newprinc,
+ &entry, &nprincs))) {
+ com_err("adm5_change", 0, "No principal exists!");
+ krb5_free_principal(newprinc);
+ return(1);
+ }
+
+ memset((char *) new_passwd, 0, ADM_MAX_PW_LENGTH + 1);
+
+ /* Negotiate for New Key */
+ if (retval = adm_negotiate_key("adm5_change", client_creds,
+ new_passwd)) {
+ krb5_db_free_principal(&entry, nprincs);
+ krb5_free_principal(newprinc);
+ return(1);
+ }
+
+ retval = krb5_unparse_name(newprinc, &composite_name);
+
+ if (entry.salt_type == KRB5_KDB_SALTTYPE_V4) {
+ entry.salt_type = KRB5_KDB_SALTTYPE_NORMAL;
+ entry.alt_salt_type = KRB5_KDB_SALTTYPE_V4;
+ com_err("adm5_change", 0, "Converting v4user to v5user");
+ }
+
+ retval = adm_enter_pwd_key("adm5_change",
+ composite_name,
+ newprinc,
+ newprinc,
+ 1, /* change */
+ KRB5_KDB_SALTTYPE_NORMAL,
+ new_passwd,
+ &entry);
+ (void) memset(new_passwd, 0, strlen(new_passwd));
+ krb5_free_principal(newprinc);
+ krb5_db_free_principal(&entry, nprincs);
+ free(composite_name);
+ return(retval);
+}
+
+#ifdef SANDIA
+krb5_error_code
+adm5_create_rnd(prog, change_princ, client_auth_data, client_creds)
+char *prog;
+krb5_principal change_princ;
+krb5_authenticator *client_auth_data;
+krb5_ticket *client_creds;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+
+ krb5_error_code retval;
+
+ if (!(adm_princ_exists("adm5_create_rnd",
+ change_princ,
+ &entry,
+ &nprincs))) {
+ com_err("adm5_create_rnd", 0, "No principal exists!");
+ krb5_free_principal(change_princ);
+ return(1);
+ }
+
+ if (retval = adm_get_rnd_key("adm5_create_rnd",
+ client_creds,
+ client_auth_data,
+ change_princ,
+ 1, /* change */
+ &entry)) {
+ krb5_db_free_principal(&entry, nprincs);
+ krb5_free_principal(change_princ);
+ return(retval);
+ }
+
+ krb5_free_principal(change_princ);
+ krb5_db_free_principal(&entry, nprincs);
+ return(0);
+}
+#endif
+#define MAXMSGSZ 255
+
+krb5_error_code
+adm_enter_rnd_pwd_key(DECLARG(char *, cmdname),
+ DECLARG(krb5_principal, change_princ),
+ DECLARG(int, req_type),
+ DECLARG(krb5_db_entry *, entry))
+OLDDECLARG(char *, cmdname)
+OLDDECLARG(krb5_principal, change_princ)
+OLDDECLARG(int, req_type)
+OLDDECLARG(krb5_db_entry *, entry)
+{
+ krb5_error_code retval;
+ krb5_keyblock *tempkey;
+ krb5_pointer master_random;
+ int salttype = KRB5_KDB_SALTTYPE_NORMAL;
+ struct saltblock salt;
+ char *principal_name;
+
+ salt.salttype = salttype;
+ entry->salt_type = salttype;
+
+ if (retval = krb5_init_random_key(&master_encblock,
+ &master_keyblock,
+ &master_random)) {
+ com_err("adm_enter_rnd_pwd_key", 0, "Unable to Initialize Random Key");
+ (void) krb5_finish_key(&master_encblock);
+ memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+ xfree(master_keyblock.contents);
+ goto finish;
+ }
+
+ /* Get Random Key */
+ if (retval = krb5_random_key(&master_encblock,
+ master_random,
+ &tempkey)) {
+ com_err("adm_enter_rnd_pwd_key", 0, "Unable to Obtain Random Key");
+ goto finish;
+ }
+
+ /* Tie the Random Key to the Principal */
+ if (retval = krb5_principal2salt(change_princ, &salt.saltdata)) {
+ com_err("adm_enter_rnd_pwd_key", 0, "Principal2salt Failure");
+ goto finish;
+ }
+
+ retval = krb5_unparse_name(change_princ, &principal_name);
+ if (retval)
+ return retval;
+
+ /* Modify Database */
+ retval = adm_modify_kdb("adm_enter_rnd_pwd_key",
+ principal_name,
+ change_princ,
+ tempkey,
+ tempkey,
+ req_type,
+ &salt,
+ &salt,
+ entry);
+ free(principal_name);
+
+ if (retval) {
+ com_err("adm_enter_rnd_pwd_key", 0, "Database Modification Failure");
+ retval = 2;
+ goto finish;
+ }
+
+ finish:
+
+ if(retval) {
+ memset((char *) tempkey->contents, 0, tempkey->length);
+ return(retval);
+ }
+
+ memset((char *) tempkey->contents, 0, tempkey->length);
+
+ return(0);
+}