krb5 commit: Add kadm5_setkey_principal_4 RPC to kadmin

Greg Hudson ghudson at mit.edu
Fri Feb 19 15:46:57 EST 2016


https://github.com/krb5/krb5/commit/1d4e83625f1c8cde7638702ab404f4594da3f062
commit 1d4e83625f1c8cde7638702ab404f4594da3f062
Author: Simo Sorce <simo at redhat.com>
Date:   Tue Dec 15 14:49:22 2015 -0500

    Add kadm5_setkey_principal_4 RPC to kadmin
    
    This new version of the RPC allows a user to set not only the
    keyblocks but also the kvno and the salts of a key.
    
    ticket: 8355 (new)

 src/kadmin/server/kadm_rpc_svc.c            |    7 +
 src/kadmin/server/server_stubs.c            |   61 +++++++++
 src/lib/kadm5/admin.h                       |   12 ++
 src/lib/kadm5/admin_xdr.h                   |    2 +
 src/lib/kadm5/clnt/client_principal.c       |   27 ++++
 src/lib/kadm5/clnt/client_rpc.c             |   15 ++
 src/lib/kadm5/clnt/libkadm5clnt_mit.exports |    3 +
 src/lib/kadm5/kadm_err.et                   |    1 +
 src/lib/kadm5/kadm_rpc.h                    |   14 ++
 src/lib/kadm5/kadm_rpc_xdr.c                |   35 +++++
 src/lib/kadm5/srv/libkadm5srv_mit.exports   |    2 +
 src/lib/kadm5/srv/svr_principal.c           |  195 +++++++++++++++++++++++++++
 12 files changed, 374 insertions(+), 0 deletions(-)

diff --git a/src/kadmin/server/kadm_rpc_svc.c b/src/kadmin/server/kadm_rpc_svc.c
index f4d2a7c..dee3938 100644
--- a/src/kadmin/server/kadm_rpc_svc.c
+++ b/src/kadmin/server/kadm_rpc_svc.c
@@ -58,6 +58,7 @@ void kadm_1(rqstp, transp)
 	  chpass3_arg chpass_principal3_2_arg;
 	  chrand3_arg chrand_principal3_2_arg;
 	  setkey3_arg setkey_principal3_2_arg;
+	  setkey4_arg setkey_principal4_2_arg;
      } argument;
      char *result;
      bool_t (*xdr_argument)(), (*xdr_result)();
@@ -222,6 +223,12 @@ void kadm_1(rqstp, transp)
 	  local = (char *(*)()) set_string_2_svc;
 	  break;
 
+     case SETKEY_PRINCIPAL4:
+	  xdr_argument = xdr_setkey4_arg;
+	  xdr_result = xdr_generic_ret;
+	  local = (char *(*)()) setkey_principal4_2_svc;
+	  break;
+
      default:
 	  krb5_klog_syslog(LOG_ERR, "Invalid KADM5 procedure number: %s, %d",
 			   client_addr(rqstp->rq_xprt), rqstp->rq_proc);
diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c
index 6ac797e..673cc2e 100644
--- a/src/kadmin/server/server_stubs.c
+++ b/src/kadmin/server/server_stubs.c
@@ -1100,6 +1100,67 @@ exit_func:
     return &ret;
 }
 
