krb5 commit: Refactor and move CCAPI utility functions

ghudson at mit.edu ghudson at mit.edu
Wed May 18 17:38:19 EDT 2022


https://github.com/krb5/krb5/commit/f81fda346f07c8d67e549cb90bcbdc3c24e5dd5d
commit f81fda346f07c8d67e549cb90bcbdc3c24e5dd5d
Author: Greg Hudson <ghudson at mit.edu>
Date:   Thu Feb 24 01:24:23 2022 -0500

    Refactor and move CCAPI utility functions
    
    Move the CCAPI credential transiation functions up a layer and
    refactor them to current practices.

 src/lib/krb5/ccache/Makefile.in        |   7 +-
 src/lib/krb5/ccache/ccapi/Makefile.in  |   5 +-
 src/lib/krb5/ccache/ccapi/deps         |   6 +-
 src/lib/krb5/ccache/ccapi/stdcc.c      |  11 +-
 src/lib/krb5/ccache/ccapi/stdcc_util.c | 528 ---------------------------------
 src/lib/krb5/ccache/ccapi/stdcc_util.h |  31 --
 src/lib/krb5/ccache/ccapi_util.c       | 425 ++++++++++++++++++++++++++
 src/lib/krb5/ccache/ccapi_util.h       |  50 ++++
 src/lib/krb5/ccache/deps               |  12 +
 9 files changed, 500 insertions(+), 575 deletions(-)

diff --git a/src/lib/krb5/ccache/Makefile.in b/src/lib/krb5/ccache/Makefile.in
index eaff6d2d9..9d29ec51d 100644
--- a/src/lib/krb5/ccache/Makefile.in
+++ b/src/lib/krb5/ccache/Makefile.in
@@ -25,6 +25,7 @@ KCMRPC_OBJ = $(KCMRPC_OBJ- at OSX@)
 
 
 STLIBOBJS= \
+	ccapi_util.o \
 	ccbase.o \
 	cccopy.o \
 	cccursor.o \
@@ -44,7 +45,8 @@ STLIBOBJS= \
 	ccfns.o \
 	$(KCMRPC_OBJ)
 
-OBJS=	$(OUTPRE)ccbase.$(OBJEXT) \
+OBJS=	$(OUTPRE)ccapi_util.$(OBJEXT) \
+	$(OUTPRE)ccbase.$(OBJEXT) \
 	$(OUTPRE)cccopy.$(OBJEXT) \
 	$(OUTPRE)cccursor.$(OBJEXT) \
 	$(OUTPRE)ccdefault.$(OBJEXT) \
@@ -63,7 +65,8 @@ OBJS=	$(OUTPRE)ccbase.$(OBJEXT) \
 	$(OUTPRE)ccfns.$(OBJEXT) \
 	$(MSLSA_OBJ)
 
-SRCS=	$(srcdir)/ccbase.c \
+SRCS=	$(srcdir)/ccapi_util.c \
+	$(srcdir)/ccbase.c \
 	$(srcdir)/cccopy.c \
 	$(srcdir)/cccursor.c \
 	$(srcdir)/ccdefault.c \
diff --git a/src/lib/krb5/ccache/ccapi/Makefile.in b/src/lib/krb5/ccache/ccapi/Makefile.in
index c842b498e..2e379e461 100644
--- a/src/lib/krb5/ccache/ccapi/Makefile.in
+++ b/src/lib/krb5/ccache/ccapi/Makefile.in
@@ -11,12 +11,11 @@ DEFINES= -DUSE_CCAPI
 
 STLIBOBJS 	= \
 	stdcc.o \
-	stdcc_util.o \
 	winccld.o
 
-OBJS 	= $(OUTPRE)stdcc.$(OBJEXT) $(OUTPRE)stdcc_util.$(OBJEXT) $(OUTPRE)winccld.$(OBJEXT)
+OBJS 	= $(OUTPRE)stdcc.$(OBJEXT) $(OUTPRE)winccld.$(OBJEXT)
 
-SRCS 	= $(srcdir)/stdcc.c $(srcdir)/stdcc_util.c $(srcdir)/winccld.c
+SRCS 	= $(srcdir)/stdcc.c $(srcdir)/winccld.c
 
 ##DOS##LIBOBJS = $(OBJS)
 
diff --git a/src/lib/krb5/ccache/ccapi/deps b/src/lib/krb5/ccache/ccapi/deps
index 7df6d6852..c3ef7d0d1 100644
--- a/src/lib/krb5/ccache/ccapi/deps
+++ b/src/lib/krb5/ccache/ccapi/deps
@@ -10,9 +10,5 @@ stdcc.so stdcc.po $(OUTPRE)stdcc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/locate_plugin.h \
   $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h stdcc.c stdcc.h stdcc_util.h
-stdcc_util.so stdcc_util.po $(OUTPRE)stdcc_util.$(OBJEXT): \
-  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
-  $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
-  $(top_srcdir)/include/krb5.h stdcc_util.c stdcc_util.h
+  $(top_srcdir)/include/socket-utils.h stdcc.c stdcc.h
 winccld.so winccld.po $(OUTPRE)winccld.$(OBJEXT): winccld.c
diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c
index bb13eb574..427b3296c 100644
--- a/src/lib/krb5/ccache/ccapi/stdcc.c
+++ b/src/lib/krb5/ccache/ccapi/stdcc.c
@@ -33,8 +33,8 @@
 
 #include "k5-int.h"
 #include "../cc-int.h"
