krb5 commit: Add APIs for marshalling credentials

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/18ea3bd2fca55b789b7de9c663624bc11d348fa6
commit 18ea3bd2fca55b789b7de9c663624bc11d348fa6
Author: Robbie Harwood <[email protected]>
Date:   Thu Jan 14 18:13:09 2021 -0500

    Add APIs for marshalling credentials
    
    Faciliate KCM daemon implementations by providing functions to
    deserialize and reserialize credentials in the FILE v4 format.
    
    [[email protected]: minor editorial changes]
    
    ticket: 8980 (new)

 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 deletions(-)

diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst
index 727d9b4..9e03fd3 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 045334a..6a01ed1 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -3119,6 +3119,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 ae634cc..ab284e7 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 bd0284a..96e0931a 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 32cef6a..d5a0356 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -490,6 +490,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 4953907..60b8dd3 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.