+generic_ret *
+setkey_principal4_2_svc(setkey4_arg *arg, struct svc_req *rqstp)
+{
+    static generic_ret              ret;
+    char                            *prime_arg;
+    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+    OM_uint32                       minor_stat;
+    kadm5_server_handle_t           handle;
+    const char                      *errmsg = NULL;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+        goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle)))
+        goto exit_func;
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+        ret.code = KADM5_FAILURE;
+        goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+        ret.code = KADM5_BAD_PRINCIPAL;
+        goto exit_func;
+    }
+
+    if (!(CHANGEPW_SERVICE(rqstp)) &&
+        kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_SETKEY,
+                           arg->princ, NULL)) {
+        ret.code = kadm5_setkey_principal_4((void *)handle, arg->princ,
+                                            arg->keepold, arg->key_data,
+                                            arg->n_key_data);
+    } else {
+        log_unauth("kadm5_setkey_principal", prime_arg, &client_name,
+                   &service_name, rqstp);
+        ret.code = KADM5_AUTH_SETKEY;
+    }
+
+    if (ret.code != KADM5_AUTH_SETKEY) {
+        if (ret.code != 0)
+            errmsg = krb5_get_error_message(handle->context, ret.code);
+
+        log_done("kadm5_setkey_principal", prime_arg, errmsg, &client_name,
+                 &service_name, rqstp);
+
+        if (errmsg != NULL)
+            krb5_free_error_message(handle->context, errmsg);
+    }
+
+    free(prime_arg);
+exit_func:
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+    free_server_handle(handle);
+    return &ret;
+}
+
 chrand_ret *
 chrand_principal_2_svc(chrand_arg *arg, struct svc_req *rqstp)
 {
diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h
index 73f2811..3beb7cf 100644
--- a/src/lib/kadm5/admin.h
+++ b/src/lib/kadm5/admin.h
@@ -279,6 +279,12 @@ typedef struct _kadm5_config_params {
     int                 iprop_resync_timeout;
 } kadm5_config_params;
 
+typedef struct _kadm5_key_data {
+    krb5_kvno       kvno;
+    krb5_keyblock   key;
+    krb5_keysalt    salt;
+} kadm5_key_data;
+
 /*
  * functions
  */
@@ -403,6 +409,12 @@ kadm5_ret_t    kadm5_setkey_principal_3(void *server_handle,
                                         krb5_keyblock *keyblocks,
                                         int n_keys);
 
+kadm5_ret_t    kadm5_setkey_principal_4(void *server_handle,
+                                        krb5_principal principal,
+                                        krb5_boolean keepold,
+                                        kadm5_key_data *key_data,
+                                        int n_key_data);
+
 kadm5_ret_t    kadm5_decrypt_key(void *server_handle,
                                  kadm5_principal_ent_t entry, krb5_int32
                                  ktype, krb5_int32 stype, krb5_int32
diff --git a/src/lib/kadm5/admin_xdr.h b/src/lib/kadm5/admin_xdr.h
index e46d542..cc44396 100644
--- a/src/lib/kadm5/admin_xdr.h
+++ b/src/lib/kadm5/admin_xdr.h
@@ -40,6 +40,7 @@ bool_t      xdr_chpass3_arg(XDR *xdrs, chpass3_arg *objp);
 bool_t      xdr_setv4key_arg(XDR *xdrs, setv4key_arg *objp);
 bool_t      xdr_setkey_arg(XDR *xdrs, setkey_arg *objp);
 bool_t      xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp);
+bool_t      xdr_setkey4_arg(XDR *xdrs, setkey4_arg *objp);
 bool_t	    xdr_chrand_arg(XDR *xdrs, chrand_arg *objp);
 bool_t      xdr_chrand3_arg(XDR *xdrs, chrand3_arg *objp);
 bool_t	    xdr_chrand_ret(XDR *xdrs, chrand_ret *objp);
@@ -68,3 +69,4 @@ bool_t	    xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp);
 bool_t      xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp);
 bool_t      xdr_krb5_string_attr(XDR *xdrs, krb5_string_attr *objp);
 bool_t      xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp);
+bool_t      xdr_kadm5_key_data(XDR *xdrs, kadm5_key_data *objp);
diff --git a/src/lib/kadm5/clnt/client_principal.c b/src/lib/kadm5/clnt/client_principal.c
index 6af2a17..893d3c7 100644
--- a/src/lib/kadm5/clnt/client_principal.c
+++ b/src/lib/kadm5/clnt/client_principal.c
@@ -362,6 +362,33 @@ kadm5_setkey_principal_3(void *server_handle,
 }
 
 kadm5_ret_t
