Imported Upstream version 1.20.1
[platform/upstream/krb5.git] / src / ccapi / common / cci_cred_union.c
1 /* ccapi/common/cci_cred_union.c */
2 /*
3  * Copyright 2006 Massachusetts Institute of Technology.
4  * All Rights Reserved.
5  *
6  * Export of this software from the United States of America may
7  * require a specific license from the United States Government.
8  * It is the responsibility of any person or organization contemplating
9  * export to obtain such a license before exporting.
10  *
11  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12  * distribute this software and its documentation for any purpose and
13  * without fee is hereby granted, provided that the above copyright
14  * notice appear in all copies and that both that copyright notice and
15  * this permission notice appear in supporting documentation, and that
16  * the name of M.I.T. not be used in advertising or publicity pertaining
17  * to distribution of the software without specific, written prior
18  * permission.  Furthermore if you modify this software you must label
19  * your software as modified software and not distribute it in such a
20  * fashion that it might be confused with the original M.I.T. software.
21  * M.I.T. makes no representations about the suitability of
22  * this software for any purpose.  It is provided "as is" without express
23  * or implied warranty.
24  */
25
26 #include "cci_common.h"
27
28 /* ------------------------------------------------------------------------ */
29
30 static cc_uint32 cci_cc_data_contents_release (cc_data *io_ccdata)
31 {
32     cc_int32 err = ccNoError;
33
34     if (!io_ccdata && io_ccdata->data) { err = ccErrBadParam; }
35
36     if (!err) {
37         if (io_ccdata->length) {
38             memset (io_ccdata->data, 0, io_ccdata->length);
39         }
40         free (io_ccdata->data);
41     }
42
43     return err;
44 }
45
46 /* ------------------------------------------------------------------------ */
47
48 static cc_uint32 cci_cc_data_release (cc_data *io_ccdata)
49 {
50     cc_int32 err = ccNoError;
51
52     if (!io_ccdata) { err = ccErrBadParam; }
53
54     if (!err) {
55         cci_cc_data_contents_release (io_ccdata);
56         free (io_ccdata);
57     }
58
59     return err;
60 }
61
62 /* ------------------------------------------------------------------------ */
63
64 static cc_uint32 cci_cc_data_read (cc_data      *io_ccdata,
65                                    k5_ipc_stream io_stream)
66 {
67     cc_int32 err = ccNoError;
68     cc_uint32 type = 0;
69     cc_uint32 length = 0;
70     char *data = NULL;
71
72     if (!io_stream) { err = cci_check_error (ccErrBadParam); }
73     if (!io_ccdata) { err = cci_check_error (ccErrBadParam); }
74
75     if (!err) {
76         err = krb5int_ipc_stream_read_uint32 (io_stream, &type);
77     }
78
79     if (!err) {
80         err = krb5int_ipc_stream_read_uint32 (io_stream, &length);
81     }
82
83     if (!err && length > 0) {
84         data = malloc (length);
85         if (!data) { err = cci_check_error (ccErrNoMem); }
86
87         if (!err) {
88             err = krb5int_ipc_stream_read (io_stream, data, length);
89         }
90     }
91
92     if (!err) {
93         io_ccdata->type = type;
94         io_ccdata->length = length;
95         io_ccdata->data = data;
96         data = NULL;
97     }
98
99     free (data);
100
101     return cci_check_error (err);
102 }
103
104 /* ------------------------------------------------------------------------ */
105
106 static cc_uint32 cci_cc_data_write (cc_data      *in_ccdata,
107                                     k5_ipc_stream io_stream)
108 {
109     cc_int32 err = ccNoError;
110
111     if (!io_stream) { err = cci_check_error (ccErrBadParam); }
112     if (!in_ccdata) { err = cci_check_error (ccErrBadParam); }
113
114     if (!err) {
115         err = krb5int_ipc_stream_write_uint32 (io_stream, in_ccdata->type);
116     }
117
118     if (!err) {
119         err = krb5int_ipc_stream_write_uint32 (io_stream, in_ccdata->length);
120     }
121
122     if (!err && in_ccdata->length > 0) {
123         err = krb5int_ipc_stream_write (io_stream, in_ccdata->data, in_ccdata->length);
124     }
125
126     return cci_check_error (err);
127 }
128
129 #ifdef TARGET_OS_MAC
130 #pragma mark -
131 #endif
132
133 /* ------------------------------------------------------------------------ */
134
135 static cc_uint32 cci_cc_data_array_release (cc_data **io_ccdata_array)
136 {
137     cc_int32 err = ccNoError;
138
139     if (!io_ccdata_array) { err = ccErrBadParam; }
140
141     if (!err) {
142         cc_uint32 i;
143
144         for (i = 0; io_ccdata_array && io_ccdata_array[i]; i++) {
145             cci_cc_data_release (io_ccdata_array[i]);
146         }
147         free (io_ccdata_array);
148     }
149
150     return err;
151 }
152
153 /* ------------------------------------------------------------------------ */
154
155 static cc_uint32 cci_cc_data_array_read (cc_data      ***io_ccdata_array,
156                                          k5_ipc_stream    io_stream)
157 {
158     cc_int32 err = ccNoError;
159     cc_uint32 count = 0;
160     cc_data **array = NULL;
161     cc_uint32 i;
162
163     if (!io_stream      ) { err = cci_check_error (ccErrBadParam); }
164     if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); }
165
166     if (!err) {
167         err = krb5int_ipc_stream_read_uint32 (io_stream, &count);
168     }
169
170     if (!err && count > 0) {
171         array = malloc ((count + 1) * sizeof (*array));
172         if (array) {
173             for (i = 0; i <= count; i++) { array[i] = NULL; }
174         } else {
175             err = cci_check_error (ccErrNoMem);
176         }
177     }
178
179     if (!err) {
180         for (i = 0; !err && i < count; i++) {
181             array[i] = malloc (sizeof (cc_data));
182             if (!array[i]) { err = cci_check_error (ccErrNoMem); }
183
184             if (!err) {
185                 err = cci_cc_data_read (array[i], io_stream);
186             }
187         }
188     }
189
190     if (!err) {
191         *io_ccdata_array = array;
192         array = NULL;
193     }
194
195     cci_cc_data_array_release (array);
196
197     return cci_check_error (err);
198 }
199
200 /* ------------------------------------------------------------------------ */
201
202 static cc_uint32 cci_cc_data_array_write (cc_data      **in_ccdata_array,
203                                           k5_ipc_stream   io_stream)
204 {
205     cc_int32 err = ccNoError;
206     cc_uint32 count = 0;
207
208     if (!io_stream) { err = cci_check_error (ccErrBadParam); }
209     /* in_ccdata_array may be NULL */
210
211     if (!err) {
212         for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++);
213
214         err = krb5int_ipc_stream_write_uint32 (io_stream, count);
215     }
216
217     if (!err) {
218         cc_uint32 i;
219
220         for (i = 0; !err && i < count; i++) {
221             err = cci_cc_data_write (in_ccdata_array[i], io_stream);
222         }
223     }
224
225     return cci_check_error (err);
226 }
227
228 #ifdef TARGET_OS_MAC
229 #pragma mark -
230 #endif
231
232 /* ------------------------------------------------------------------------ */
233
234 cc_credentials_v5_t cci_credentials_v5_initializer = {
235     NULL,
236     NULL,
237     { 0, 0, NULL },
238     0, 0, 0, 0, 0, 0,
239     NULL,
240     { 0, 0, NULL },
241     { 0, 0, NULL },
242     NULL
243 };
244
245 /* ------------------------------------------------------------------------ */
246
247 static cc_uint32 cci_credentials_v5_release (cc_credentials_v5_t *io_v5creds)
248 {
249     cc_int32 err = ccNoError;
250
251     if (!io_v5creds) { err = ccErrBadParam; }
252
253     if (!err) {
254         free (io_v5creds->client);
255         free (io_v5creds->server);
256         cci_cc_data_contents_release (&io_v5creds->keyblock);
257         cci_cc_data_array_release (io_v5creds->addresses);
258         cci_cc_data_contents_release (&io_v5creds->ticket);
259         cci_cc_data_contents_release (&io_v5creds->second_ticket);
260         cci_cc_data_array_release (io_v5creds->authdata);
261         free (io_v5creds);
262     }
263
264     return err;
265 }
266
267 /* ------------------------------------------------------------------------ */
268
269 static cc_uint32 cci_credentials_v5_read (cc_credentials_v5_t **out_v5creds,
270                                           k5_ipc_stream          io_stream)
271 {
272     cc_int32 err = ccNoError;
273     cc_credentials_v5_t *v5creds = NULL;
274
275     if (!io_stream  ) { err = cci_check_error (ccErrBadParam); }
276     if (!out_v5creds) { err = cci_check_error (ccErrBadParam); }
277
278     if (!err) {
279         v5creds = malloc (sizeof (*v5creds));
280         if (v5creds) {
281             *v5creds = cci_credentials_v5_initializer;
282         } else {
283             err = cci_check_error (ccErrNoMem);
284         }
285     }
286
287     if (!err) {
288         err = krb5int_ipc_stream_read_string (io_stream, &v5creds->client);
289     }
290
291     if (!err) {
292         err = krb5int_ipc_stream_read_string (io_stream, &v5creds->server);
293     }
294
295     if (!err) {
296         err = cci_cc_data_read (&v5creds->keyblock, io_stream);
297     }
298
299     if (!err) {
300         err = krb5int_ipc_stream_read_time (io_stream, &v5creds->authtime);
301     }
302
303     if (!err) {
304         err = krb5int_ipc_stream_read_time (io_stream, &v5creds->starttime);
305     }
306
307     if (!err) {
308         err = krb5int_ipc_stream_read_time (io_stream, &v5creds->endtime);
309     }
310
311     if (!err) {
312         err = krb5int_ipc_stream_read_time (io_stream, &v5creds->renew_till);
313     }
314
315     if (!err) {
316         err = krb5int_ipc_stream_read_uint32 (io_stream, &v5creds->is_skey);
317     }
318
319     if (!err) {
320         err = krb5int_ipc_stream_read_uint32 (io_stream, &v5creds->ticket_flags);
321     }
322
323     if (!err) {
324         err = cci_cc_data_array_read (&v5creds->addresses, io_stream);
325     }
326
327     if (!err) {
328         err = cci_cc_data_read (&v5creds->ticket, io_stream);
329     }
330
331     if (!err) {
332         err = cci_cc_data_read (&v5creds->second_ticket, io_stream);
333     }
334
335     if (!err) {
336         err = cci_cc_data_array_read (&v5creds->authdata, io_stream);
337     }
338
339     if (!err) {
340         *out_v5creds = v5creds;
341         v5creds = NULL;
342     }
343
344     cci_credentials_v5_release (v5creds);
345
346     return cci_check_error (err);
347 }
348
349 /* ------------------------------------------------------------------------ */
350
351 static cc_uint32 cci_credentials_v5_write (cc_credentials_v5_t *in_v5creds,
352                                            k5_ipc_stream         io_stream)
353 {
354     cc_int32 err = ccNoError;
355
356     if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
357     if (!in_v5creds) { err = cci_check_error (ccErrBadParam); }
358
359     if (!err) {
360         err = krb5int_ipc_stream_write_string (io_stream, in_v5creds->client);
361     }
362
363     if (!err) {
364         err = krb5int_ipc_stream_write_string (io_stream, in_v5creds->server);
365     }
366
367     if (!err) {
368         err = cci_cc_data_write (&in_v5creds->keyblock, io_stream);
369     }
370
371     if (!err) {
372         err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->authtime);
373     }
374
375     if (!err) {
376         err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->starttime);
377     }
378
379     if (!err) {
380         err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->endtime);
381     }
382
383     if (!err) {
384         err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->renew_till);
385     }
386
387     if (!err) {
388         err = krb5int_ipc_stream_write_uint32 (io_stream, in_v5creds->is_skey);
389     }
390
391     if (!err) {
392         err = krb5int_ipc_stream_write_uint32 (io_stream, in_v5creds->ticket_flags);
393     }
394
395     if (!err) {
396         err = cci_cc_data_array_write (in_v5creds->addresses, io_stream);
397     }
398
399     if (!err) {
400         err = cci_cc_data_write (&in_v5creds->ticket, io_stream);
401     }
402
403     if (!err) {
404         err = cci_cc_data_write (&in_v5creds->second_ticket, io_stream);
405     }
406
407     if (!err) {
408         err = cci_cc_data_array_write (in_v5creds->authdata, io_stream);
409     }
410
411
412     return cci_check_error (err);
413 }
414
415 #ifdef TARGET_OS_MAC
416 #pragma mark -
417 #endif
418
419 /* ------------------------------------------------------------------------ */
420
421 cc_uint32 cci_credentials_union_release (cc_credentials_union *io_cred_union)
422 {
423     cc_int32 err = ccNoError;
424
425     if (!io_cred_union) { err = ccErrBadParam; }
426
427     if (!err) {
428         if (io_cred_union->version == cc_credentials_v5) {
429             cci_credentials_v5_release (io_cred_union->credentials.credentials_v5);
430         }
431         free (io_cred_union);
432     }
433
434     return err;
435 }
436
437 /* ------------------------------------------------------------------------ */
438
439 cc_uint32 cci_credentials_union_read (cc_credentials_union **out_credentials_union,
440                                       k5_ipc_stream           io_stream)
441 {
442     cc_int32 err = ccNoError;
443     cc_credentials_union *credentials_union = NULL;
444
445     if (!io_stream            ) { err = cci_check_error (ccErrBadParam); }
446     if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); }
447
448     if (!err) {
449         credentials_union = calloc (1, sizeof (*credentials_union));
450         if (!credentials_union) { err = cci_check_error (ccErrNoMem); }
451     }
452
453     if (!err) {
454         err = krb5int_ipc_stream_read_uint32 (io_stream, &credentials_union->version);
455     }
456
457     if (!err) {
458         if (credentials_union->version == cc_credentials_v5) {
459             err = cci_credentials_v5_read (&credentials_union->credentials.credentials_v5,
460                                            io_stream);
461
462
463         } else {
464             err = ccErrBadCredentialsVersion;
465         }
466     }
467
468     if (!err) {
469         *out_credentials_union = credentials_union;
470         credentials_union = NULL;
471     }
472
473     if (credentials_union) { cci_credentials_union_release (credentials_union); }
474
475     return cci_check_error (err);
476 }
477
478 /* ------------------------------------------------------------------------ */
479
480 cc_uint32 cci_credentials_union_write (const cc_credentials_union *in_credentials_union,
481                                        k5_ipc_stream                io_stream)
482 {
483     cc_int32 err = ccNoError;
484
485     if (!io_stream           ) { err = cci_check_error (ccErrBadParam); }
486     if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
487
488     if (!err) {
489         err = krb5int_ipc_stream_write_uint32 (io_stream, in_credentials_union->version);
490     }
491
492     if (!err) {
493         if (in_credentials_union->version == cc_credentials_v5) {
494             err = cci_credentials_v5_write (in_credentials_union->credentials.credentials_v5,
495                                             io_stream);
496
497         } else {
498             err = ccErrBadCredentialsVersion;
499         }
500     }
501
502     return cci_check_error (err);
503 }
504
505 #ifdef TARGET_OS_MAC
506 #pragma mark -
507 #pragma mark -- CCAPI v2 Compat --
508 #endif
509
510 /* ------------------------------------------------------------------------ */
511
512 cc_credentials_v5_compat cci_credentials_v5_compat_initializer = {
513     NULL,
514     NULL,
515     { 0, 0, NULL },
516     0, 0, 0, 0, 0, 0,
517     NULL,
518     { 0, 0, NULL },
519     { 0, 0, NULL },
520     NULL
521 };
522
523 /* ------------------------------------------------------------------------ */
524
525 cc_uint32 cci_cred_union_release (cred_union *io_cred_union)
526 {
527     cc_int32 err = ccNoError;
528
529     if (!io_cred_union) { err = ccErrBadParam; }
530
531     if (!err) {
532         if (io_cred_union->cred_type == CC_CRED_V5) {
533             free (io_cred_union->cred.pV5Cred->client);
534             free (io_cred_union->cred.pV5Cred->server);
535             cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->keyblock);
536             cci_cc_data_array_release (io_cred_union->cred.pV5Cred->addresses);
537             cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->ticket);
538             cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->second_ticket);
539             cci_cc_data_array_release (io_cred_union->cred.pV5Cred->authdata);
540             free (io_cred_union->cred.pV5Cred);
541         }
542         free (io_cred_union);
543     }
544
545     return err;
546 }
547
548 /* ------------------------------------------------------------------------ */
549
550 static cc_uint32 cci_cc_data_copy_contents (cc_data      *io_ccdata,
551                                             cc_data      *in_ccdata)
552 {
553     cc_int32 err = ccNoError;
554     char *data = NULL;
555
556     if (!io_ccdata) { err = cci_check_error (ccErrBadParam); }
557     if (!in_ccdata) { err = cci_check_error (ccErrBadParam); }
558
559     if (!err && in_ccdata->length > 0) {
560         data = malloc (in_ccdata->length);
561         if (data) {
562             memcpy (data, in_ccdata->data, in_ccdata->length);
563         } else {
564             err = cci_check_error (ccErrNoMem);
565         }
566     }
567
568     if (!err) {
569         io_ccdata->type = in_ccdata->type;
570         io_ccdata->length = in_ccdata->length;
571         io_ccdata->data = data;
572         data = NULL;
573     }
574
575     free (data);
576
577     return cci_check_error (err);
578 }
579
580 /* ------------------------------------------------------------------------ */
581
582 static cc_uint32 cci_cc_data_array_copy (cc_data      ***io_ccdata_array,
583                                          cc_data       **in_ccdata_array)
584 {
585     cc_int32 err = ccNoError;
586     cc_uint32 count = 0;
587     cc_data **array = NULL;
588     cc_uint32 i;
589
590     if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); }
591
592     if (!err) {
593         for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++);
594     }
595
596     if (!err && count > 0) {
597         array = malloc ((count + 1) * sizeof (*array));
598         if (array) {
599             for (i = 0; i <= count; i++) { array[i] = NULL; }
600         } else {
601             err = cci_check_error (ccErrNoMem);
602         }
603     }
604
605     if (!err) {
606         for (i = 0; !err && i < count; i++) {
607             array[i] = malloc (sizeof (cc_data));
608             if (!array[i]) { err = cci_check_error (ccErrNoMem); }
609
610             if (!err) {
611                 err = cci_cc_data_copy_contents (array[i], in_ccdata_array[i]);
612             }
613         }
614     }
615
616     if (!err) {
617         *io_ccdata_array = array;
618         array = NULL;
619     }
620
621     cci_cc_data_array_release (array);
622
623     return cci_check_error (err);
624 }
625
626 /* ------------------------------------------------------------------------ */
627
628 cc_uint32 cci_credentials_union_to_cred_union (const cc_credentials_union  *in_credentials_union,
629                                                cred_union                 **out_cred_union)
630 {
631     cc_int32 err = ccNoError;
632     cred_union *compat_cred_union = NULL;
633
634     if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
635     if (!out_cred_union      ) { err = cci_check_error (ccErrBadParam); }
636
637     if (!err) {
638         compat_cred_union = calloc (1, sizeof (*compat_cred_union));
639         if (!compat_cred_union) { err = cci_check_error (ccErrNoMem); }
640     }
641
642     if (!err) {
643         if (in_credentials_union->version == cc_credentials_v5) {
644             cc_credentials_v5_t *v5creds = in_credentials_union->credentials.credentials_v5;
645             cc_credentials_v5_compat *compat_v5creds = NULL;
646
647             compat_v5creds = malloc (sizeof (*compat_v5creds));
648             if (compat_v5creds) {
649                 *compat_v5creds = cci_credentials_v5_compat_initializer;
650             } else {
651                 err = cci_check_error (ccErrNoMem);
652             }
653
654             if (!err) {
655                 if (!v5creds->client) {
656                     err = cci_check_error (ccErrBadParam);
657                 } else {
658                     compat_v5creds->client = strdup (v5creds->client);
659                     if (!compat_v5creds->client) { err = cci_check_error (ccErrNoMem); }
660                 }
661             }
662
663             if (!err) {
664                 if (!v5creds->server) {
665                     err = cci_check_error (ccErrBadParam);
666                 } else {
667                     compat_v5creds->server = strdup (v5creds->server);
668                     if (!compat_v5creds->server) { err = cci_check_error (ccErrNoMem); }
669                 }
670             }
671
672             if (!err) {
673                 err = cci_cc_data_copy_contents (&compat_v5creds->keyblock, &v5creds->keyblock);
674             }
675
676             if (!err) {
677                 err = cci_cc_data_array_copy (&compat_v5creds->addresses, v5creds->addresses);
678             }
679
680             if (!err) {
681                 err = cci_cc_data_copy_contents (&compat_v5creds->ticket, &v5creds->ticket);
682             }
683
684             if (!err) {
685                 err = cci_cc_data_copy_contents (&compat_v5creds->second_ticket, &v5creds->second_ticket);
686             }
687
688             if (!err) {
689                 err = cci_cc_data_array_copy (&compat_v5creds->authdata, v5creds->authdata);
690             }
691
692             if (!err) {
693                 compat_cred_union->cred_type = CC_CRED_V5;
694                 compat_cred_union->cred.pV5Cred = compat_v5creds;
695
696                 compat_v5creds->keyblock      = v5creds->keyblock;
697                 compat_v5creds->authtime      = v5creds->authtime;
698                 compat_v5creds->starttime     = v5creds->starttime;
699                 compat_v5creds->endtime       = v5creds->endtime;
700                 compat_v5creds->renew_till    = v5creds->renew_till;
701                 compat_v5creds->is_skey       = v5creds->is_skey;
702                 compat_v5creds->ticket_flags  = v5creds->ticket_flags;
703             }
704         } else {
705             err = cci_check_error (ccErrBadCredentialsVersion);
706         }
707     }
708
709     if (!err) {
710         *out_cred_union = compat_cred_union;
711         compat_cred_union = NULL;
712     }
713
714     if (compat_cred_union) { cci_cred_union_release (compat_cred_union); }
715
716     return cci_check_error (err);
717 }
718
719 /* ------------------------------------------------------------------------ */
720
721 cc_uint32 cci_cred_union_to_credentials_union (const cred_union      *in_cred_union,
722                                                cc_credentials_union **out_credentials_union)
723 {
724     cc_int32 err = ccNoError;
725     cc_credentials_union *creds_union = NULL;
726
727     if (!in_cred_union        ) { err = cci_check_error (ccErrBadParam); }
728     if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); }
729
730     if (!err) {
731         creds_union = calloc (1, sizeof (*creds_union));
732         if (!creds_union) { err = cci_check_error (ccErrNoMem); }
733     }
734
735     if (!err) {
736         if (in_cred_union->cred_type == CC_CRED_V5) {
737             cc_credentials_v5_compat *compat_v5creds = in_cred_union->cred.pV5Cred;
738             cc_credentials_v5_t *v5creds = NULL;
739
740             if (!err) {
741                 v5creds = malloc (sizeof (*v5creds));
742                 if (v5creds) {
743                     *v5creds = cci_credentials_v5_initializer;
744                 } else {
745                     err = cci_check_error (ccErrNoMem);
746                 }
747             }
748
749             if (!err) {
750                 if (!compat_v5creds->client) {
751                     err = cci_check_error (ccErrBadParam);
752                 } else {
753                     v5creds->client = strdup (compat_v5creds->client);
754                     if (!v5creds->client) { err = cci_check_error (ccErrNoMem); }
755                 }
756             }
757
758             if (!err) {
759                 if (!compat_v5creds->server) {
760                     err = cci_check_error (ccErrBadParam);
761                 } else {
762                     v5creds->server = strdup (compat_v5creds->server);
763                     if (!v5creds->server) { err = cci_check_error (ccErrNoMem); }
764                 }
765             }
766
767             if (!err) {
768                 err = cci_cc_data_copy_contents (&v5creds->keyblock, &compat_v5creds->keyblock);
769             }
770
771             if (!err) {
772                 err = cci_cc_data_array_copy (&v5creds->addresses, compat_v5creds->addresses);
773             }
774
775             if (!err) {
776                 err = cci_cc_data_copy_contents (&v5creds->ticket, &compat_v5creds->ticket);
777             }
778
779             if (!err) {
780                 err = cci_cc_data_copy_contents (&v5creds->second_ticket, &compat_v5creds->second_ticket);
781             }
782
783             if (!err) {
784                 err = cci_cc_data_array_copy (&v5creds->authdata, compat_v5creds->authdata);
785             }
786
787             if (!err) {
788                 creds_union->version = cc_credentials_v5;
789                 creds_union->credentials.credentials_v5 = v5creds;
790
791                 v5creds->authtime      = compat_v5creds->authtime;
792                 v5creds->starttime     = compat_v5creds->starttime;
793                 v5creds->endtime       = compat_v5creds->endtime;
794                 v5creds->renew_till    = compat_v5creds->renew_till;
795                 v5creds->is_skey       = compat_v5creds->is_skey;
796                 v5creds->ticket_flags  = compat_v5creds->ticket_flags;
797             }
798
799         } else {
800             err = cci_check_error (ccErrBadCredentialsVersion);
801         }
802     }
803
804     if (!err) {
805         *out_credentials_union = creds_union;
806         creds_union = NULL;
807     }
808
809     if (creds_union) { cci_credentials_union_release (creds_union); }
810
811     return cci_check_error (err);
812 }
813
814 /* ------------------------------------------------------------------------ */
815
816 cc_uint32 cci_cred_union_compare_to_credentials_union (const cred_union           *in_cred_union_compat,
817                                                        const cc_credentials_union *in_credentials_union,
818                                                        cc_uint32                  *out_equal)
819 {
820     cc_int32 err = ccNoError;
821     cc_uint32 equal = 0;
822
823     if (!in_cred_union_compat) { err = cci_check_error (ccErrBadParam); }
824     if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
825     if (!out_equal           ) { err = cci_check_error (ccErrBadParam); }
826
827     if (!err) {
828         if (in_cred_union_compat->cred_type == CC_CRED_V5 &&
829                    in_credentials_union->version == cc_credentials_v5) {
830             cc_credentials_v5_compat *old_creds_v5 = in_cred_union_compat->cred.pV5Cred;
831             cc_credentials_v5_t *new_creds_v5 = in_credentials_union->credentials.credentials_v5;
832
833             /* Really should use krb5_parse_name and krb5_principal_compare */
834             if (old_creds_v5 && new_creds_v5 &&
835                 !strcmp (old_creds_v5->client, new_creds_v5->client) &&
836                 !strcmp (old_creds_v5->server, new_creds_v5->server) &&
837                 (old_creds_v5->starttime == new_creds_v5->starttime)) {
838                 equal = 1;
839             }
840         }
841     }
842
843     if (!err) {
844         *out_equal = equal;
845     }
846
847     return cci_check_error (err);
848 }