/* ccapi/common/cci_cred_union.c */ /* * Copyright 2006 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #include "cci_common.h" /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_contents_release (cc_data *io_ccdata) { cc_int32 err = ccNoError; if (!io_ccdata && io_ccdata->data) { err = ccErrBadParam; } if (!err) { if (io_ccdata->length) { memset (io_ccdata->data, 0, io_ccdata->length); } free (io_ccdata->data); } return err; } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_release (cc_data *io_ccdata) { cc_int32 err = ccNoError; if (!io_ccdata) { err = ccErrBadParam; } if (!err) { cci_cc_data_contents_release (io_ccdata); free (io_ccdata); } return err; } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_read (cc_data *io_ccdata, k5_ipc_stream io_stream) { cc_int32 err = ccNoError; cc_uint32 type = 0; cc_uint32 length = 0; char *data = NULL; if (!io_stream) { err = cci_check_error (ccErrBadParam); } if (!io_ccdata) { err = cci_check_error (ccErrBadParam); } if (!err) { err = krb5int_ipc_stream_read_uint32 (io_stream, &type); } if (!err) { err = krb5int_ipc_stream_read_uint32 (io_stream, &length); } if (!err && length > 0) { data = malloc (length); if (!data) { err = cci_check_error (ccErrNoMem); } if (!err) { err = krb5int_ipc_stream_read (io_stream, data, length); } } if (!err) { io_ccdata->type = type; io_ccdata->length = length; io_ccdata->data = data; data = NULL; } free (data); return cci_check_error (err); } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_write (cc_data *in_ccdata, k5_ipc_stream io_stream) { cc_int32 err = ccNoError; if (!io_stream) { err = cci_check_error (ccErrBadParam); } if (!in_ccdata) { err = cci_check_error (ccErrBadParam); } if (!err) { err = krb5int_ipc_stream_write_uint32 (io_stream, in_ccdata->type); } if (!err) { err = krb5int_ipc_stream_write_uint32 (io_stream, in_ccdata->length); } if (!err && in_ccdata->length > 0) { err = krb5int_ipc_stream_write (io_stream, in_ccdata->data, in_ccdata->length); } return cci_check_error (err); } #ifdef TARGET_OS_MAC #pragma mark - #endif /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_array_release (cc_data **io_ccdata_array) { cc_int32 err = ccNoError; if (!io_ccdata_array) { err = ccErrBadParam; } if (!err) { cc_uint32 i; for (i = 0; io_ccdata_array && io_ccdata_array[i]; i++) { cci_cc_data_release (io_ccdata_array[i]); } free (io_ccdata_array); } return err; } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_array_read (cc_data ***io_ccdata_array, k5_ipc_stream io_stream) { cc_int32 err = ccNoError; cc_uint32 count = 0; cc_data **array = NULL; cc_uint32 i; if (!io_stream ) { err = cci_check_error (ccErrBadParam); } if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); } if (!err) { err = krb5int_ipc_stream_read_uint32 (io_stream, &count); } if (!err && count > 0) { array = malloc ((count + 1) * sizeof (*array)); if (array) { for (i = 0; i <= count; i++) { array[i] = NULL; } } else { err = cci_check_error (ccErrNoMem); } } if (!err) { for (i = 0; !err && i < count; i++) { array[i] = malloc (sizeof (cc_data)); if (!array[i]) { err = cci_check_error (ccErrNoMem); } if (!err) { err = cci_cc_data_read (array[i], io_stream); } } } if (!err) { *io_ccdata_array = array; array = NULL; } cci_cc_data_array_release (array); return cci_check_error (err); } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_array_write (cc_data **in_ccdata_array, k5_ipc_stream io_stream) { cc_int32 err = ccNoError; cc_uint32 count = 0; if (!io_stream) { err = cci_check_error (ccErrBadParam); } /* in_ccdata_array may be NULL */ if (!err) { for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++); err = krb5int_ipc_stream_write_uint32 (io_stream, count); } if (!err) { cc_uint32 i; for (i = 0; !err && i < count; i++) { err = cci_cc_data_write (in_ccdata_array[i], io_stream); } } return cci_check_error (err); } #ifdef TARGET_OS_MAC #pragma mark - #endif /* ------------------------------------------------------------------------ */ cc_credentials_v5_t cci_credentials_v5_initializer = { NULL, NULL, { 0, 0, NULL }, 0, 0, 0, 0, 0, 0, NULL, { 0, 0, NULL }, { 0, 0, NULL }, NULL }; /* ------------------------------------------------------------------------ */ static cc_uint32 cci_credentials_v5_release (cc_credentials_v5_t *io_v5creds) { cc_int32 err = ccNoError; if (!io_v5creds) { err = ccErrBadParam; } if (!err) { free (io_v5creds->client); free (io_v5creds->server); cci_cc_data_contents_release (&io_v5creds->keyblock); cci_cc_data_array_release (io_v5creds->addresses); cci_cc_data_contents_release (&io_v5creds->ticket); cci_cc_data_contents_release (&io_v5creds->second_ticket); cci_cc_data_array_release (io_v5creds->authdata); free (io_v5creds); } return err; } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_credentials_v5_read (cc_credentials_v5_t **out_v5creds, k5_ipc_stream io_stream) { cc_int32 err = ccNoError; cc_credentials_v5_t *v5creds = NULL; if (!io_stream ) { err = cci_check_error (ccErrBadParam); } if (!out_v5creds) { err = cci_check_error (ccErrBadParam); } if (!err) { v5creds = malloc (sizeof (*v5creds)); if (v5creds) { *v5creds = cci_credentials_v5_initializer; } else { err = cci_check_error (ccErrNoMem); } } if (!err) { err = krb5int_ipc_stream_read_string (io_stream, &v5creds->client); } if (!err) { err = krb5int_ipc_stream_read_string (io_stream, &v5creds->server); } if (!err) { err = cci_cc_data_read (&v5creds->keyblock, io_stream); } if (!err) { err = krb5int_ipc_stream_read_time (io_stream, &v5creds->authtime); } if (!err) { err = krb5int_ipc_stream_read_time (io_stream, &v5creds->starttime); } if (!err) { err = krb5int_ipc_stream_read_time (io_stream, &v5creds->endtime); } if (!err) { err = krb5int_ipc_stream_read_time (io_stream, &v5creds->renew_till); } if (!err) { err = krb5int_ipc_stream_read_uint32 (io_stream, &v5creds->is_skey); } if (!err) { err = krb5int_ipc_stream_read_uint32 (io_stream, &v5creds->ticket_flags); } if (!err) { err = cci_cc_data_array_read (&v5creds->addresses, io_stream); } if (!err) { err = cci_cc_data_read (&v5creds->ticket, io_stream); } if (!err) { err = cci_cc_data_read (&v5creds->second_ticket, io_stream); } if (!err) { err = cci_cc_data_array_read (&v5creds->authdata, io_stream); } if (!err) { *out_v5creds = v5creds; v5creds = NULL; } cci_credentials_v5_release (v5creds); return cci_check_error (err); } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_credentials_v5_write (cc_credentials_v5_t *in_v5creds, k5_ipc_stream io_stream) { cc_int32 err = ccNoError; if (!io_stream ) { err = cci_check_error (ccErrBadParam); } if (!in_v5creds) { err = cci_check_error (ccErrBadParam); } if (!err) { err = krb5int_ipc_stream_write_string (io_stream, in_v5creds->client); } if (!err) { err = krb5int_ipc_stream_write_string (io_stream, in_v5creds->server); } if (!err) { err = cci_cc_data_write (&in_v5creds->keyblock, io_stream); } if (!err) { err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->authtime); } if (!err) { err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->starttime); } if (!err) { err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->endtime); } if (!err) { err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->renew_till); } if (!err) { err = krb5int_ipc_stream_write_uint32 (io_stream, in_v5creds->is_skey); } if (!err) { err = krb5int_ipc_stream_write_uint32 (io_stream, in_v5creds->ticket_flags); } if (!err) { err = cci_cc_data_array_write (in_v5creds->addresses, io_stream); } if (!err) { err = cci_cc_data_write (&in_v5creds->ticket, io_stream); } if (!err) { err = cci_cc_data_write (&in_v5creds->second_ticket, io_stream); } if (!err) { err = cci_cc_data_array_write (in_v5creds->authdata, io_stream); } return cci_check_error (err); } #ifdef TARGET_OS_MAC #pragma mark - #endif /* ------------------------------------------------------------------------ */ cc_uint32 cci_credentials_union_release (cc_credentials_union *io_cred_union) { cc_int32 err = ccNoError; if (!io_cred_union) { err = ccErrBadParam; } if (!err) { if (io_cred_union->version == cc_credentials_v5) { cci_credentials_v5_release (io_cred_union->credentials.credentials_v5); } free (io_cred_union); } return err; } /* ------------------------------------------------------------------------ */ cc_uint32 cci_credentials_union_read (cc_credentials_union **out_credentials_union, k5_ipc_stream io_stream) { cc_int32 err = ccNoError; cc_credentials_union *credentials_union = NULL; if (!io_stream ) { err = cci_check_error (ccErrBadParam); } if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); } if (!err) { credentials_union = calloc (1, sizeof (*credentials_union)); if (!credentials_union) { err = cci_check_error (ccErrNoMem); } } if (!err) { err = krb5int_ipc_stream_read_uint32 (io_stream, &credentials_union->version); } if (!err) { if (credentials_union->version == cc_credentials_v5) { err = cci_credentials_v5_read (&credentials_union->credentials.credentials_v5, io_stream); } else { err = ccErrBadCredentialsVersion; } } if (!err) { *out_credentials_union = credentials_union; credentials_union = NULL; } if (credentials_union) { cci_credentials_union_release (credentials_union); } return cci_check_error (err); } /* ------------------------------------------------------------------------ */ cc_uint32 cci_credentials_union_write (const cc_credentials_union *in_credentials_union, k5_ipc_stream io_stream) { cc_int32 err = ccNoError; if (!io_stream ) { err = cci_check_error (ccErrBadParam); } if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } if (!err) { err = krb5int_ipc_stream_write_uint32 (io_stream, in_credentials_union->version); } if (!err) { if (in_credentials_union->version == cc_credentials_v5) { err = cci_credentials_v5_write (in_credentials_union->credentials.credentials_v5, io_stream); } else { err = ccErrBadCredentialsVersion; } } return cci_check_error (err); } #ifdef TARGET_OS_MAC #pragma mark - #pragma mark -- CCAPI v2 Compat -- #endif /* ------------------------------------------------------------------------ */ cc_credentials_v5_compat cci_credentials_v5_compat_initializer = { NULL, NULL, { 0, 0, NULL }, 0, 0, 0, 0, 0, 0, NULL, { 0, 0, NULL }, { 0, 0, NULL }, NULL }; /* ------------------------------------------------------------------------ */ cc_uint32 cci_cred_union_release (cred_union *io_cred_union) { cc_int32 err = ccNoError; if (!io_cred_union) { err = ccErrBadParam; } if (!err) { if (io_cred_union->cred_type == CC_CRED_V5) { free (io_cred_union->cred.pV5Cred->client); free (io_cred_union->cred.pV5Cred->server); cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->keyblock); cci_cc_data_array_release (io_cred_union->cred.pV5Cred->addresses); cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->ticket); cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->second_ticket); cci_cc_data_array_release (io_cred_union->cred.pV5Cred->authdata); free (io_cred_union->cred.pV5Cred); } free (io_cred_union); } return err; } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_copy_contents (cc_data *io_ccdata, cc_data *in_ccdata) { cc_int32 err = ccNoError; char *data = NULL; if (!io_ccdata) { err = cci_check_error (ccErrBadParam); } if (!in_ccdata) { err = cci_check_error (ccErrBadParam); } if (!err && in_ccdata->length > 0) { data = malloc (in_ccdata->length); if (data) { memcpy (data, in_ccdata->data, in_ccdata->length); } else { err = cci_check_error (ccErrNoMem); } } if (!err) { io_ccdata->type = in_ccdata->type; io_ccdata->length = in_ccdata->length; io_ccdata->data = data; data = NULL; } free (data); return cci_check_error (err); } /* ------------------------------------------------------------------------ */ static cc_uint32 cci_cc_data_array_copy (cc_data ***io_ccdata_array, cc_data **in_ccdata_array) { cc_int32 err = ccNoError; cc_uint32 count = 0; cc_data **array = NULL; cc_uint32 i; if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); } if (!err) { for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++); } if (!err && count > 0) { array = malloc ((count + 1) * sizeof (*array)); if (array) { for (i = 0; i <= count; i++) { array[i] = NULL; } } else { err = cci_check_error (ccErrNoMem); } } if (!err) { for (i = 0; !err && i < count; i++) { array[i] = malloc (sizeof (cc_data)); if (!array[i]) { err = cci_check_error (ccErrNoMem); } if (!err) { err = cci_cc_data_copy_contents (array[i], in_ccdata_array[i]); } } } if (!err) { *io_ccdata_array = array; array = NULL; } cci_cc_data_array_release (array); return cci_check_error (err); } /* ------------------------------------------------------------------------ */ cc_uint32 cci_credentials_union_to_cred_union (const cc_credentials_union *in_credentials_union, cred_union **out_cred_union) { cc_int32 err = ccNoError; cred_union *compat_cred_union = NULL; if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } if (!out_cred_union ) { err = cci_check_error (ccErrBadParam); } if (!err) { compat_cred_union = calloc (1, sizeof (*compat_cred_union)); if (!compat_cred_union) { err = cci_check_error (ccErrNoMem); } } if (!err) { if (in_credentials_union->version == cc_credentials_v5) { cc_credentials_v5_t *v5creds = in_credentials_union->credentials.credentials_v5; cc_credentials_v5_compat *compat_v5creds = NULL; compat_v5creds = malloc (sizeof (*compat_v5creds)); if (compat_v5creds) { *compat_v5creds = cci_credentials_v5_compat_initializer; } else { err = cci_check_error (ccErrNoMem); } if (!err) { if (!v5creds->client) { err = cci_check_error (ccErrBadParam); } else { compat_v5creds->client = strdup (v5creds->client); if (!compat_v5creds->client) { err = cci_check_error (ccErrNoMem); } } } if (!err) { if (!v5creds->server) { err = cci_check_error (ccErrBadParam); } else { compat_v5creds->server = strdup (v5creds->server); if (!compat_v5creds->server) { err = cci_check_error (ccErrNoMem); } } } if (!err) { err = cci_cc_data_copy_contents (&compat_v5creds->keyblock, &v5creds->keyblock); } if (!err) { err = cci_cc_data_array_copy (&compat_v5creds->addresses, v5creds->addresses); } if (!err) { err = cci_cc_data_copy_contents (&compat_v5creds->ticket, &v5creds->ticket); } if (!err) { err = cci_cc_data_copy_contents (&compat_v5creds->second_ticket, &v5creds->second_ticket); } if (!err) { err = cci_cc_data_array_copy (&compat_v5creds->authdata, v5creds->authdata); } if (!err) { compat_cred_union->cred_type = CC_CRED_V5; compat_cred_union->cred.pV5Cred = compat_v5creds; compat_v5creds->keyblock = v5creds->keyblock; compat_v5creds->authtime = v5creds->authtime; compat_v5creds->starttime = v5creds->starttime; compat_v5creds->endtime = v5creds->endtime; compat_v5creds->renew_till = v5creds->renew_till; compat_v5creds->is_skey = v5creds->is_skey; compat_v5creds->ticket_flags = v5creds->ticket_flags; } } else { err = cci_check_error (ccErrBadCredentialsVersion); } } if (!err) { *out_cred_union = compat_cred_union; compat_cred_union = NULL; } if (compat_cred_union) { cci_cred_union_release (compat_cred_union); } return cci_check_error (err); } /* ------------------------------------------------------------------------ */ cc_uint32 cci_cred_union_to_credentials_union (const cred_union *in_cred_union, cc_credentials_union **out_credentials_union) { cc_int32 err = ccNoError; cc_credentials_union *creds_union = NULL; if (!in_cred_union ) { err = cci_check_error (ccErrBadParam); } if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); } if (!err) { creds_union = calloc (1, sizeof (*creds_union)); if (!creds_union) { err = cci_check_error (ccErrNoMem); } } if (!err) { if (in_cred_union->cred_type == CC_CRED_V5) { cc_credentials_v5_compat *compat_v5creds = in_cred_union->cred.pV5Cred; cc_credentials_v5_t *v5creds = NULL; if (!err) { v5creds = malloc (sizeof (*v5creds)); if (v5creds) { *v5creds = cci_credentials_v5_initializer; } else { err = cci_check_error (ccErrNoMem); } } if (!err) { if (!compat_v5creds->client) { err = cci_check_error (ccErrBadParam); } else { v5creds->client = strdup (compat_v5creds->client); if (!v5creds->client) { err = cci_check_error (ccErrNoMem); } } } if (!err) { if (!compat_v5creds->server) { err = cci_check_error (ccErrBadParam); } else { v5creds->server = strdup (compat_v5creds->server); if (!v5creds->server) { err = cci_check_error (ccErrNoMem); } } } if (!err) { err = cci_cc_data_copy_contents (&v5creds->keyblock, &compat_v5creds->keyblock); } if (!err) { err = cci_cc_data_array_copy (&v5creds->addresses, compat_v5creds->addresses); } if (!err) { err = cci_cc_data_copy_contents (&v5creds->ticket, &compat_v5creds->ticket); } if (!err) { err = cci_cc_data_copy_contents (&v5creds->second_ticket, &compat_v5creds->second_ticket); } if (!err) { err = cci_cc_data_array_copy (&v5creds->authdata, compat_v5creds->authdata); } if (!err) { creds_union->version = cc_credentials_v5; creds_union->credentials.credentials_v5 = v5creds; v5creds->authtime = compat_v5creds->authtime; v5creds->starttime = compat_v5creds->starttime; v5creds->endtime = compat_v5creds->endtime; v5creds->renew_till = compat_v5creds->renew_till; v5creds->is_skey = compat_v5creds->is_skey; v5creds->ticket_flags = compat_v5creds->ticket_flags; } } else { err = cci_check_error (ccErrBadCredentialsVersion); } } if (!err) { *out_credentials_union = creds_union; creds_union = NULL; } if (creds_union) { cci_credentials_union_release (creds_union); } return cci_check_error (err); } /* ------------------------------------------------------------------------ */ cc_uint32 cci_cred_union_compare_to_credentials_union (const cred_union *in_cred_union_compat, const cc_credentials_union *in_credentials_union, cc_uint32 *out_equal) { cc_int32 err = ccNoError; cc_uint32 equal = 0; if (!in_cred_union_compat) { err = cci_check_error (ccErrBadParam); } if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } if (!out_equal ) { err = cci_check_error (ccErrBadParam); } if (!err) { if (in_cred_union_compat->cred_type == CC_CRED_V5 && in_credentials_union->version == cc_credentials_v5) { cc_credentials_v5_compat *old_creds_v5 = in_cred_union_compat->cred.pV5Cred; cc_credentials_v5_t *new_creds_v5 = in_credentials_union->credentials.credentials_v5; /* Really should use krb5_parse_name and krb5_principal_compare */ if (old_creds_v5 && new_creds_v5 && !strcmp (old_creds_v5->client, new_creds_v5->client) && !strcmp (old_creds_v5->server, new_creds_v5->server) && (old_creds_v5->starttime == new_creds_v5->starttime)) { equal = 1; } } } if (!err) { *out_equal = equal; } return cci_check_error (err); }