+kadm5_setkey_principal_4(void *server_handle,
+                         krb5_principal princ,
+                         krb5_boolean keepold,
+                         kadm5_key_data *key_data,
+                         int n_key_data)
+{
+    setkey4_arg         arg;
+    generic_ret         *r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+
+    arg.api_version = handle->api_version;
+    arg.princ = princ;
+    arg.keepold = keepold;
+    arg.key_data = key_data;
+    arg.n_key_data = n_key_data;
+
+    if (princ == NULL || key_data == NULL || n_key_data == 0)
+        return EINVAL;
+    r = setkey_principal4_2(&arg, handle->clnt);
+    if (r == NULL)
+        eret();
+    return r->code;
+}
+
+kadm5_ret_t
 kadm5_randkey_principal_3(void *server_handle,
                           krb5_principal princ,
                           krb5_boolean keepold, int n_ks_tuple,
diff --git a/src/lib/kadm5/clnt/client_rpc.c b/src/lib/kadm5/clnt/client_rpc.c
index 0d2f953..fa335a4 100644
--- a/src/lib/kadm5/clnt/client_rpc.c
+++ b/src/lib/kadm5/clnt/client_rpc.c
@@ -192,6 +192,21 @@ setkey_principal3_2(setkey3_arg *argp, CLIENT *clnt)
 	return (&clnt_res);
 }
 
+generic_ret *
+setkey_principal4_2(setkey4_arg *argp, CLIENT *clnt)
+{
+	static generic_ret clnt_res;
+
+	memset(&clnt_res, 0, sizeof(clnt_res));
+	if (clnt_call(clnt, SETKEY_PRINCIPAL4,
+		      (xdrproc_t)xdr_setkey4_arg, (caddr_t)argp,
+		      (xdrproc_t)xdr_generic_ret, (caddr_t)&clnt_res,
+		      TIMEOUT) != RPC_SUCCESS) {
+		return NULL;
+	}
+	return &clnt_res;
+}
+
 chrand_ret *
 chrand_principal_2(chrand_arg *argp, CLIENT *clnt)
 {
diff --git a/src/lib/kadm5/clnt/libkadm5clnt_mit.exports b/src/lib/kadm5/clnt/libkadm5clnt_mit.exports
index b7d0ec5..d9e99ef 100644
--- a/src/lib/kadm5/clnt/libkadm5clnt_mit.exports
+++ b/src/lib/kadm5/clnt/libkadm5clnt_mit.exports
@@ -41,6 +41,7 @@ kadm5_rename_principal
 kadm5_set_string
 kadm5_setkey_principal
 kadm5_setkey_principal_3
+kadm5_setkey_principal_4
 kadm5_setv4key_principal
 kadm5_unlock
 krb5_aprof_finish
@@ -81,6 +82,7 @@ xdr_gprinc_arg
 xdr_gprinc_ret
 xdr_gprincs_arg
 xdr_gprincs_ret
+xdr_kadm5_key_data
 xdr_kadm5_policy_ent_rec
 xdr_kadm5_principal_ent_rec
 xdr_kadm5_ret_t
@@ -105,6 +107,7 @@ xdr_nullstring
 xdr_nulltype
 xdr_rprinc_arg
 xdr_setkey3_arg
+xdr_setkey4_arg
 xdr_setkey_arg
 xdr_setv4key_arg
 xdr_ui_4
diff --git a/src/lib/kadm5/kadm_err.et b/src/lib/kadm5/kadm_err.et
index c717670..bc10a5b 100644
--- a/src/lib/kadm5/kadm_err.et
+++ b/src/lib/kadm5/kadm_err.et
@@ -63,4 +63,5 @@ error_code KADM5_XDR_FAILURE,		"XDR encoding error"
 error_code KADM5_CANT_RESOLVE, "Cannot resolve network address for admin server in requested realm"
 error_code KADM5_PASS_Q_GENERIC, "Unspecified password quality failure"
 error_code KADM5_BAD_KEYSALTS, "Invalid key/salt tuples"
+error_code KADM5_SETKEY_BAD_KVNO, "Invalid multiple or duplicate kvnos in setkey operation"
 end
diff --git a/src/lib/kadm5/kadm_rpc.h b/src/lib/kadm5/kadm_rpc.h
index d5e9e7f..24565bd 100644
--- a/src/lib/kadm5/kadm_rpc.h
+++ b/src/lib/kadm5/kadm_rpc.h
@@ -108,6 +108,15 @@ struct setkey3_arg {
 };
 typedef struct setkey3_arg setkey3_arg;
 
+struct setkey4_arg {
+	krb5_ui_4 api_version;
+	krb5_principal princ;
+	krb5_boolean keepold;
+	kadm5_key_data *key_data;
+	int n_key_data;
+};
+typedef struct setkey4_arg setkey4_arg;
+
 struct chrand_arg {
 	krb5_ui_4 api_version;
 	krb5_principal princ;
@@ -303,6 +312,9 @@ extern  gstrings_ret * get_strings_2_svc(gstrings_arg *, struct svc_req *);
 #define SET_STRING 24
 extern  generic_ret * set_string_2(sstring_arg *, CLIENT *);
 extern  generic_ret * set_string_2_svc(sstring_arg *, struct svc_req *);
+#define SETKEY_PRINCIPAL4 25
+extern  generic_ret * setkey_principal4_2(setkey4_arg *, CLIENT *);
+extern  generic_ret * setkey_principal4_2_svc(setkey4_arg *, struct svc_req *);
 
 extern bool_t xdr_cprinc_arg ();
 extern bool_t xdr_cprinc3_arg ();
@@ -317,6 +329,7 @@ extern bool_t xdr_chpass3_arg ();
 extern bool_t xdr_setv4key_arg ();
 extern bool_t xdr_setkey_arg ();
 extern bool_t xdr_setkey3_arg ();
+extern bool_t xdr_setkey4_arg ();
 extern bool_t xdr_chrand_arg ();
 extern bool_t xdr_chrand3_arg ();
 extern bool_t xdr_chrand_ret ();
@@ -344,6 +357,7 @@ extern bool_t xdr_gstrings_arg ();
 extern bool_t xdr_gstrings_ret ();
 extern bool_t xdr_sstring_arg ();
 extern bool_t xdr_krb5_string_attr ();
+extern bool_t xdr_kadm5_key_data ();
 
 
 #endif /* __KADM_RPC_H__ */
diff --git a/src/lib/kadm5/kadm_rpc_xdr.c b/src/lib/kadm5/kadm_rpc_xdr.c
index ba67084..bfd0341 100644
--- a/src/lib/kadm5/kadm_rpc_xdr.c
+++ b/src/lib/kadm5/kadm_rpc_xdr.c
@@ -772,6 +772,26 @@ xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp)
 }
 
 bool_t
