From 4505316756e42db02b6dabe0a6b075fe52852371 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Thu, 14 Jan 2021 18:13:09 -0500 Subject: [PATCH] Add APIs for marshalling credentials Faciliate KCM daemon implementations by providing functions to deserialize and reserialize credentials in the FILE v4 format. [ghudson@mit.edu: minor editorial changes] ticket: 8980 (new) (cherry picked from commit 18ea3bd2fca55b789b7de9c663624bc11d348fa6) --- doc/appdev/refs/api/index.rst | 2 ++ src/include/krb5/krb5.hin | 36 ++++++++++++++++++++++ src/lib/krb5/ccache/ccmarshal.c | 53 +++++++++++++++++++++++++++++++++ src/lib/krb5/ccache/t_marshal.c | 15 +++++++++- src/lib/krb5/libkrb5.exports | 2 ++ src/lib/krb5_32.def | 4 +++ 6 files changed, 111 insertions(+), 1 deletion(-) diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst index 727d9b492..9e03fd386 100644 --- a/doc/appdev/refs/api/index.rst +++ b/doc/appdev/refs/api/index.rst @@ -232,6 +232,7 @@ Rarely used public interfaces krb5_kt_remove_entry.rst krb5_kt_start_seq_get.rst krb5_make_authdata_kdc_issued.rst + krb5_marshal_credentials.rst krb5_merge_authdata.rst krb5_mk_1cred.rst krb5_mk_error.rst @@ -285,6 +286,7 @@ Rarely used public interfaces krb5_tkt_creds_get_times.rst krb5_tkt_creds_init.rst krb5_tkt_creds_step.rst + krb5_unmarshal_credentials.rst krb5_verify_init_creds.rst krb5_verify_init_creds_opt_init.rst krb5_verify_init_creds_opt_set_ap_req_nofail.rst diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index 63e67a2ba..c26dde535 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -3125,6 +3125,42 @@ krb5_get_credentials(krb5_context context, krb5_flags options, krb5_ccache ccache, krb5_creds *in_creds, krb5_creds **out_creds); +/** + * Serialize a @c krb5_creds object. + * + * @param [in] context Library context + * @param [in] creds The credentials object to serialize + * @param [out] data_out The serialized credentials + * + * Serialize @a creds in the format used by the FILE ccache format (vesion 4) + * and KCM ccache protocol. + * + * Use krb5_free_data() to free @a data_out when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds, + krb5_data **data_out); + +/** + * Deserialize a @c krb5_creds object. + * + * @param [in] context Library context + * @param [in] data The serialized credentials + * @param [out] creds_out The resulting creds object + * + * Deserialize @a data to credentials in the format used by the FILE ccache + * format (vesion 4) and KCM ccache protocol. + * + * Use krb5_free_creds() to free @a creds_out when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_unmarshal_credentials(krb5_context context, const krb5_data *data, + krb5_creds **creds_out); + /** @deprecated Replaced by krb5_get_validated_creds. */ krb5_error_code KRB5_CALLCONV krb5_get_credentials_validate(krb5_context context, krb5_flags options, diff --git a/src/lib/krb5/ccache/ccmarshal.c b/src/lib/krb5/ccache/ccmarshal.c index ae634ccab..ab284e721 100644 --- a/src/lib/krb5/ccache/ccmarshal.c +++ b/src/lib/krb5/ccache/ccmarshal.c @@ -515,3 +515,56 @@ k5_marshal_mcred(struct k5buf *buf, krb5_creds *mcred) if (mcred->second_ticket.length > 0) put_data(buf, version, &mcred->second_ticket); } + +krb5_error_code KRB5_CALLCONV +krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds, + krb5_data **data_out) +{ + krb5_error_code ret; + krb5_data *data; + struct k5buf buf; + + *data_out = NULL; + + data = k5alloc(sizeof(krb5_data), &ret); + if (ret) + return ret; + + k5_buf_init_dynamic(&buf); + k5_marshal_cred(&buf, 4, in_creds); + + ret = k5_buf_status(&buf); + if (ret) { + free(data); + return ret; + } + + /* Steal payload from buf. */ + *data = make_data(buf.data, buf.len); + *data_out = data; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_unmarshal_credentials(krb5_context context, const krb5_data *data, + krb5_creds **creds_out) +{ + krb5_error_code ret; + krb5_creds *creds; + + *creds_out = NULL; + + creds = k5alloc(sizeof(krb5_creds), &ret); + if (ret) + return ret; + + ret = k5_unmarshal_cred((unsigned char *)data->data, data->length, 4, + creds); + if (ret) { + free(creds); + return ret; + } + + *creds_out = creds; + return 0; +} diff --git a/src/lib/krb5/ccache/t_marshal.c b/src/lib/krb5/ccache/t_marshal.c index bd0284afa..96e0931a2 100644 --- a/src/lib/krb5/ccache/t_marshal.c +++ b/src/lib/krb5/ccache/t_marshal.c @@ -268,13 +268,14 @@ main(int argc, char **argv) krb5_context context; krb5_ccache cache; krb5_principal princ; - krb5_creds cred1, cred2; + krb5_creds cred1, cred2, *alloc_cred; krb5_cc_cursor cursor; const char *filename; char *ccname, filebuf[256]; int version, fd; const struct test *t; struct k5buf buf; + krb5_data ser_data, *alloc_data; if (argc != 2) abort(); @@ -285,6 +286,18 @@ main(int argc, char **argv) if (krb5_init_context(&context) != 0) abort(); + /* Test public functions for unmarshalling and marshalling. */ + ser_data = make_data((char *)tests[3].cred1, tests[3].cred1len); + if (krb5_unmarshal_credentials(context, &ser_data, &alloc_cred) != 0) + abort(); + verify_cred1(alloc_cred); + if (krb5_marshal_credentials(context, alloc_cred, &alloc_data) != 0) + abort(); + assert(alloc_data->length == tests[3].cred1len); + assert(memcmp(tests[3].cred1, alloc_data->data, alloc_data->length) == 0); + krb5_free_data(context, alloc_data); + krb5_free_creds(context, alloc_cred); + for (version = FIRST_VERSION; version <= 4; version++) { t = &tests[version - 1]; diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 2d9d56530..adbfa332b 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -489,6 +489,7 @@ krb5_lock_file krb5_make_authdata_kdc_issued krb5_make_full_ipaddr krb5_make_fulladdr +krb5_marshal_credentials krb5_mcc_ops krb5_merge_authdata krb5_mk_1cred @@ -592,6 +593,7 @@ krb5_timeofday krb5_timestamp_to_sfstring krb5_timestamp_to_string krb5_unlock_file +krb5_unmarshal_credentials krb5_unpack_full_ipaddr krb5_unparse_name krb5_unparse_name_ext diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def index 4953907aa..60b8dd311 100644 --- a/src/lib/krb5_32.def +++ b/src/lib/krb5_32.def @@ -503,3 +503,7 @@ EXPORTS ; new in 1.19 k5_cc_store_primary_cred @470 ; PRIVATE k5_kt_have_match @471 ; PRIVATE GSSAPI + +; new in 1.20 + krb5_marshal_credentials @472 + krb5_unmarshal_credentials @473