From 69357b54afbe8232ad849da28f13f2b6190f91d9 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Mon, 14 Feb 2000 00:07:10 +0000 Subject: [PATCH] Add client-side stubs and functions with additional capabilities to take key_salt_tuples and optionally keep old keys around. Add server-side functionality for setkey with key_salt_tuple and "keepold" functionality. Update rpc stubs and xdr functions/headers appropriately. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@12040 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/kadm5/ChangeLog | 11 ++ src/lib/kadm5/admin.h | 8 ++ src/lib/kadm5/clnt/ChangeLog | 7 ++ src/lib/kadm5/clnt/client_principal.c | 173 ++++++++++++++++++++++++++ src/lib/kadm5/clnt/client_rpc.c | 56 +++++++++ src/lib/kadm5/kadm_err.et | 1 + src/lib/kadm5/kadm_rpc.h | 53 ++++++++ src/lib/kadm5/kadm_rpc_xdr.c | 124 +++++++++++++++++- src/lib/kadm5/srv/ChangeLog | 4 + src/lib/kadm5/srv/svr_principal.c | 79 ++++++++++-- 10 files changed, 501 insertions(+), 15 deletions(-) diff --git a/src/lib/kadm5/ChangeLog b/src/lib/kadm5/ChangeLog index 2eb05a8bc..a951c04dc 100644 --- a/src/lib/kadm5/ChangeLog +++ b/src/lib/kadm5/ChangeLog @@ -1,3 +1,14 @@ +2000-02-13 Tom Yu + + * kadm_rpc_xdr.c: Add xdr functions for new kadm rpc functions. + + * kadm_rpc.h: Add arg structs, prototypes, constants for new kadm + rpc functions. + + * kadm_err.et: Add error code KADM5_SETKEY3_ETYPE_MISMATCH. + + * admin.h: Add prototype for setkey_principal_3. + 1999-12-01 Ken Raeburn * logger.c (klog_vsyslog): Convert pid_t to long for printing. diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h index 6aa432f34..d8904e664 100644 --- a/src/lib/kadm5/admin.h +++ b/src/lib/kadm5/admin.h @@ -361,6 +361,14 @@ kadm5_ret_t kadm5_setkey_principal(void *server_handle, krb5_keyblock *keyblocks, int n_keys); +kadm5_ret_t kadm5_setkey_principal_3(void *server_handle, + krb5_principal principal, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + krb5_keyblock *keyblocks, + int n_keys); + kadm5_ret_t kadm5_create_policy(void *server_handle, kadm5_policy_ent_t ent, long mask); diff --git a/src/lib/kadm5/clnt/ChangeLog b/src/lib/kadm5/clnt/ChangeLog index de4c52557..37f4207ed 100644 --- a/src/lib/kadm5/clnt/ChangeLog +++ b/src/lib/kadm5/clnt/ChangeLog @@ -1,3 +1,10 @@ +2000-02-13 Tom Yu + + * client_rpc.c: Add new client stubs. + + * client_principal.c: Add new functions for client-side kadm rpc + calls. + 2000-01-27 Ken Raeburn * client_init.c (enctypes): New array, listing only diff --git a/src/lib/kadm5/clnt/client_principal.c b/src/lib/kadm5/clnt/client_principal.c index b23ff1f2e..97ea6989c 100644 --- a/src/lib/kadm5/clnt/client_principal.c +++ b/src/lib/kadm5/clnt/client_principal.c @@ -71,6 +71,68 @@ kadm5_create_principal(void *server_handle, return r->code; } +kadm5_ret_t +kadm5_create_principal_3(void *server_handle, + kadm5_principal_ent_t princ, long mask, + krb5_boolean keepold, int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + char *pw) +{ + generic_ret *r; + cprinc3_arg arg; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + memset(&arg, 0, sizeof(arg)); + arg.mask = mask; + arg.passwd = pw; + arg.api_version = handle->api_version; + arg.keepold = keepold; + arg.n_ks_tuple = n_ks_tuple; + arg.ks_tuple = ks_tuple; + + if(princ == NULL) + return EINVAL; + + if (handle->api_version == KADM5_API_VERSION_1) { + memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1)); + } else { + memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec)); + } + if (handle->api_version == KADM5_API_VERSION_1) { + /* + * hack hack cough cough. + * krb5_unparse name dumps core if we pass it in garbage + * or null. So, since the client is not allowed to set mod_name + * anyway, we just fill it in with a dummy principal. The server of + * course ignores this. + */ + krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name); + } else + arg.rec.mod_name = NULL; + + if(!(mask & KADM5_POLICY)) + arg.rec.policy = NULL; + if (! (mask & KADM5_KEY_DATA)) { + arg.rec.n_key_data = 0; + arg.rec.key_data = NULL; + } + if (! (mask & KADM5_TL_DATA)) { + arg.rec.n_tl_data = 0; + arg.rec.tl_data = NULL; + } + + r = create_principal3_1(&arg, handle->clnt); + + if (handle->api_version == KADM5_API_VERSION_1) + krb5_free_principal(handle->context, arg.rec.mod_name); + + if(r == NULL) + return KADM5_RPC_ERROR; + return r->code; +} + kadm5_ret_t kadm5_delete_principal(void *server_handle, krb5_principal principal) { @@ -261,6 +323,33 @@ kadm5_chpass_principal(void *server_handle, return r->code; } +kadm5_ret_t +kadm5_chpass_principal_3(void *server_handle, + krb5_principal princ, krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + char *password) +{ + chpass3_arg arg; + generic_ret *r; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.pass = password; + arg.api_version = handle->api_version; + arg.keepold = keepold; + arg.n_ks_tuple = n_ks_tuple; + arg.ks_tuple = ks_tuple; + + if(princ == NULL) + return EINVAL; + r = chpass_principal3_1(&arg, handle->clnt); + if(r == NULL) + return KADM5_RPC_ERROR; + return r->code; +} + kadm5_ret_t kadm5_setv4key_principal(void *server_handle, krb5_principal princ, @@ -309,6 +398,90 @@ kadm5_setkey_principal(void *server_handle, return r->code; } +kadm5_ret_t +kadm5_setkey_principal_3(void *server_handle, + krb5_principal princ, + krb5_boolean keepold, int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + krb5_keyblock *keyblocks, + int n_keys) +{ + setkey3_arg arg; + generic_ret *r; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.keyblocks = keyblocks; + arg.n_keys = n_keys; + arg.api_version = handle->api_version; + arg.keepold = keepold; + arg.n_ks_tuple = n_ks_tuple; + arg.ks_tuple = ks_tuple; + + if(princ == NULL || keyblocks == NULL) + return EINVAL; + r = setkey_principal3_1(&arg, handle->clnt); + if(r == NULL) + return KADM5_RPC_ERROR; + return r->code; +} + +kadm5_ret_t +kadm5_randkey_principal_3(void *server_handle, + krb5_principal princ, + krb5_boolean keepold, int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + krb5_keyblock **key, int *n_keys) +{ + chrand3_arg arg; + chrand_ret *r; + krb5_keyblock new; + kadm5_server_handle_t handle = server_handle; + int i, ret; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.api_version = handle->api_version; + arg.keepold = keepold; + arg.n_ks_tuple = n_ks_tuple; + arg.ks_tuple = ks_tuple; + + if(princ == NULL) + return EINVAL; + r = chrand_principal3_1(&arg, handle->clnt); + if(r == NULL) + return KADM5_RPC_ERROR; + if (handle->api_version == KADM5_API_VERSION_1) { + if (key) + krb5_copy_keyblock(handle->context, &r->key, key); + } else { + if (n_keys) + *n_keys = r->n_keys; + if (key) { + if(r->n_keys) { + *key = (krb5_keyblock *) + malloc(r->n_keys*sizeof(krb5_keyblock)); + if (*key == NULL) + return ENOMEM; + for (i = 0; i < r->n_keys; i++) { + ret = krb5_copy_keyblock_contents(handle->context, + &r->keys[i], + &(*key)[i]); + if (ret) { + free(*key); + return ENOMEM; + } + } + } else *key = NULL; + } + } + + return r->code; +} + kadm5_ret_t kadm5_randkey_principal(void *server_handle, krb5_principal princ, diff --git a/src/lib/kadm5/clnt/client_rpc.c b/src/lib/kadm5/clnt/client_rpc.c index 8a284e382..7c55ab461 100644 --- a/src/lib/kadm5/clnt/client_rpc.c +++ b/src/lib/kadm5/clnt/client_rpc.c @@ -21,6 +21,20 @@ create_principal_1(argp, clnt) return (&res); } +generic_ret * +create_principal3_1(argp, clnt) + cprinc_arg *argp; + CLIENT *clnt; +{ + static generic_ret res; + + memset((char *)&res, 0, sizeof(res)); + if (clnt_call(clnt, CREATE_PRINCIPAL3, xdr_cprinc3_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&res); +} + generic_ret * delete_principal_1(argp, clnt) dprinc_arg *argp; @@ -106,6 +120,20 @@ chpass_principal_1(argp, clnt) return (&res); } +generic_ret * +chpass_principal3_1(argp, clnt) + chpass_arg *argp; + CLIENT *clnt; +{ + static generic_ret res; + + memset((char *)&res, 0, sizeof(res)); + if (clnt_call(clnt, CHPASS_PRINCIPAL3, xdr_chpass3_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&res); +} + generic_ret * setv4key_principal_1(argp, clnt) setv4key_arg *argp; @@ -134,6 +162,20 @@ setkey_principal_1(argp, clnt) return (&res); } +generic_ret * +setkey_principal3_1(argp, clnt) + setkey_arg *argp; + CLIENT *clnt; +{ + static generic_ret res; + + memset((char *)&res, 0, sizeof(res)); + if (clnt_call(clnt, SETKEY_PRINCIPAL3, xdr_setkey3_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&res); +} + chrand_ret * chrand_principal_1(argp, clnt) chrand_arg *argp; @@ -148,6 +190,20 @@ chrand_principal_1(argp, clnt) return (&res); } +chrand_ret * +chrand_principal3_1(argp, clnt) + chrand_arg *argp; + CLIENT *clnt; +{ + static chrand_ret res; + + memset((char *)&res, 0, sizeof(res)); + if (clnt_call(clnt, CHRAND_PRINCIPAL3, xdr_chrand3_arg, argp, xdr_chrand_ret, &res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&res); +} + generic_ret * create_policy_1(argp, clnt) cpol_arg *argp; diff --git a/src/lib/kadm5/kadm_err.et b/src/lib/kadm5/kadm_err.et index 29c65818c..0e2b2c523 100644 --- a/src/lib/kadm5/kadm_err.et +++ b/src/lib/kadm5/kadm_err.et @@ -58,3 +58,4 @@ error_code KADM5_AUTH_SETKEY, "Operation requires ``set-key'' privilege" error_code KADM5_SETKEY_DUP_ENCTYPES, "Multiple values for single or folded enctype" error_code KADM5_SETV4KEY_INVAL_ENCTYPE, "Invalid enctype for setv4key" end +error_code KADM5_SETKEY3_ETYPE_MISMATCH, "Mismatched enctypes for setkey3" diff --git a/src/lib/kadm5/kadm_rpc.h b/src/lib/kadm5/kadm_rpc.h index 468e072b2..e1aa36432 100644 --- a/src/lib/kadm5/kadm_rpc.h +++ b/src/lib/kadm5/kadm_rpc.h @@ -12,6 +12,18 @@ struct cprinc_arg { typedef struct cprinc_arg cprinc_arg; bool_t xdr_cprinc_arg(); +struct cprinc3_arg { + krb5_ui_4 api_version; + kadm5_principal_ent_rec rec; + long mask; + krb5_boolean keepold; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple; + char *passwd; +}; +typedef struct cprinc3_arg cprinc3_arg; +bool_t xdr_cprinc3_arg(); + struct generic_ret { krb5_ui_4 api_version; kadm5_ret_t code; @@ -66,6 +78,17 @@ struct chpass_arg { typedef struct chpass_arg chpass_arg; bool_t xdr_chpass_arg(); +struct chpass3_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_boolean keepold; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple; + char *pass; +}; +typedef struct chpass3_arg chpass3_arg; +bool_t xdr_chpass3_arg(); + struct setv4key_arg { krb5_ui_4 api_version; krb5_principal princ; @@ -83,6 +106,18 @@ struct setkey_arg { typedef struct setkey_arg setkey_arg; bool_t xdr_setkey_arg(); +struct setkey3_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_boolean keepold; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple; + krb5_keyblock *keyblocks; + int n_keys; +}; +typedef struct setkey3_arg setkey3_arg; +bool_t xdr_setkey3_arg(); + struct chrand_arg { krb5_ui_4 api_version; krb5_principal princ; @@ -90,6 +125,16 @@ struct chrand_arg { typedef struct chrand_arg chrand_arg; bool_t xdr_chrand_arg(); +struct chrand3_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_boolean keepold; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple; +}; +typedef struct chrand3_arg chrand3_arg; +bool_t xdr_chrand3_arg(); + struct chrand_ret { krb5_ui_4 api_version; kadm5_ret_t code; @@ -223,3 +268,11 @@ extern gpols_ret *get_pols_1(); extern generic_ret *setkey_principal_1(); #define SETV4KEY_PRINCIPAL ((krb5_ui_4) 17) extern generic_ret *setv4key_principal_1(); +#define CREATE_PRINCIPAL3 ((krb5_ui_4) 18) +extern generic_ret *create_principal3_1(); +#define CHPASS_PRINCIPAL3 ((krb5_ui_4) 19) +extern generic_ret *chpass_principal3_1(); +#define CHRAND_PRINCIPAL3 ((krb5_ui_4) 20) +extern chrand_ret *chrand_principal3_1(); +#define SETKEY_PRINCIPAL3 ((krb5_ui_4) 21) +extern generic_ret *setkey_principal3_1(); diff --git a/src/lib/kadm5/kadm_rpc_xdr.c b/src/lib/kadm5/kadm_rpc_xdr.c index 63be6a092..4e313a749 100644 --- a/src/lib/kadm5/kadm_rpc_xdr.c +++ b/src/lib/kadm5/kadm_rpc_xdr.c @@ -13,7 +13,6 @@ static bool_t _xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp, int v); - /* * Function: xdr_ui_4 * @@ -243,6 +242,17 @@ bool_t xdr_krb5_key_data_nocontents(XDR *xdrs, krb5_key_data *objp) return (TRUE); } + +bool_t +xdr_krb5_key_salt_tuple(XDR *xdrs, krb5_key_salt_tuple *objp) +{ + if (!xdr_krb5_enctype(xdrs, &objp->ks_enctype)) + return FALSE; + if (!xdr_krb5_salttype(xdrs, &objp->ks_salttype)) + return FALSE; + return TRUE; +} + bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head) { krb5_tl_data *tl, *tl2; @@ -470,6 +480,39 @@ xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp) return (TRUE); } +bool_t +xdr_cprinc3_arg(XDR *xdrs, cprinc3_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (objp->api_version == KADM5_API_VERSION_1) { + if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) { + return (FALSE); + } + } else { + if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) { + return (FALSE); + } + } + if (!xdr_long(xdrs, &objp->mask)) { + return (FALSE); + } + if (!xdr_bool(xdrs, &objp->keepold)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple, + (unsigned int *)&objp->n_ks_tuple, ~0, + sizeof(krb5_key_salt_tuple), + xdr_krb5_key_salt_tuple)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->passwd)) { + return (FALSE); + } + return (TRUE); +} + bool_t xdr_generic_ret(XDR *xdrs, generic_ret *objp) { @@ -579,6 +622,30 @@ xdr_chpass_arg(XDR *xdrs, chpass_arg *objp) return (TRUE); } +bool_t +xdr_chpass3_arg(XDR *xdrs, chpass3_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_bool(xdrs, &objp->keepold)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple, + objp->n_ks_tuple, ~0, + sizeof(krb5_key_salt_tuple), + xdr_krb5_key_salt_tuple)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->pass)) { + return (FALSE); + } + return (TRUE); +} + bool_t xdr_setv4key_arg(XDR *xdrs, setv4key_arg *objp) { @@ -615,6 +682,31 @@ xdr_setkey_arg(XDR *xdrs, setkey_arg *objp) return (TRUE); } +bool_t +xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_bool(xdrs, &objp->keepold)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->ks_tuple, + (unsigned int *) &objp->n_ks_tuple, ~0, + sizeof(krb5_key_salt_tuple), xdr_krb5_key_salt_tuple)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks, + (unsigned int *) &objp->n_keys, ~0, + sizeof(krb5_keyblock), xdr_krb5_keyblock)) { + return (FALSE); + } + return (TRUE); +} + bool_t xdr_chrand_arg(XDR *xdrs, chrand_arg *objp) { @@ -627,6 +719,27 @@ xdr_chrand_arg(XDR *xdrs, chrand_arg *objp) return (TRUE); } +bool_t +xdr_chrand3_arg(XDR *xdrs, chrand3_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_bool(xdrs, &objp->keepold)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple, + objp->n_ks_tuple, ~0, + sizeof(krb5_key_salt_tuple), + xdr_krb5_key_salt_tuple)) { + return (FALSE); + } + return (TRUE); +} + bool_t xdr_chrand_ret(XDR *xdrs, chrand_ret *objp) { @@ -880,6 +993,14 @@ xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp) return (TRUE); } +bool_t +xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp) +{ + if (!xdr_int32(xdrs, (rpc_int32 *) objp)) + return FALSE; + return TRUE; +} + bool_t xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp) { @@ -893,4 +1014,3 @@ xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp) return FALSE; return TRUE; } - diff --git a/src/lib/kadm5/srv/ChangeLog b/src/lib/kadm5/srv/ChangeLog index 22e0cf1ec..23d05d607 100644 --- a/src/lib/kadm5/srv/ChangeLog +++ b/src/lib/kadm5/srv/ChangeLog @@ -1,3 +1,7 @@ +2000-02-13 Tom Yu + + * svr_principal.c (kadm5_setkey_principal_3): New function. + 1999-10-26 Tom Yu * Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES, diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index b58e11b5d..f8148a046 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -1432,15 +1432,31 @@ kadm5_setkey_principal(void *server_handle, krb5_principal principal, krb5_keyblock *keyblocks, int n_keys) +{ + return + kadm5_setkey_principal_3(server_handle, principal, + FALSE, 0, NULL, + keyblocks, n_keys); +} + +kadm5_ret_t +kadm5_setkey_principal_3(void *server_handle, + krb5_principal principal, + krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + krb5_keyblock *keyblocks, + int n_keys) { krb5_db_entry kdb; osa_princ_ent_rec adb; krb5_int32 now; kadm5_policy_ent_rec pol; - krb5_key_data *key_data; + krb5_key_data *old_key_data; + int n_old_keys; int i, j, kvno, ret, last_pwd, have_pol = 0; kadm5_server_handle_t handle = server_handle; krb5_boolean similar; + krb5_keysalt keysalt; CHECK_HANDLE(server_handle); @@ -1459,10 +1475,17 @@ kadm5_setkey_principal(void *server_handle, &similar)) return(ret); if (similar) - return KADM5_SETKEY_DUP_ENCTYPES; + if (n_ks_tuple) { + if (ks_tuple[i].ks_salttype == ks_tuple[j].ks_salttype) + return KADM5_SETKEY_DUP_ENCTYPES; + } else + return KADM5_SETKEY_DUP_ENCTYPES; } } + if (n_ks_tuple != n_keys) + return KADM5_SETKEY3_ETYPE_MISMATCH; + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) return(ret); @@ -1470,24 +1493,54 @@ kadm5_setkey_principal(void *server_handle, if (kdb.key_data[i].key_data_kvno > kvno) kvno = kdb.key_data[i].key_data_kvno; - if (kdb.key_data != NULL) - cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data); + if (keepold) { + old_key_data = kdb.key_data; + n_old_keys = kdb.n_key_data; + } else { + if (kdb.key_data != NULL) + cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data); + n_old_keys = 0; + old_key_data = NULL; + } - kdb.key_data = (krb5_key_data*)malloc(n_keys*sizeof(krb5_key_data)); + kdb.key_data = (krb5_key_data*)malloc((n_keys+n_old_keys) + *sizeof(krb5_key_data)); if (kdb.key_data == NULL) return ENOMEM; - memset(kdb.key_data, 0, n_keys*sizeof(krb5_key_data)); - kdb.n_key_data = n_keys; + memset(kdb.key_data, 0, (n_keys+n_old_keys)*sizeof(krb5_key_data)); + kdb.n_key_data = 0; for (i = 0; i < n_keys; i++) { - if (ret = krb5_dbekd_encrypt_key_data(handle->context, - &master_keyblock, - &keyblocks[i], NULL, - kvno + 1, - &kdb.key_data[i])) - return ret; + if (n_ks_tuple) { + keysalt.type = ks_tuple[i].ks_salttype; + keysalt.data.length = 0; + keysalt.data.data = NULL; + if (ks_tuple[i].ks_enctype != keyblocks[i].enctype) { + cleanup_key_data(handle->context, kdb.n_key_data, + kdb.key_data); + return KADM5_SETKEY3_ETYPE_MISMATCH; + } + } + ret = krb5_dbekd_encrypt_key_data(handle->context, + &master_keyblock, + &keyblocks[i], + n_ks_tuple ? &keysalt : NULL, + kvno + 1, + &kdb.key_data[i]); + if (ret) { + cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data); + return ret; + } + kdb.n_key_data++; } + /* copy old key data if necessary */ + for (i = 0; i < n_old_keys; i++) { + kdb.key_data[i+n_keys] = old_key_data[i]; + memset(&old_key_data[i], 0, sizeof (krb5_key_data)); + kdb.n_key_data++; + } + /* assert(kdb.n_key_data == n_keys + n_old_keys) */ kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; if (ret = krb5_timeofday(handle->context, &now)) -- 2.26.2