+xdr_setkey4_arg(XDR *xdrs, setkey4_arg *objp)
+{
+	if (!xdr_ui_4(xdrs, &objp->api_version)) {
+		return FALSE;
+	}
+	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+		return FALSE;
+	}
+	if (!xdr_krb5_boolean(xdrs, &objp->keepold)) {
+		return FALSE;
+	}
+	if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
+		       (unsigned int *) &objp->n_key_data, ~0,
+		       sizeof(kadm5_key_data), xdr_kadm5_key_data)) {
+		return FALSE;
+	}
+	return TRUE;
+}
+
+bool_t
 xdr_chrand_arg(XDR *xdrs, chrand_arg *objp)
 {
 	if (!xdr_ui_4(xdrs, &objp->api_version)) {
@@ -1157,3 +1177,18 @@ xdr_krb5_string_attr(XDR *xdrs, krb5_string_attr *objp)
 		return FALSE;
 	return TRUE;
 }
+
+bool_t
+xdr_kadm5_key_data(XDR *xdrs, kadm5_key_data *objp)
+{
+	if (!xdr_krb5_kvno(xdrs, &objp->kvno))
+		return FALSE;
+	if (!xdr_krb5_keyblock(xdrs, &objp->key))
+		return FALSE;
+	if (!xdr_krb5_int16(xdrs, &objp->salt.type))
+		return FALSE;
+	if (!xdr_bytes(xdrs, &objp->salt.data.data,
+		       &objp->salt.data.length, ~0))
+		return FALSE;
+	return TRUE;
+}
diff --git a/src/lib/kadm5/srv/libkadm5srv_mit.exports b/src/lib/kadm5/srv/libkadm5srv_mit.exports
index 86af371..2cdd5a0 100644
--- a/src/lib/kadm5/srv/libkadm5srv_mit.exports
+++ b/src/lib/kadm5/srv/libkadm5srv_mit.exports
@@ -48,6 +48,7 @@ kadm5_rename_principal
 kadm5_set_string
 kadm5_setkey_principal
 kadm5_setkey_principal_3
+kadm5_setkey_principal_4
 kadm5_setv4key_principal
 kadm5_unlock
 kdb_delete_entry
@@ -131,6 +132,7 @@ xdr_osa_pw_hist_ent
 xdr_purgekeys_arg
 xdr_rprinc_arg
 xdr_setkey3_arg
+xdr_setkey4_arg
 xdr_setkey_arg
 xdr_setv4key_arg
 xdr_sstring_arg
diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
index f3791c6..4a083c2 100644
--- a/src/lib/kadm5/srv/svr_principal.c
+++ b/src/lib/kadm5/srv/svr_principal.c
@@ -2206,6 +2206,201 @@ done:
     return ret;
 }
 
