xref: /freebsd/crypto/krb5/src/lib/krb5/ccache/t_marshal.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/ccache/t_marshal.c - test program for cred marshalling */
3 /*
4  * Copyright (C) 2014 by the Massachusetts Institute of Technology.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in
16  *   the documentation and/or other materials provided with the
17  *   distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30  * OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "cc-int.h"
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <arpa/inet.h>
37 #include <fcntl.h>
38 
39 /*
40  * Versions 1 and 2 of the ccache format use native byte order representations
41  * of integers.  The test data below is from a little-endian platform.  Skip
42  * those tests on big-endian platforms by starting at version 3.
43  */
44 #ifdef K5_BE
45 #define FIRST_VERSION 3
46 #else
47 #define FIRST_VERSION 1
48 #endif
49 
50 /* Each test contains the expected binary representation of a credential cache
51  * divided into the header, the default principal, and two credentials. */
52 const struct test {
53     size_t headerlen;
54     const unsigned char header[256];
55     size_t princlen;
56     const unsigned char princ[256];
57     size_t cred1len;
58     const unsigned char cred1[256];
59     size_t cred2len;
60     const unsigned char cred2[256];
61 } tests[4] = {
62     {
63         /* Version 1 header */
64         2,
65         "\x05\x01",
66         /* Version 1 principal */
67         33,
68         "\x02\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54\x45\x53\x54\x2E"
69         "\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63\x6C\x69\x65\x6E"
70         "\x74",
71         /* Version 1 cred 1 */
72         165,
73         "\x02\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54\x45\x53\x54\x2E"
74         "\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63\x6C\x69\x65\x6E"
75         "\x74\x03\x00\x00\x00\x0B\x00\x00\x00\x45\x58\x41\x4D\x50\x4C\x45"
76         "\x2E\x43\x4F\x4D\x04\x00\x00\x00\x74\x65\x73\x74\x04\x00\x00\x00"
77         "\x68\x6F\x73\x74\x11\x00\x10\x00\x00\x00\x00\x01\x02\x03\x04\x05"
78         "\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x0B\x00\x00\x00\xDE\x00"
79         "\x00\x00\x05\x0D\x00\x00\x00\xCA\x9A\x3B\x00\x00\x00\x80\x40\x01"
80         "\x00\x00\x00\x02\x00\x04\x00\x00\x00\x0A\x00\x00\x01\x02\x00\x00"
81         "\x00\x00\x02\x0A\x00\x00\x00\x73\x69\x67\x6E\x74\x69\x63\x6B\x65"
82         "\x74\x9C\xFF\x00\x00\x00\x00\x06\x00\x00\x00\x74\x69\x63\x6B\x65"
83         "\x74\x00\x00\x00\x00",
84         /* Version 1 cred 2 */
85         113,
86         "\x02\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54\x45\x53\x54\x2E"
87         "\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63\x6C\x69\x65\x6E"
88         "\x74\x01\x00\x00\x00\x00\x00\x00\x00\x17\x00\x10\x00\x00\x00\x0F"
89         "\x0E\x0D\x0C\x0B\x0A\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00\x00"
90         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
91         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00"
92         "\x74\x69\x63\x6B\x65\x74\x07\x00\x00\x00\x32\x74\x69\x63\x6B\x65"
93         "\x74"
94     },
95     {
96         /* Version 2 header */
97         2,
98         "\x05\x02",
99         /* Version 2 principal */
100         37,
101         "\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54"
102         "\x45\x53\x54\x2E\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63"
103         "\x6C\x69\x65\x6E\x74",
104         /* Version 2 cred 1 */
105         173,
106         "\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54"
107         "\x45\x53\x54\x2E\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63"
108         "\x6C\x69\x65\x6E\x74\x01\x00\x00\x00\x02\x00\x00\x00\x0B\x00\x00"
109         "\x00\x45\x58\x41\x4D\x50\x4C\x45\x2E\x43\x4F\x4D\x04\x00\x00\x00"
110         "\x74\x65\x73\x74\x04\x00\x00\x00\x68\x6F\x73\x74\x11\x00\x10\x00"
111         "\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D"
112         "\x0E\x0F\x0B\x00\x00\x00\xDE\x00\x00\x00\x05\x0D\x00\x00\x00\xCA"
113         "\x9A\x3B\x00\x00\x00\x80\x40\x01\x00\x00\x00\x02\x00\x04\x00\x00"
114         "\x00\x0A\x00\x00\x01\x02\x00\x00\x00\x00\x02\x0A\x00\x00\x00\x73"
115         "\x69\x67\x6E\x74\x69\x63\x6B\x65\x74\x9C\xFF\x00\x00\x00\x00\x06"
116         "\x00\x00\x00\x74\x69\x63\x6B\x65\x74\x00\x00\x00\x00",
117         /* Version 2 cred 2 */
118         121,
119         "\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54"
120         "\x45\x53\x54\x2E\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63"
121         "\x6C\x69\x65\x6E\x74\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
122         "\x00\x17\x00\x10\x00\x00\x00\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07"
123         "\x06\x05\x04\x03\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
124         "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
125         "\x00\x00\x00\x00\x06\x00\x00\x00\x74\x69\x63\x6B\x65\x74\x07\x00"
126         "\x00\x00\x32\x74\x69\x63\x6B\x65\x74"
127     },
128     {
129         /* Version 3 header */
130         2,
131         "\x05\x03",
132         /* Version 3 principal */
133         37,
134         "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54"
135         "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63"
136         "\x6C\x69\x65\x6E\x74",
137         /* Version 3 cred 1 */
138         175,
139         "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54"
140         "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63"
141         "\x6C\x69\x65\x6E\x74\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00"
142         "\x0B\x45\x58\x41\x4D\x50\x4C\x45\x2E\x43\x4F\x4D\x00\x00\x00\x04"
143         "\x74\x65\x73\x74\x00\x00\x00\x04\x68\x6F\x73\x74\x00\x11\x00\x11"
144         "\x00\x00\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"
145         "\x0C\x0D\x0E\x0F\x00\x00\x00\x0B\x00\x00\x00\xDE\x00\x00\x0D\x05"
146         "\x3B\x9A\xCA\x00\x00\x40\x80\x00\x00\x00\x00\x00\x01\x00\x02\x00"
147         "\x00\x00\x04\x0A\x00\x00\x01\x00\x00\x00\x02\x02\x00\x00\x00\x00"
148         "\x0A\x73\x69\x67\x6E\x74\x69\x63\x6B\x65\x74\xFF\x9C\x00\x00\x00"
149         "\x00\x00\x00\x00\x06\x74\x69\x63\x6B\x65\x74\x00\x00\x00\x00",
150         /* Version 3 cred 2 */
151         123,
152         "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54"
153         "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63"
154         "\x6C\x69\x65\x6E\x74\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
155         "\x00\x00\x17\x00\x17\x00\x00\x00\x10\x0F\x0E\x0D\x0C\x0B\x0A\x09"
156         "\x08\x07\x06\x05\x04\x03\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00"
157         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
158         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x74\x69\x63\x6B\x65\x74"
159         "\x00\x00\x00\x07\x32\x74\x69\x63\x6B\x65\x74"
160     },
161     {
162         /* Version 4 header */
163         16,
164         "\x05\x04\x00\x0C\x00\x01\x00\x08\x00\x00\x01\x2C\x00\x00\xD4\x31",
165         /* Version 4 principal */
166         37,
167         "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54"
168         "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63"
169         "\x6C\x69\x65\x6E\x74",
170         /* Version 4 cred 1 */
171         173,
172         "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54"
173         "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63"
174         "\x6C\x69\x65\x6E\x74\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00"
175         "\x0B\x45\x58\x41\x4D\x50\x4C\x45\x2E\x43\x4F\x4D\x00\x00\x00\x04"
176         "\x74\x65\x73\x74\x00\x00\x00\x04\x68\x6F\x73\x74\x00\x11\x00\x00"
177         "\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D"
178         "\x0E\x0F\x00\x00\x00\x0B\x00\x00\x00\xDE\x00\x00\x0D\x05\x3B\x9A"
179         "\xCA\x00\x00\x40\x80\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00"
180         "\x04\x0A\x00\x00\x01\x00\x00\x00\x02\x02\x00\x00\x00\x00\x0A\x73"
181         "\x69\x67\x6E\x74\x69\x63\x6B\x65\x74\xFF\x9C\x00\x00\x00\x00\x00"
182         "\x00\x00\x06\x74\x69\x63\x6B\x65\x74\x00\x00\x00\x00",
183         /* Version 4 cred 2 */
184         121,
185         "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54"
186         "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63"
187         "\x6C\x69\x65\x6E\x74\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
188         "\x00\x00\x17\x00\x00\x00\x10\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07"
189         "\x06\x05\x04\x03\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
190         "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
191         "\x00\x00\x00\x00\x00\x00\x00\x06\x74\x69\x63\x6B\x65\x74\x00\x00"
192         "\x00\x07\x32\x74\x69\x63\x6B\x65\x74"
193     }
194 };
195 
196 static void
verify_princ(krb5_principal p)197 verify_princ(krb5_principal p)
198 {
199     assert(p->length == 1);
200     assert(data_eq_string(p->realm, "KRBTEST.COM"));
201     assert(data_eq_string(p->data[0], "testclient"));
202 }
203 
204 static void
verify_cred1(const krb5_creds * c)205 verify_cred1(const krb5_creds *c)
206 {
207     uint32_t ipaddr = ntohl(0x0A000001);
208 
209     verify_princ(c->client);
210     assert(c->server->length == 2);
211     assert(data_eq_string(c->server->realm, "EXAMPLE.COM"));
212     assert(data_eq_string(c->server->data[0], "test"));
213     assert(data_eq_string(c->server->data[1], "host"));
214     assert(c->keyblock.enctype == ENCTYPE_AES128_CTS_HMAC_SHA1_96);
215     assert(c->keyblock.length == 16);
216     assert(memcmp(c->keyblock.contents,
217                   "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF",
218                   16) == 0);
219     assert(c->times.authtime == 11);
220     assert(c->times.starttime == 222);
221     assert(c->times.endtime == 3333);
222     assert(c->times.renew_till == 1000000000);
223     assert(c->is_skey == FALSE);
224     assert(c->ticket_flags == (TKT_FLG_FORWARDABLE | TKT_FLG_RENEWABLE));
225     assert(c->addresses != NULL && c->addresses[0] != NULL);
226     assert(c->addresses[0]->addrtype == ADDRTYPE_INET);
227     assert(c->addresses[0]->length == 4);
228     assert(memcmp(c->addresses[0]->contents, &ipaddr, 4) == 0);
229     assert(c->addresses[1] == NULL);
230     assert(c->authdata != NULL && c->authdata[0] != NULL);
231     assert(c->authdata[0]->ad_type == KRB5_AUTHDATA_SIGNTICKET);
232     assert(c->authdata[0]->length == 10);
233     assert(memcmp(c->authdata[0]->contents, "signticket", 10) == 0);
234     assert(c->authdata[1] != NULL);
235     assert(c->authdata[1]->ad_type == -100);
236     assert(c->authdata[1]->length == 0);
237     assert(c->authdata[2] == NULL);
238     assert(data_eq_string(c->ticket, "ticket"));
239     assert(c->second_ticket.length == 0);
240 }
241 
242 static void
verify_cred2(const krb5_creds * c)243 verify_cred2(const krb5_creds *c)
244 {
245     verify_princ(c->client);
246     assert(c->server->length == 0);
247     assert(c->server->realm.length == 0);
248     assert(c->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC);
249     assert(c->keyblock.length == 16);
250     assert(memcmp(c->keyblock.contents,
251                   "\xF\xE\xD\xC\xB\xA\x9\x8\x7\x6\x5\x4\x3\x2\x1\x0",
252                   16) == 0);
253     assert(c->times.authtime == 0);
254     assert(c->times.starttime == 0);
255     assert(c->times.endtime == 0);
256     assert(c->times.renew_till == 0);
257     assert(c->is_skey == TRUE);
258     assert(c->ticket_flags == 0);
259     assert(c->addresses == NULL || c->addresses[0] == NULL);
260     assert(c->authdata == NULL || c->authdata[0] == NULL);
261     assert(data_eq_string(c->ticket, "ticket"));
262     assert(data_eq_string(c->second_ticket, "2ticket"));
263 }
264 
265 int
main(int argc,char ** argv)266 main(int argc, char **argv)
267 {
268     krb5_context context;
269     krb5_ccache cache;
270     krb5_principal princ;
271     krb5_creds cred1, cred2, *alloc_cred;
272     krb5_cc_cursor cursor;
273     const char *filename;
274     char *ccname, filebuf[256];
275     int version, fd;
276     const struct test *t;
277     struct k5buf buf;
278     krb5_data ser_data, *alloc_data;
279 
280     if (argc != 2)
281         abort();
282     filename = argv[1];
283     if (asprintf(&ccname, "FILE:%s", filename) == -1)
284         abort();
285 
286     if (krb5_init_context(&context) != 0)
287         abort();
288 
289     /* Test public functions for unmarshalling and marshalling. */
290     ser_data = make_data((char *)tests[3].cred1, tests[3].cred1len);
291     if (krb5_unmarshal_credentials(context, &ser_data, &alloc_cred) != 0)
292         abort();
293     verify_cred1(alloc_cred);
294     if (krb5_marshal_credentials(context, alloc_cred, &alloc_data) != 0)
295         abort();
296     assert(alloc_data->length == tests[3].cred1len);
297     assert(memcmp(tests[3].cred1, alloc_data->data, alloc_data->length) == 0);
298     krb5_free_data(context, alloc_data);
299     krb5_free_creds(context, alloc_cred);
300 
301     for (version = FIRST_VERSION; version <= 4; version++) {
302         t = &tests[version - 1];
303 
304         /* Test principal unmarshalling and marshalling. */
305         if (k5_unmarshal_princ(t->princ, t->princlen, version, &princ) != 0)
306             abort();
307         verify_princ(princ);
308         k5_buf_init_dynamic(&buf);
309         k5_marshal_princ(&buf, version, princ);
310         assert(buf.len == t->princlen);
311         assert(memcmp(t->princ, buf.data, buf.len) == 0);
312         k5_buf_free(&buf);
313 
314         /* Test cred1 unmarshalling and marshalling. */
315         if (k5_unmarshal_cred(t->cred1, t->cred1len, version, &cred1) != 0)
316             abort();
317         verify_cred1(&cred1);
318         k5_buf_init_dynamic(&buf);
319         k5_marshal_cred(&buf, version, &cred1);
320         assert(buf.len == t->cred1len);
321         assert(memcmp(t->cred1, buf.data, buf.len) == 0);
322         k5_buf_free(&buf);
323 
324         /* Test cred2 unmarshalling and marshalling. */
325         if (k5_unmarshal_cred(t->cred2, t->cred2len, version, &cred2) != 0)
326             abort();
327         verify_cred2(&cred2);
328         k5_buf_init_dynamic(&buf);
329         k5_marshal_cred(&buf, version, &cred2);
330         assert(buf.len == t->cred2len);
331         assert(memcmp(t->cred2, buf.data, buf.len) == 0);
332         k5_buf_free(&buf);
333 
334         /* Write a ccache containing the principal and creds.  Use the same
335          * time offset as the version 4 test data used. */
336         context->fcc_default_format = 0x0500 + version;
337         context->os_context.time_offset = 300;
338         context->os_context.usec_offset = 54321;
339         context->os_context.os_flags = KRB5_OS_TOFFSET_VALID;
340         if (krb5_cc_resolve(context, ccname, &cache) != 0)
341             abort();
342         if (krb5_cc_initialize(context, cache, princ) != 0)
343             abort();
344         if (krb5_cc_store_cred(context, cache, &cred1) != 0)
345             abort();
346         if (krb5_cc_store_cred(context, cache, &cred2) != 0)
347             abort();
348         if (krb5_cc_close(context, cache) != 0)
349             abort();
350 
351         /* Verify the cache representation against the test data. */
352         fd = open(filename, O_RDONLY);
353         if (fd == -1)
354             abort();
355         if (read(fd, filebuf, t->headerlen) != (ssize_t)t->headerlen)
356             abort();
357         assert(memcmp(filebuf, t->header, t->headerlen) == 0);
358         if (read(fd, filebuf, t->princlen) != (ssize_t)t->princlen)
359             abort();
360         assert(memcmp(filebuf, t->princ, t->princlen) == 0);
361         if (read(fd, filebuf, t->cred1len) != (ssize_t)t->cred1len)
362             abort();
363         assert(memcmp(filebuf, t->cred1, t->cred1len) == 0);
364         if (read(fd, filebuf, t->cred2len) != (ssize_t)t->cred2len)
365             abort();
366         assert(memcmp(filebuf, t->cred2, t->cred2len) == 0);
367         close(fd);
368 
369         krb5_free_principal(context, princ);
370         krb5_free_cred_contents(context, &cred1);
371         krb5_free_cred_contents(context, &cred2);
372 
373         /* Write a cache containing the test data. */
374         fd = open(filename, O_CREAT|O_TRUNC|O_RDWR, 0700);
375         if (fd == -1)
376             abort();
377         if (write(fd, t->header, t->headerlen) != (ssize_t)t->headerlen)
378             abort();
379         if (write(fd, t->princ, t->princlen) != (ssize_t)t->princlen)
380             abort();
381         if (write(fd, t->cred1, t->cred1len) != (ssize_t)t->cred1len)
382             abort();
383         if (write(fd, t->cred2, t->cred2len) != (ssize_t)t->cred2len)
384             abort();
385         close(fd);
386 
387         /* Read the cache and verify that it matches. */
388         if (krb5_cc_resolve(context, ccname, &cache) != 0)
389             abort();
390         if (krb5_cc_get_principal(context, cache, &princ) != 0)
391             abort();
392         /* Not every version stores the time offset, but at least it shouldn't
393          * have changed from when we set it before. */
394         assert(context->os_context.time_offset == 300);
395         assert(context->os_context.usec_offset == 54321);
396         verify_princ(princ);
397         if (krb5_cc_start_seq_get(context, cache, &cursor) != 0)
398             abort();
399         if (krb5_cc_next_cred(context, cache, &cursor, &cred1) != 0)
400             abort();
401         verify_cred1(&cred1);
402         krb5_free_cred_contents(context, &cred1);
403         if (krb5_cc_next_cred(context, cache, &cursor, &cred2) != 0)
404             abort();
405         verify_cred2(&cred2);
406         krb5_free_cred_contents(context, &cred2);
407         if (krb5_cc_next_cred(context, cache, &cursor, &cred2) != KRB5_CC_END)
408             abort();
409         if (krb5_cc_end_seq_get(context, cache, &cursor) != 0)
410             abort();
411         if (krb5_cc_close(context, cache) != 0)
412             abort();
413         krb5_free_principal(context, princ);
414     }
415 
416     (void)unlink(filename);
417     free(ccname);
418     krb5_free_context(context);
419     return 0;
420 }
421