+#include "../ccapi_util.h"
 #include "stdcc.h"
-#include "stdcc_util.h"
 #include "string.h"
 #include <stdio.h>
 
@@ -464,7 +464,7 @@ krb5_stdccv3_store (krb5_context context, krb5_ccache id, krb5_creds *creds )
 
     if (!err) {
         /* copy the fields from the almost identical structures */
-        err = copy_krb5_creds_to_cc_cred_union (context, creds, &cred_union);
+        err = k5_krb5_to_ccapi_creds (context, creds, &cred_union);
     }
 
     if (!err) {
@@ -475,7 +475,7 @@ krb5_stdccv3_store (krb5_context context, krb5_ccache id, krb5_creds *creds )
         cache_changed();
     }
 
-    if (cred_union) { cred_union_release (cred_union); }
+    if (cred_union) { k5_release_ccapi_cred (cred_union); }
 
     return cc_err_xlate (err);
 }
@@ -537,7 +537,7 @@ krb5_stdccv3_next_cred (krb5_context context,
         err = cc_credentials_iterator_next (iterator, &credentials);
 
         if (!err && (credentials->data->version == cc_credentials_v5)) {
-            copy_cc_cred_union_to_krb5_creds(context, credentials->data, creds);
+            err = k5_ccapi_to_krb5_creds (context, credentials->data, creds);
             break;
         }
     }