+/* Create a key/salt list from a key_data array. */
+static kadm5_ret_t
+make_ks_from_key_data(krb5_context context, kadm5_key_data *key_data,
+                      int n_key_data, krb5_key_salt_tuple **out)
+{
+    int i;
+    krb5_key_salt_tuple *ks;
+
+    *out = NULL;
+
+    ks = calloc(n_key_data, sizeof(*ks));
+    if (ks == NULL)
+        return ENOMEM;
+
+    for (i = 0; i < n_key_data; i++) {
+        ks[i].ks_enctype = key_data[i].key.enctype;
+        ks[i].ks_salttype = key_data[i].salt.type;
+    }
+    *out = ks;
+    return 0;
+}
+
+kadm5_ret_t
+kadm5_setkey_principal_4(void *server_handle, krb5_principal principal,
+                         krb5_boolean keepold, kadm5_key_data *key_data,
+                         int n_key_data)
+{
+    krb5_db_entry *kdb;
+    osa_princ_ent_rec adb;
+    krb5_int32 now;
+    kadm5_policy_ent_rec pol;
+    krb5_key_data *new_key_data = NULL;
+    int i, j, ret, n_new_key_data = 0;
+    krb5_kvno kvno;
+    krb5_boolean similar, have_pol = FALSE;
+    kadm5_server_handle_t handle = server_handle;
+    krb5_keyblock *act_mkey;
+    krb5_key_salt_tuple *ks_from_keys = NULL;
+
+    CHECK_HANDLE(server_handle);
+
+    krb5_clear_error_message(handle->context);
+
+    if (principal == NULL || key_data == NULL || n_key_data == 0)
+        return EINVAL;
+
+    /* hist_princ will be NULL when initializing the database. */
+    if (hist_princ != NULL &&
+        krb5_principal_compare(handle->context, principal, hist_princ))
+        return KADM5_PROTECT_PRINCIPAL;
+
+    /* For now, all keys must have the same kvno. */
+    kvno = key_data[0].kvno;
+    for (i = 1; i < n_key_data; i++) {
+        if (key_data[i].kvno != kvno)
+            return KADM5_SETKEY_BAD_KVNO;
+    }
+
+    ret = kdb_get_entry(handle, principal, &kdb, &adb);
+    if (ret)
+        return ret;
+
+    if (kvno == 0) {
+        /* Pick the next kvno. */
+        for (i = 0; i < kdb->n_key_data; i++) {
+            if (kdb->key_data[i].key_data_kvno > kvno)
+                kvno = kdb->key_data[i].key_data_kvno;
+        }
+        kvno++;
+    } else if (keepold) {
+        /* Check that the kvno does collide with existing keys. */
+        for (i = 0; i < kdb->n_key_data; i++) {
+            if (kdb->key_data[i].key_data_kvno == kvno) {
+                ret = KADM5_SETKEY_BAD_KVNO;
+                goto done;
+            }
+        }
+    }
+
+    ret = make_ks_from_key_data(handle->context, key_data, n_key_data,
+                                &ks_from_keys);
+    if (ret)
+        goto done;
+
+    ret = apply_keysalt_policy(handle, adb.policy, n_key_data, ks_from_keys,
+                               NULL, NULL);
+    free(ks_from_keys);
+    if (ret)
+        goto done;
+
+    for (i = 0; i < n_key_data; i++) {
+        for (j = i + 1; j < n_key_data; j++) {
+            ret = krb5_c_enctype_compare(handle->context,
+                                         key_data[i].key.enctype,
+                                         key_data[j].key.enctype,
+                                         &similar);
+            if (ret)
+                goto done;
+            if (similar) {
+                if (key_data[i].salt.type == key_data[j].salt.type) {
+                    ret = KADM5_SETKEY_DUP_ENCTYPES;
+                    goto done;
+                }
+            }
+        }
+    }
+
+    n_new_key_data = n_key_data + (keepold ? kdb->n_key_data : 0);
+    new_key_data = krb5_db_alloc(handle->context, NULL,
+                                 n_new_key_data * sizeof(krb5_key_data));
+    if (new_key_data == NULL) {
+        n_new_key_data = 0;
+        ret = ENOMEM;
+        goto done;
+    }
+    memset(new_key_data, 0, n_new_key_data * sizeof(krb5_key_data));
+
+    n_new_key_data = 0;
+    for (i = 0; i < n_key_data; i++) {
+
+        ret = kdb_get_active_mkey(handle, NULL, &act_mkey);
+        if (ret)
+            goto done;
+
+        ret = krb5_dbe_encrypt_key_data(handle->context, act_mkey,
+                                        &key_data[i].key, &key_data[i].salt,
+                                        kvno, &new_key_data[i]);
+        if (ret)
+            goto done;
+
+        n_new_key_data++;
+    }
+
+    /* Copy old key data if necessary. */
+    if (keepold) {
+        memcpy(new_key_data + n_new_key_data, kdb->key_data,
+               kdb->n_key_data * sizeof(krb5_key_data));
+        memset(kdb->key_data, 0, kdb->n_key_data * sizeof(krb5_key_data));
+
+        /*
+         * Sort the keys to maintain the defined kvno order.  We only need to
+         * sort if we keep old keys, as otherwise we allow only a single kvno
+         * to be specified.
+         */
+        krb5_dbe_sort_key_data(new_key_data, n_new_key_data);
+    }
+
+    /* Replace kdb->key_data with the new keys. */
+    cleanup_key_data(handle->context, kdb->n_key_data, kdb->key_data);
+    kdb->key_data = new_key_data;
+    kdb->n_key_data = n_new_key_data;
+    new_key_data = NULL;
+    n_new_key_data = 0;
+
+    kdb->attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+
+    ret = krb5_timeofday(handle->context, &now);
+    if (ret)
+        goto done;
+
+    if (adb.aux_attributes & KADM5_POLICY) {
+        ret = get_policy(handle, adb.policy, &pol, &have_pol);
+        if (ret)
+            goto done;
+    }
+    if (have_pol) {
+        if (pol.pw_max_life)
+            kdb->pw_expiration = now + pol.pw_max_life;
+        else
+            kdb->pw_expiration = 0;
+    } else {
+        kdb->pw_expiration = 0;
+    }
+
+    ret = krb5_dbe_update_last_pwd_change(handle->context, kdb, now);
+    if (ret)
+        goto done;
+
+    /* Unlock principal on this KDC. */
+    kdb->fail_auth_count = 0;
+
+    ret = kdb_put_entry(handle, kdb, &adb);
+    if (ret)
+        goto done;
+
+    ret = KADM5_OK;
+
+done:
+    cleanup_key_data(handle->context, n_new_key_data, new_key_data);
+    kdb_free_entry(handle, kdb, &adb);
+    if (have_pol)
+        kadm5_free_policy_ent(handle->lhandle, &pol);
+    return ret;
+}
+
 /*
  * Return the list of keys like kadm5_randkey_principal,
  * but don't modify the principal.


More information about the cvs-krb5 mailing list