@@ -787,8 +787,7 @@ krb5_stdccv3_remove (krb5_context context,
         if (!err && (credentials->data->version == cc_credentials_v5)) {
             krb5_creds creds;
 
-            err = copy_cc_cred_union_to_krb5_creds(context,
-                                                   credentials->data, &creds);
+            err = k5_ccapi_to_krb5_creds (context, credentials->data, &creds);
 
             if (!err) {
                 found = krb5int_cc_creds_match_request(context,
diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.c b/src/lib/krb5/ccache/ccapi/stdcc_util.c
deleted file mode 100644
index 91f2bd5a7..000000000
--- a/src/lib/krb5/ccache/ccapi/stdcc_util.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * stdcc_util.c
- * utility functions used in implementing the ccache api for krb5
- * not publicly exported
- * Frank Dabek, July 1998
- */
-
-#if defined(_WIN32) || defined(USE_CCAPI)
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#if defined(_WIN32)
-#include <malloc.h>
-#endif
-
-#include "k5-int.h"
-#include "stdcc_util.h"
-#ifdef _WIN32                   /* it's part of krb5.h everywhere else */
-#include "kv5m_err.h"
-#endif
-
-#define fieldSize 255
-
-static void
-free_cc_array (cc_data **io_cc_array)
-{
-    if (io_cc_array) {
-        unsigned int i;
-
-        for (i = 0; io_cc_array[i]; i++) {
-            if (io_cc_array[i]->data) { free (io_cc_array[i]->data); }
-            free (io_cc_array[i]);
-        }
-        free (io_cc_array);
-    }
-}
-
-static krb5_error_code
-copy_cc_array_to_addresses (krb5_context in_context,
-                            cc_data **in_cc_array,
-                            krb5_address ***out_addresses)
-{
-    krb5_error_code err = 0;
-
-    if (in_cc_array == NULL) {
-        *out_addresses = NULL;
-
-    } else {
-        unsigned int count, i;
-        krb5_address **addresses = NULL;
-
-        /* get length of array */
-        for (count = 0; in_cc_array[count]; count++);
-        addresses = (krb5_address **) malloc (sizeof (*addresses) * (count + 1));
-        if (!addresses) { err = KRB5_CC_NOMEM; }
-
-        for (i = 0; !err && i < count; i++) {
-            addresses[i] = (krb5_address *) malloc (sizeof (krb5_address));
-            if (!addresses[i]) { err = KRB5_CC_NOMEM; }
-
-            if (!err) {
-                addresses[i]->contents = (krb5_octet *) malloc (sizeof (krb5_octet) *
-                                                                in_cc_array[i]->length);
-                if (!addresses[i]->contents) { err = KRB5_CC_NOMEM; }
-            }
-
-            if (!err) {
-                addresses[i]->magic = KV5M_ADDRESS;
-                addresses[i]->addrtype = in_cc_array[i]->type;
-                addresses[i]->length = in_cc_array[i]->length;
-                memcpy (addresses[i]->contents,
-                        in_cc_array[i]->data, in_cc_array[i]->length);
-            }
-        }
-
-        if (!err) {
-            addresses[i] = NULL; /* terminator */
-            *out_addresses = addresses;
-            addresses = NULL;
-        }
-
-        if (addresses) { krb5_free_addresses (in_context, addresses); }
-    }
-
-    return err;
-}
-
-static krb5_error_code
-copy_cc_array_to_authdata (krb5_context in_context,
-                           cc_data **in_cc_array,
-                           krb5_authdata ***out_authdata)
-{
-    krb5_error_code err = 0;
-
-    if (in_cc_array == NULL) {
-        *out_authdata = NULL;
-
-    } else {
-        unsigned int count, i;
-        krb5_authdata **authdata = NULL;
-
-        /* get length of array */
-        for (count = 0; in_cc_array[count]; count++);
-        authdata = (krb5_authdata **) malloc (sizeof (*authdata) * (count + 1));
-        if (!authdata) { err = KRB5_CC_NOMEM; }
-
-        for (i = 0; !err && i < count; i++) {
-            authdata[i] = (krb5_authdata *) malloc (sizeof (krb5_authdata));
-            if (!authdata[i]) { err = KRB5_CC_NOMEM; }
-
-            if (!err) {
-                authdata[i]->contents = (krb5_octet *) malloc (sizeof (krb5_octet) *
-                                                               in_cc_array[i]->length);
-                if (!authdata[i]->contents) { err = KRB5_CC_NOMEM; }
-            }
-
-            if (!err) {
-                authdata[i]->magic = KV5M_AUTHDATA;
-                authdata[i]->ad_type = in_cc_array[i]->type;
-                authdata[i]->length = in_cc_array[i]->length;
-                memcpy (authdata[i]->contents,
-                        in_cc_array[i]->data, in_cc_array[i]->length);
-            }
-        }
-
-        if (!err) {
-            authdata[i] = NULL; /* terminator */
-            *out_authdata = authdata;
-            authdata = NULL;
-        }
-
-        if (authdata) { krb5_free_authdata (in_context, authdata); }
-    }
-
-    return err;
-}
-
-static krb5_error_code
-copy_addresses_to_cc_array (krb5_context in_context,
-                            krb5_address **in_addresses,
-                            cc_data ***out_cc_array)
-{
-    krb5_error_code err = 0;
-
-    if (in_addresses == NULL) {
-        *out_cc_array = NULL;
-
-    } else {
-        unsigned int count, i;
-        cc_data **cc_array = NULL;
-
-        /* get length of array */
-        for (count = 0; in_addresses[count]; count++);
-        cc_array = (cc_data **) malloc (sizeof (*cc_array) * (count + 1));
-        if (!cc_array) { err = KRB5_CC_NOMEM; }
-
-        for (i = 0; !err && i < count; i++) {
-            cc_array[i] = (cc_data *) malloc (sizeof (cc_data));
-            if (!cc_array[i]) { err = KRB5_CC_NOMEM; }
-
-            if (!err) {
-                cc_array[i]->data = malloc (in_addresses[i]->length);
-                if (!cc_array[i]->data) { err = KRB5_CC_NOMEM; }
-            }
-
-            if (!err) {
-                cc_array[i]->type = in_addresses[i]->addrtype;
-                cc_array[i]->length = in_addresses[i]->length;
-                memcpy (cc_array[i]->data, in_addresses[i]->contents, in_addresses[i]->length);
-            }
-        }
-
-        if (!err) {
-            cc_array[i] = NULL; /* terminator */
-            *out_cc_array = cc_array;
-            cc_array = NULL;
-        }
-
-        if (cc_array) { free_cc_array (cc_array); }
-    }
-
-
-    return err;
-}
-
-static krb5_error_code
-copy_authdata_to_cc_array (krb5_context in_context,
-                           krb5_authdata **in_authdata,
-                           cc_data ***out_cc_array)
-{
-    krb5_error_code err = 0;
-
-    if (in_authdata == NULL) {
-        *out_cc_array = NULL;
-
-    } else {
-        unsigned int count, i;
-        cc_data **cc_array = NULL;
-
-        /* get length of array */
-        for (count = 0; in_authdata[count]; count++);
-        cc_array = (cc_data **) malloc (sizeof (*cc_array) * (count + 1));
-        if (!cc_array) { err = KRB5_CC_NOMEM; }
-
-        for (i = 0; !err && i < count; i++) {
-            cc_array[i] = (cc_data *) malloc (sizeof (cc_data));
-            if (!cc_array[i]) { err = KRB5_CC_NOMEM; }
-
-            if (!err) {
-                cc_array[i]->data = malloc (in_authdata[i]->length);
-                if (!cc_array[i]->data) { err = KRB5_CC_NOMEM; }
-            }
-
-            if (!err) {
-                cc_array[i]->type = in_authdata[i]->ad_type;
-                cc_array[i]->length = in_authdata[i]->length;
-                memcpy (cc_array[i]->data, in_authdata[i]->contents, in_authdata[i]->length);
-            }
-        }
-
-        if (!err) {
-            cc_array[i] = NULL; /* terminator */
-            *out_cc_array = cc_array;
-            cc_array = NULL;
-        }
-
-        if (cc_array) { free_cc_array (cc_array); }
-    }
-
-
-    return err;
-}
-
-
-/*
- * copy_cc_credentials_to_krb5_creds
- * - allocate an empty k5 style ticket and copy info from the cc_creds ticket
- */
-
-krb5_error_code
-copy_cc_cred_union_to_krb5_creds (krb5_context in_context,
-                                  const cc_credentials_union *in_cred_union,
-                                  krb5_creds *out_creds)
-{
-    krb5_error_code err = 0;
-    cc_credentials_v5_t *cv5 = NULL;
-    krb5_int32 offset_seconds = 0, offset_microseconds = 0;
-    krb5_principal client = NULL;
-    krb5_principal server = NULL;
-    char *ticket_data = NULL;
-    char *second_ticket_data = NULL;
-    unsigned char *keyblock_contents = NULL;
-    krb5_address **addresses = NULL;
-    krb5_authdata **authdata = NULL;
-
-    if (in_cred_union->version != cc_credentials_v5) {
-        err = KRB5_CC_NOT_KTYPE;
-    } else {
-        cv5 = in_cred_union->credentials.credentials_v5;
-    }
-
-#if TARGET_OS_MAC
-    if (!err) {
-        err = krb5_get_time_offsets (in_context, &offset_seconds, &offset_microseconds);
-    }
-#endif
-
-    if (!err) {
-        err = krb5_parse_name (in_context, cv5->client, &client);
-    }
-
-    if (!err) {
-        err = krb5_parse_name (in_context, cv5->server, &server);
-    }
-
-    if (!err && cv5->keyblock.data) {
-        keyblock_contents = (unsigned char *) malloc (cv5->keyblock.length);
-        if (!keyblock_contents) { err = KRB5_CC_NOMEM; }
-    }
-
-    if (!err && cv5->ticket.data) {
-        ticket_data = (char *) malloc (cv5->ticket.length);
-        if (!ticket_data) { err = KRB5_CC_NOMEM; }
-    }
-
-    if (!err && cv5->second_ticket.data) {
-        second_ticket_data = (char *) malloc (cv5->second_ticket.length);
-        if (!second_ticket_data) { err = KRB5_CC_NOMEM; }
-    }
-
-    if (!err) {
-        /* addresses */
-        err = copy_cc_array_to_addresses (in_context, cv5->addresses, &addresses);
-    }
-
-    if (!err) {
-        /* authdata */
-        err = copy_cc_array_to_authdata (in_context, cv5->authdata, &authdata);
-    }
-
-    if (!err) {
-        /* principals */
-        out_creds->client = client;
-        client = NULL;
-        out_creds->server = server;
-        server = NULL;
-
-        /* copy keyblock */
-        if (cv5->keyblock.data) {
-            memcpy (keyblock_contents, cv5->keyblock.data, cv5->keyblock.length);
-        }
-        out_creds->keyblock.enctype = cv5->keyblock.type;
-        out_creds->keyblock.length = cv5->keyblock.length;
-        out_creds->keyblock.contents = keyblock_contents;
-        keyblock_contents = NULL;
-
-        /* copy times */
-        out_creds->times.authtime   = ts_incr(cv5->authtime, offset_seconds);
-        out_creds->times.starttime  = ts_incr(cv5->starttime, offset_seconds);
-        out_creds->times.endtime    = ts_incr(cv5->endtime, offset_seconds);
-        out_creds->times.renew_till = ts_incr(cv5->renew_till, offset_seconds);
-        out_creds->is_skey          = cv5->is_skey;
-        out_creds->ticket_flags     = cv5->ticket_flags;
-
-        /* first ticket */
-        if (cv5->ticket.data) {
-            memcpy(ticket_data, cv5->ticket.data, cv5->ticket.length);
-        }
-        out_creds->ticket.length = cv5->ticket.length;
-        out_creds->ticket.data = ticket_data;
-        ticket_data = NULL;
-
-        /* second ticket */
-        if (cv5->second_ticket.data) {
-            memcpy(second_ticket_data, cv5->second_ticket.data, cv5->second_ticket.length);
-        }
-        out_creds->second_ticket.length = cv5->second_ticket.length;
-        out_creds->second_ticket.data = second_ticket_data;
-        second_ticket_data = NULL;
-
-        out_creds->addresses = addresses;
-        addresses = NULL;
-
-        out_creds->authdata = authdata;
-        authdata = NULL;
-
-        /* zero out magic number */
-        out_creds->magic = 0;
-    }
-
-    if (addresses)          { krb5_free_addresses (in_context, addresses); }
-    if (authdata)           { krb5_free_authdata (in_context, authdata); }
-    if (keyblock_contents)  { free (keyblock_contents); }
-    if (ticket_data)        { free (ticket_data); }
-    if (second_ticket_data) { free (second_ticket_data); }
-    if (client)             { krb5_free_principal (in_context, client); }
-    if (server)             { krb5_free_principal (in_context, server); }
-
-    return err;
-}
-
-/*
- * copy_krb5_creds_to_cc_credentials
- * - analogous to above but in the reverse direction
- */
-krb5_error_code
-copy_krb5_creds_to_cc_cred_union (krb5_context in_context,
-                                  krb5_creds *in_creds,
-                                  cc_credentials_union **out_cred_union)
-{
-    krb5_error_code err = 0;
-    cc_credentials_union *cred_union = NULL;
-    cc_credentials_v5_t *cv5 = NULL;
-    char *client = NULL;
-    char *server = NULL;
-    unsigned char *ticket_data = NULL;
-    unsigned char *second_ticket_data = NULL;
-    unsigned char *keyblock_data = NULL;
-    krb5_int32 offset_seconds = 0, offset_microseconds = 0;
-    cc_data **cc_address_array = NULL;
-    cc_data **cc_authdata_array = NULL;
-
-    if (out_cred_union == NULL) { err = KRB5_CC_NOMEM; }
-
-#if TARGET_OS_MAC
-    if (!err) {
-        err = krb5_get_time_offsets (in_context, &offset_seconds, &offset_microseconds);
-    }
-#endif
-
-    if (!err) {
-        cred_union = (cc_credentials_union *) malloc (sizeof (*cred_union));
-        if (!cred_union) { err = KRB5_CC_NOMEM; }
-    }
-
-    if (!err) {
-        cv5 = (cc_credentials_v5_t *) malloc (sizeof (*cv5));
-        if (!cv5) { err = KRB5_CC_NOMEM; }
-    }
-
-    if (!err) {
-        err = krb5_unparse_name (in_context, in_creds->client, &client);
-    }
-
-    if (!err) {
-        err = krb5_unparse_name (in_context, in_creds->server, &server);
-    }
-
-    if (!err && in_creds->keyblock.contents) {
-        keyblock_data = (unsigned char *) malloc (in_creds->keyblock.length);
-        if (!keyblock_data) { err = KRB5_CC_NOMEM; }
-    }
-
-    if (!err && in_creds->ticket.data) {
-        ticket_data = (unsigned char *) malloc (in_creds->ticket.length);
-        if (!ticket_data) { err = KRB5_CC_NOMEM; }
-    }
-
-    if (!err && in_creds->second_ticket.data) {
-        second_ticket_data = (unsigned char *) malloc (in_creds->second_ticket.length);
-        if (!second_ticket_data) { err = KRB5_CC_NOMEM; }
-    }
-
-    if (!err) {
-        err = copy_addresses_to_cc_array (in_context, in_creds->addresses, &cc_address_array);
-    }
-
-    if (!err) {
-        err = copy_authdata_to_cc_array (in_context, in_creds->authdata, &cc_authdata_array);
-    }
-
-    if (!err) {
-        /* principals */
-        cv5->client = client;
-        client = NULL;
-        cv5->server = server;
-        server = NULL;
-
-        /* copy more fields */
-        if (in_creds->keyblock.contents) {
-            memcpy(keyblock_data, in_creds->keyblock.contents, in_creds->keyblock.length);
-        }
-        cv5->keyblock.type = in_creds->keyblock.enctype;
-        cv5->keyblock.length = in_creds->keyblock.length;
-        cv5->keyblock.data = keyblock_data;
-        keyblock_data = NULL;
-
-        cv5->authtime = ts_incr(in_creds->times.authtime, -offset_seconds);
-        cv5->starttime = ts_incr(in_creds->times.starttime, -offset_seconds);
-        cv5->endtime = ts_incr(in_creds->times.endtime, -offset_seconds);
-        cv5->renew_till = ts_incr(in_creds->times.renew_till, -offset_seconds);
-        cv5->is_skey = in_creds->is_skey;
-        cv5->ticket_flags = in_creds->ticket_flags;
-
-        if (in_creds->ticket.data) {
-            memcpy (ticket_data, in_creds->ticket.data, in_creds->ticket.length);
-        }
-        cv5->ticket.length = in_creds->ticket.length;
-        cv5->ticket.data = ticket_data;
-        ticket_data = NULL;
-
-        if (in_creds->second_ticket.data) {
-            memcpy (second_ticket_data, in_creds->second_ticket.data, in_creds->second_ticket.length);
-        }
-        cv5->second_ticket.length = in_creds->second_ticket.length;
-        cv5->second_ticket.data = second_ticket_data;
-        second_ticket_data = NULL;
-
-        cv5->addresses = cc_address_array;
-        cc_address_array = NULL;
-
-        cv5->authdata = cc_authdata_array;
-        cc_authdata_array = NULL;
-
-        /* Set up the structures to return to the caller */
-        cred_union->version = cc_credentials_v5;
-        cred_union->credentials.credentials_v5 = cv5;
-        cv5 = NULL;
-
-        *out_cred_union = cred_union;
-        cred_union = NULL;
-    }
-
-    if (cc_address_array)   { free_cc_array (cc_address_array); }
-    if (cc_authdata_array)  { free_cc_array (cc_authdata_array); }
-    if (keyblock_data)      { free (keyblock_data); }
-    if (ticket_data)        { free (ticket_data); }
-    if (second_ticket_data) { free (second_ticket_data); }
-    if (client)             { krb5_free_unparsed_name (in_context, client); }
-    if (server)             { krb5_free_unparsed_name (in_context, server); }
-    if (cv5)                { free (cv5); }
-    if (cred_union)         { free (cred_union); }
-
-    return err;
-}
-
-krb5_error_code
-cred_union_release (cc_credentials_union *in_cred_union)
-{
-    if (in_cred_union) {
-        if (in_cred_union->version == cc_credentials_v5 &&
-            in_cred_union->credentials.credentials_v5) {
-            cc_credentials_v5_t *cv5 = in_cred_union->credentials.credentials_v5;
-
-            /* should use krb5_free_unparsed_name but we have no context */
-            if (cv5->client) { free (cv5->client); }
-            if (cv5->server) { free (cv5->server); }
-
-            if (cv5->keyblock.data)      { free (cv5->keyblock.data); }
-            if (cv5->ticket.data)        { free (cv5->ticket.data); }
-            if (cv5->second_ticket.data) { free (cv5->second_ticket.data); }
-
-            free_cc_array (cv5->addresses);
-            free_cc_array (cv5->authdata);
-
-            free (cv5);
-
-        }
-        free ((cc_credentials_union *) in_cred_union);
-    }
-
-    return 0;
-}
-
-#endif /* defined(_WIN32) || defined(USE_CCAPI) */
diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.h b/src/lib/krb5/ccache/ccapi/stdcc_util.h
deleted file mode 100644
index 34e438dfd..000000000
--- a/src/lib/krb5/ccache/ccapi/stdcc_util.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* stdcc_util.h
- *
- * Frank Dabek, July 1998
- */
-
-#if defined(_WIN32) || defined(USE_CCAPI)
-
-#include "autoconf.h"
-
-#include <CredentialsCache.h>
-
-#include "krb5.h"
-
-/* prototypes for private functions declared in stdcc_util.c */
-krb5_error_code
-copy_cc_cred_union_to_krb5_creds (krb5_context in_context,
-                                  const cc_credentials_union *in_cred_union,
-                                  krb5_creds *out_creds);
-krb5_error_code
-copy_krb5_creds_to_cc_cred_union (krb5_context in_context,
-                                  krb5_creds *in_creds,
-                                  cc_credentials_union **out_cred_union);
-
-krb5_error_code
-cred_union_release (cc_credentials_union *in_cred_union);
-
-#define kAddressArray 4
-#define kAuthDataArray 5
-
-#endif /* defined(_WIN32) || defined(USE_CCAPI) */
diff --git a/src/lib/krb5/ccache/ccapi_util.c b/src/lib/krb5/ccache/ccapi_util.c
new file mode 100644
index 000000000..76f686c9f
--- /dev/null
+++ b/src/lib/krb5/ccache/ccapi_util.c
@@ -0,0 +1,425 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/ccache/ccapi_util.c - conversion functions for CCAPI creds */
+/*
+ * Copyright (C) 2022 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cc-int.h"
+#include "ccapi_util.h"
+
+#if defined(USE_CCAPI)
+
+static void
+free_cc_data_list(cc_data **list)
+{
+    size_t i;
+
+    for (i = 0; list != NULL && list[i] != NULL; i++) {
+        free(list[i]->data);
+        free(list[i]);
+    }
+    free(list);
+}
+
+static krb5_error_code
+cc_data_list_to_addresses(krb5_context context, cc_data **list,
+                          krb5_address ***addrs_out)
+{
+    krb5_error_code ret;
+    size_t count, i;
+    krb5_address **addrs = NULL;
+
+    *addrs_out = NULL;
+    if (list == NULL)
+        return 0;
+
+    for (count = 0; list[count]; count++);
+    addrs = k5calloc(count + 1, sizeof(*addrs), &ret);
+    if (addrs == NULL)
+        return ret;
+
+    for (i = 0; i < count; i++) {
+        addrs[i] = k5alloc(sizeof(*addrs[i]), &ret);
+        if (addrs[i] == NULL)
+            goto cleanup;
+
+        addrs[i]->contents = k5memdup(list[i]->data, list[i]->length, &ret);
+        if (addrs[i]->contents == NULL)
+            goto cleanup;
+        addrs[i]->length = list[i]->length;
+        addrs[i]->addrtype = list[i]->type;
+        addrs[i]->magic = KV5M_ADDRESS;
+    }
+
+    *addrs_out = addrs;
+    addrs = NULL;
+
+cleanup:
+    krb5_free_addresses(context, addrs);
+    return ret;
+}
+
+static krb5_error_code
+cc_data_list_to_authdata(krb5_context context, cc_data **list,
+                         krb5_authdata ***authdata_out)
+{
+    krb5_error_code ret;
+    size_t count, i;
+    krb5_authdata **authdata = NULL;
+
+    *authdata_out = NULL;
+    if (list == NULL)
+        return 0;
+
+    for (count = 0; list[count]; count++);
+    authdata = k5calloc(count + 1, sizeof(*authdata), &ret);
+    if (authdata == NULL)
+        return ret;
+
+    for (i = 0; i < count; i++) {
+        authdata[i] = k5alloc(sizeof(*authdata[i]), &ret);
+        if (authdata[i] == NULL)
+            goto cleanup;
+
+        authdata[i]->contents = k5memdup(list[i]->data, list[i]->length, &ret);
+        if (authdata[i]->contents == NULL)
+            goto cleanup;
+        authdata[i]->length = list[i]->length;
+        authdata[i]->ad_type = list[i]->type;
+        authdata[i]->magic = KV5M_AUTHDATA;
+    }
+
+    *authdata_out = authdata;
+    authdata = NULL;
+
+cleanup:
+    krb5_free_authdata(context, authdata);
+    return ret;
+}
+
+static krb5_error_code
+addresses_to_cc_data_list(krb5_context context, krb5_address **addrs,
+                          cc_data ***list_out)
+{
+    krb5_error_code ret;
+    size_t count, i;
+    cc_data **list = NULL;
+
+    *list_out = NULL;
+    if (addrs == NULL)
+        return 0;
+
+    for (count = 0; addrs[count]; count++);
+    list = k5calloc(count + 1, sizeof(*list), &ret);
+    if (list == NULL)
+        return ret;
+
+    for (i = 0; i < count; i++) {
+        list[i] = k5alloc(sizeof(*list[i]), &ret);
+        if (list[i] == NULL)
+            goto cleanup;
+
+        list[i]->data = k5memdup(addrs[i]->contents, addrs[i]->length, &ret);
+        if (list[i]->data == NULL)
+            goto cleanup;
+        list[i]->length = addrs[i]->length;
+        list[i]->type = addrs[i]->addrtype;
+    }
+
+    *list_out = list;
+    list = NULL;
+
+cleanup:
+    free_cc_data_list(list);
+    return ret;
+}
+
+static krb5_error_code
+authdata_to_cc_data_list(krb5_context context, krb5_authdata **authdata,
+                         cc_data ***list_out)
+{
+    krb5_error_code ret;
+    size_t count, i;
+    cc_data **list = NULL;
+
+    *list_out = NULL;
+    if (authdata == NULL)
+        return 0;
+
+    for (count = 0; authdata[count]; count++);
+    list = k5calloc(count + 1, sizeof(*list), &ret);
+    if (list == NULL)
+        return ret;
+
+    for (i = 0; i < count; i++) {
+        list[i] = k5alloc(sizeof(*list[i]), &ret);
+        if (list[i] == NULL)
+            goto cleanup;
+
+        list[i]->data = k5memdup(authdata[i]->contents, authdata[i]->length,
+                                 &ret);
+        if (list[i]->data == NULL)
+            goto cleanup;
+        list[i]->length = authdata[i]->length;
+        list[i]->type = authdata[i]->ad_type;
+    }
+
+    *list_out = list;
+    list = NULL;
+
+cleanup:
+    free_cc_data_list(list);
+    return ret;
+}
+
+krb5_error_code
+k5_ccapi_to_krb5_creds(krb5_context context,
+                       const cc_credentials_union *ccapi_cred,
+                       krb5_creds *cred_out)
+{
+    krb5_error_code ret;
+    cc_credentials_v5_t *cv5 = NULL;
+    krb5_principal client = NULL;
+    krb5_principal server = NULL;
+    char *ticket_data = NULL;
+    char *second_ticket_data = NULL;
+    uint8_t *keyblock_contents = NULL;
+    krb5_address **addresses = NULL;
+    krb5_authdata **authdata = NULL;
+
+    if (ccapi_cred->version != cc_credentials_v5)
+        return KRB5_CC_NOT_KTYPE;
+
+    cv5 = ccapi_cred->credentials.credentials_v5;
+
+    ret = krb5_parse_name(context, cv5->client, &client);
+    if (ret)
+        goto cleanup;
+    ret = krb5_parse_name(context, cv5->server, &server);
+    if (ret)
+        goto cleanup;
+
+    if (cv5->keyblock.length > 0) {
+        keyblock_contents = k5memdup(cv5->keyblock.data, cv5->keyblock.length,
+                                     &ret);
+        if (keyblock_contents == NULL)
+            goto cleanup;
+    }
+
+    if (cv5->ticket.length > 0) {
+        ticket_data = k5memdup(cv5->ticket.data, cv5->ticket.length, &ret);
+        if (ticket_data == NULL)
+            goto cleanup;
+    }
+
+    if (cv5->second_ticket.length > 0) {
+        second_ticket_data = k5memdup(cv5->second_ticket.data,
+                                      cv5->second_ticket.length, &ret);
+        if (second_ticket_data == NULL)
+            goto cleanup;
+    }
+
+    ret = cc_data_list_to_addresses(context, cv5->addresses, &addresses);
+    if (ret)
+        goto cleanup;
+
+    ret = cc_data_list_to_authdata(context, cv5->authdata, &authdata);
+    if (ret)
+        goto cleanup;
+
+    cred_out->client = client;
+    cred_out->server = server;
+    client = server = NULL;
+
+    cred_out->keyblock.magic = KV5M_KEYBLOCK;
+    cred_out->keyblock.enctype = cv5->keyblock.type;
+    cred_out->keyblock.length = cv5->keyblock.length;
+    cred_out->keyblock.contents = keyblock_contents;
+    keyblock_contents = NULL;
+
+    cred_out->times.authtime = cv5->authtime;
+    cred_out->times.starttime = cv5->starttime;
+    cred_out->times.endtime = cv5->endtime;
+    cred_out->times.renew_till = cv5->renew_till;
+    cred_out->is_skey = cv5->is_skey;
+    cred_out->ticket_flags = cv5->ticket_flags;
+
+    cred_out->ticket = make_data(ticket_data, cv5->ticket.length);
+    cred_out->second_ticket = make_data(second_ticket_data,
+                                        cv5->second_ticket.length);
+    ticket_data = second_ticket_data = NULL;
+
+    cred_out->addresses = addresses;
+    addresses = NULL;
+
+    cred_out->authdata = authdata;
+    authdata = NULL;
+
+    cred_out->magic = KV5M_CREDS;
+
+cleanup:
+    krb5_free_principal(context, client);
+    krb5_free_principal(context, server);
+    krb5_free_addresses(context, addresses);
+    krb5_free_authdata(context, authdata);
+    free(keyblock_contents);
+    free(ticket_data);
+    free(second_ticket_data);
+    return ret;
+}
+
+krb5_error_code
+k5_krb5_to_ccapi_creds(krb5_context context, krb5_creds *cred,
+                       cc_credentials_union **ccapi_cred_out)
+{
+    krb5_error_code ret;
+    cc_credentials_union *cred_union = NULL;
+    cc_credentials_v5_t *cv5 = NULL;
+    char *client = NULL, *server = NULL;
+    uint8_t *ticket_data = NULL, *second_ticket_data = NULL;
+    uint8_t *keyblock_data = NULL;
+    cc_data **addr_list = NULL, **authdata_list = NULL;
+
+    cred_union = k5alloc(sizeof(*cred_union), &ret);
+    if (cred_union == NULL)
+        goto cleanup;
+
+    cv5 = k5alloc(sizeof(*cv5), &ret);
+    if (cv5 == NULL)
+        goto cleanup;
+
+    ret = krb5_unparse_name(context, cred->client, &client);
+    if (ret)
+        goto cleanup;
+    ret = krb5_unparse_name(context, cred->server, &server);
+    if (ret)
+        goto cleanup;
+
+    if (cred->keyblock.length > 0) {
+        keyblock_data = k5memdup(cred->keyblock.contents,
+                                 cred->keyblock.length, &ret);
+        if (keyblock_data == NULL)
+            goto cleanup;
+    }
+
+    if (cred->ticket.length > 0) {
+        ticket_data = k5memdup0(cred->ticket.data, cred->ticket.length, &ret);
+        if (ticket_data == NULL)
+            goto cleanup;
+    }
+
+    if (cred->second_ticket.length > 0) {
+        second_ticket_data = k5memdup0(cred->second_ticket.data,
+                                       cred->second_ticket.length, &ret);
+        if (second_ticket_data == NULL)
+            goto cleanup;
+    }
+
+    ret = addresses_to_cc_data_list(context, cred->addresses, &addr_list);
+    if (ret)
+        goto cleanup;
+
+    ret = authdata_to_cc_data_list(context, cred->authdata, &authdata_list);
+    if (ret)
+        goto cleanup;
+
+    cv5->client = client;
+    cv5->server = server;
+    client = server = NULL;
+
+    cv5->keyblock.type = cred->keyblock.enctype;
+    cv5->keyblock.length = cred->keyblock.length;
+    cv5->keyblock.data = keyblock_data;
+    keyblock_data = NULL;
+
+    cv5->authtime = cred->times.authtime;
+    cv5->starttime = cred->times.starttime;
+    cv5->endtime = cred->times.endtime;
+    cv5->renew_till = cred->times.renew_till;
+    cv5->is_skey = cred->is_skey;
+    cv5->ticket_flags = cred->ticket_flags;
+
+    cv5->ticket.length = cred->ticket.length;
+    cv5->ticket.data = ticket_data;
+    cv5->second_ticket.length = cred->second_ticket.length;
+    cv5->second_ticket.data = second_ticket_data;
+    ticket_data = second_ticket_data = NULL;
+
+    cv5->addresses = addr_list;
+    addr_list = NULL;
+
+    cv5->authdata = authdata_list;
+    authdata_list = NULL;
+
+    cred_union->version = cc_credentials_v5;
+    cred_union->credentials.credentials_v5 = cv5;
+    cv5 = NULL;
+
+    *ccapi_cred_out = cred_union;
+    cred_union = NULL;
+
+cleanup:
+    free_cc_data_list(addr_list);
+    free_cc_data_list(authdata_list);
+    free(keyblock_data);
+    free(ticket_data);
+    free(second_ticket_data);
+    krb5_free_unparsed_name(context, client);
+    krb5_free_unparsed_name(context, server);
+    free(cv5);
+    free(cred_union);
+    return ret;
+}
+
+void
+k5_release_ccapi_cred(cc_credentials_union *ccapi_cred)
+{
+    cc_credentials_v5_t *cv5;
+
+    if (ccapi_cred == NULL)
+        return;
+    if (ccapi_cred->version != cc_credentials_v5)
+        return;
+    if (ccapi_cred->credentials.credentials_v5 == NULL)
+        return;
+
+    cv5 = ccapi_cred->credentials.credentials_v5;
+
+    free(cv5->client);
+    free(cv5->server);
+    free(cv5->keyblock.data);
+    free(cv5->ticket.data);
+    free(cv5->second_ticket.data);
+    free_cc_data_list(cv5->addresses);
+    free_cc_data_list(cv5->authdata);
+    free(cv5);
+    free(ccapi_cred);
+}
+
+#endif /* defined(USE_CCAPI) */
diff --git a/src/lib/krb5/ccache/ccapi_util.h b/src/lib/krb5/ccache/ccapi_util.h
new file mode 100644
index 000000000..6a866082b
--- /dev/null
+++ b/src/lib/krb5/ccache/ccapi_util.h
@@ -0,0 +1,50 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/ccache/ccapi_util.c - conversion declarations for CCAPI creds */
+/*
+ * Copyright (C) 2021 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCAPI_UTIL_H
+#define CCAPI_UTIL_H
+
+#include <CredentialsCache.h>
+
+krb5_error_code
+k5_ccapi_to_krb5_creds(krb5_context context,
+                       const cc_credentials_union *ccapi_cred,
+                       krb5_creds *cred_out);
+
+krb5_error_code
+k5_krb5_to_ccapi_creds(krb5_context context, krb5_creds *cred,
+                       cc_credentials_union **ccapi_cred_out);
+
+void
+k5_release_ccapi_cred(cc_credentials_union *ccapi_cred);
+
+#endif /* CCAPI_UTIL_H */
diff --git a/src/lib/krb5/ccache/deps b/src/lib/krb5/ccache/deps
index 919e4758c..1f69e0f93 100644
--- a/src/lib/krb5/ccache/deps
+++ b/src/lib/krb5/ccache/deps
@@ -1,6 +1,18 @@
 #
 # Generated makefile dependencies follow.
 #
+ccapi_util.so ccapi_util.po $(OUTPRE)ccapi_util.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  cc-int.h ccapi_util.c ccapi_util.h
 ccbase.so ccbase.po $(OUTPRE)ccbase.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
   $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \


More information about the cvs-krb5 mailing list