1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* tests/adata.c - Test harness for KDC authorization data */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright (C) 2014 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert * All rights reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Redistribution and use in source and binary forms, with or without
8*7f2fe78bSCy Schubert * modification, are permitted provided that the following conditions
9*7f2fe78bSCy Schubert * are met:
10*7f2fe78bSCy Schubert *
11*7f2fe78bSCy Schubert * * Redistributions of source code must retain the above copyright
12*7f2fe78bSCy Schubert * notice, this list of conditions and the following disclaimer.
13*7f2fe78bSCy Schubert *
14*7f2fe78bSCy Schubert * * Redistributions in binary form must reproduce the above copyright
15*7f2fe78bSCy Schubert * notice, this list of conditions and the following disclaimer in
16*7f2fe78bSCy Schubert * the documentation and/or other materials provided with the
17*7f2fe78bSCy Schubert * distribution.
18*7f2fe78bSCy Schubert *
19*7f2fe78bSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*7f2fe78bSCy Schubert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*7f2fe78bSCy Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22*7f2fe78bSCy Schubert * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23*7f2fe78bSCy Schubert * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24*7f2fe78bSCy Schubert * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25*7f2fe78bSCy Schubert * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26*7f2fe78bSCy Schubert * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*7f2fe78bSCy Schubert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28*7f2fe78bSCy Schubert * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*7f2fe78bSCy Schubert * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30*7f2fe78bSCy Schubert * OF THE POSSIBILITY OF SUCH DAMAGE.
31*7f2fe78bSCy Schubert */
32*7f2fe78bSCy Schubert
33*7f2fe78bSCy Schubert /*
34*7f2fe78bSCy Schubert * Usage: ./adata [-c ccname] [-p clientprinc] serviceprinc
35*7f2fe78bSCy Schubert * [ad-type ad-contents ...]
36*7f2fe78bSCy Schubert *
37*7f2fe78bSCy Schubert * This program acquires credentials for the specified service principal, using
38*7f2fe78bSCy Schubert * the specified or default ccache, possibly including requested authdata. The
39*7f2fe78bSCy Schubert * resulting ticket is decrypted using the default keytab, and the authdata in
40*7f2fe78bSCy Schubert * the ticket are displayed to stdout.
41*7f2fe78bSCy Schubert *
42*7f2fe78bSCy Schubert * In the requested authdata types, the type may be prefixed with '?' for an
43*7f2fe78bSCy Schubert * AD-IF-RELEVANT container, '!' for an AD-MANDATORY-FOR-KDC container, or '^'
44*7f2fe78bSCy Schubert * for an AD-KDC-ISSUED container checksummed with a random AES256 key.
45*7f2fe78bSCy Schubert * Multiple prefixes may be specified for nested container.
46*7f2fe78bSCy Schubert *
47*7f2fe78bSCy Schubert * In the output, authdata containers will be flattened and displayed with the
48*7f2fe78bSCy Schubert * above prefixes or '+' for an AD-CAMMAC container. AD-KDC-ISSUED and
49*7f2fe78bSCy Schubert * AD-CAMMAC containers will be verified with the appropriate key. Nested
50*7f2fe78bSCy Schubert * containers only display the prefix for the innermost container.
51*7f2fe78bSCy Schubert */
52*7f2fe78bSCy Schubert
53*7f2fe78bSCy Schubert #include <k5-int.h>
54*7f2fe78bSCy Schubert #include <ctype.h>
55*7f2fe78bSCy Schubert
56*7f2fe78bSCy Schubert static krb5_context ctx;
57*7f2fe78bSCy Schubert
58*7f2fe78bSCy Schubert static void display_authdata_list(krb5_authdata **list,
59*7f2fe78bSCy Schubert krb5_enc_tkt_part *enc_tkt,
60*7f2fe78bSCy Schubert krb5_keyblock *tktkey, char prefix_byte,
61*7f2fe78bSCy Schubert krb5_boolean pac_ok);
62*7f2fe78bSCy Schubert
63*7f2fe78bSCy Schubert static void
check(krb5_error_code code)64*7f2fe78bSCy Schubert check(krb5_error_code code)
65*7f2fe78bSCy Schubert {
66*7f2fe78bSCy Schubert const char *errmsg;
67*7f2fe78bSCy Schubert
68*7f2fe78bSCy Schubert if (code) {
69*7f2fe78bSCy Schubert errmsg = krb5_get_error_message(ctx, code);
70*7f2fe78bSCy Schubert fprintf(stderr, "%s\n", errmsg);
71*7f2fe78bSCy Schubert krb5_free_error_message(ctx, errmsg);
72*7f2fe78bSCy Schubert exit(1);
73*7f2fe78bSCy Schubert }
74*7f2fe78bSCy Schubert }
75*7f2fe78bSCy Schubert
76*7f2fe78bSCy Schubert static krb5_authdatatype
get_type_for_prefix(int prefix_byte)77*7f2fe78bSCy Schubert get_type_for_prefix(int prefix_byte)
78*7f2fe78bSCy Schubert {
79*7f2fe78bSCy Schubert if (prefix_byte == '?')
80*7f2fe78bSCy Schubert return KRB5_AUTHDATA_IF_RELEVANT;
81*7f2fe78bSCy Schubert if (prefix_byte == '!')
82*7f2fe78bSCy Schubert return KRB5_AUTHDATA_MANDATORY_FOR_KDC;
83*7f2fe78bSCy Schubert if (prefix_byte == '^')
84*7f2fe78bSCy Schubert return KRB5_AUTHDATA_KDC_ISSUED;
85*7f2fe78bSCy Schubert if (prefix_byte == '+')
86*7f2fe78bSCy Schubert return KRB5_AUTHDATA_CAMMAC;
87*7f2fe78bSCy Schubert abort();
88*7f2fe78bSCy Schubert }
89*7f2fe78bSCy Schubert
90*7f2fe78bSCy Schubert static int
get_prefix_byte(krb5_authdata * ad)91*7f2fe78bSCy Schubert get_prefix_byte(krb5_authdata *ad)
92*7f2fe78bSCy Schubert {
93*7f2fe78bSCy Schubert if (ad->ad_type == KRB5_AUTHDATA_IF_RELEVANT)
94*7f2fe78bSCy Schubert return '?';
95*7f2fe78bSCy Schubert if (ad->ad_type == KRB5_AUTHDATA_MANDATORY_FOR_KDC)
96*7f2fe78bSCy Schubert return '!';
97*7f2fe78bSCy Schubert if (ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED)
98*7f2fe78bSCy Schubert return '^';
99*7f2fe78bSCy Schubert if (ad->ad_type == KRB5_AUTHDATA_CAMMAC)
100*7f2fe78bSCy Schubert return '+';
101*7f2fe78bSCy Schubert abort();
102*7f2fe78bSCy Schubert }
103*7f2fe78bSCy Schubert
104*7f2fe78bSCy Schubert /* Construct a container of type ad_type for the single authdata element
105*7f2fe78bSCy Schubert * content. For KDC-ISSUED containers, use a random checksum key. */
106*7f2fe78bSCy Schubert static krb5_authdata *
make_container(krb5_authdatatype ad_type,krb5_authdata * content)107*7f2fe78bSCy Schubert make_container(krb5_authdatatype ad_type, krb5_authdata *content)
108*7f2fe78bSCy Schubert {
109*7f2fe78bSCy Schubert krb5_authdata *list[2], **enclist, *ad;
110*7f2fe78bSCy Schubert krb5_keyblock kb;
111*7f2fe78bSCy Schubert
112*7f2fe78bSCy Schubert list[0] = content;
113*7f2fe78bSCy Schubert list[1] = NULL;
114*7f2fe78bSCy Schubert
115*7f2fe78bSCy Schubert if (ad_type == KRB5_AUTHDATA_KDC_ISSUED) {
116*7f2fe78bSCy Schubert check(krb5_c_make_random_key(ctx, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
117*7f2fe78bSCy Schubert &kb));
118*7f2fe78bSCy Schubert check(krb5_make_authdata_kdc_issued(ctx, &kb, NULL, list, &enclist));
119*7f2fe78bSCy Schubert krb5_free_keyblock_contents(ctx, &kb);
120*7f2fe78bSCy Schubert } else {
121*7f2fe78bSCy Schubert check(krb5_encode_authdata_container(ctx, ad_type, list, &enclist));
122*7f2fe78bSCy Schubert }
123*7f2fe78bSCy Schubert
124*7f2fe78bSCy Schubert /* Grab the first element from the encoded list and free the array. */
125*7f2fe78bSCy Schubert ad = enclist[0];
126*7f2fe78bSCy Schubert free(enclist);
127*7f2fe78bSCy Schubert return ad;
128*7f2fe78bSCy Schubert }
129*7f2fe78bSCy Schubert
130*7f2fe78bSCy Schubert /* Parse typestr and contents into an authdata element. */
131*7f2fe78bSCy Schubert static krb5_authdata *
make_authdata(const char * typestr,const char * contents)132*7f2fe78bSCy Schubert make_authdata(const char *typestr, const char *contents)
133*7f2fe78bSCy Schubert {
134*7f2fe78bSCy Schubert krb5_authdata *inner_ad, *ad;
135*7f2fe78bSCy Schubert
136*7f2fe78bSCy Schubert if (*typestr == '?' || *typestr == '!' || *typestr == '^') {
137*7f2fe78bSCy Schubert inner_ad = make_authdata(typestr + 1, contents);
138*7f2fe78bSCy Schubert ad = make_container(get_type_for_prefix(*typestr), inner_ad);
139*7f2fe78bSCy Schubert free(inner_ad->contents);
140*7f2fe78bSCy Schubert free(inner_ad);
141*7f2fe78bSCy Schubert return ad;
142*7f2fe78bSCy Schubert }
143*7f2fe78bSCy Schubert
144*7f2fe78bSCy Schubert ad = malloc(sizeof(*ad));
145*7f2fe78bSCy Schubert assert(ad != NULL);
146*7f2fe78bSCy Schubert ad->magic = KV5M_AUTHDATA;
147*7f2fe78bSCy Schubert ad->ad_type = atoi(typestr);
148*7f2fe78bSCy Schubert ad->length = strlen(contents);
149*7f2fe78bSCy Schubert ad->contents = (unsigned char *)strdup(contents);
150*7f2fe78bSCy Schubert assert(ad->contents != NULL);
151*7f2fe78bSCy Schubert return ad;
152*7f2fe78bSCy Schubert }
153*7f2fe78bSCy Schubert
154*7f2fe78bSCy Schubert static krb5_authdata **
get_container_contents(krb5_authdata * ad,krb5_keyblock * skey,krb5_keyblock * tktkey)155*7f2fe78bSCy Schubert get_container_contents(krb5_authdata *ad, krb5_keyblock *skey,
156*7f2fe78bSCy Schubert krb5_keyblock *tktkey)
157*7f2fe78bSCy Schubert {
158*7f2fe78bSCy Schubert krb5_authdata **inner_ad;
159*7f2fe78bSCy Schubert
160*7f2fe78bSCy Schubert if (ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED)
161*7f2fe78bSCy Schubert check(krb5_verify_authdata_kdc_issued(ctx, skey, ad, NULL, &inner_ad));
162*7f2fe78bSCy Schubert else if (ad->ad_type == KRB5_AUTHDATA_CAMMAC)
163*7f2fe78bSCy Schubert check(k5_unwrap_cammac_svc(ctx, ad, tktkey, &inner_ad));
164*7f2fe78bSCy Schubert else
165*7f2fe78bSCy Schubert check(krb5_decode_authdata_container(ctx, ad->ad_type, ad, &inner_ad));
166*7f2fe78bSCy Schubert return inner_ad;
167*7f2fe78bSCy Schubert }
168*7f2fe78bSCy Schubert
169*7f2fe78bSCy Schubert static int
compare_uint32(const void * p1,const void * p2)170*7f2fe78bSCy Schubert compare_uint32(const void *p1, const void *p2)
171*7f2fe78bSCy Schubert {
172*7f2fe78bSCy Schubert uint32_t t1 = *(uint32_t *)p1, t2 = *(uint32_t *)p2;
173*7f2fe78bSCy Schubert
174*7f2fe78bSCy Schubert return (t1 > t2) ? 1 : (t1 == t2) ? 0 : -1;
175*7f2fe78bSCy Schubert }
176*7f2fe78bSCy Schubert
177*7f2fe78bSCy Schubert static void
display_pac(krb5_authdata * ad,krb5_enc_tkt_part * enc_tkt,krb5_keyblock * tktkey)178*7f2fe78bSCy Schubert display_pac(krb5_authdata *ad, krb5_enc_tkt_part *enc_tkt,
179*7f2fe78bSCy Schubert krb5_keyblock *tktkey)
180*7f2fe78bSCy Schubert {
181*7f2fe78bSCy Schubert krb5_pac pac;
182*7f2fe78bSCy Schubert size_t tlen, i;
183*7f2fe78bSCy Schubert uint32_t *types;
184*7f2fe78bSCy Schubert
185*7f2fe78bSCy Schubert assert(ad->ad_type == KRB5_AUTHDATA_WIN2K_PAC);
186*7f2fe78bSCy Schubert check(krb5_pac_parse(ctx, ad->contents, ad->length, &pac));
187*7f2fe78bSCy Schubert
188*7f2fe78bSCy Schubert check(krb5_pac_verify(ctx, pac, enc_tkt->times.authtime, enc_tkt->client,
189*7f2fe78bSCy Schubert tktkey, NULL));
190*7f2fe78bSCy Schubert
191*7f2fe78bSCy Schubert check(krb5_pac_get_types(ctx, pac, &tlen, &types));
192*7f2fe78bSCy Schubert qsort(types, tlen, sizeof(*types), compare_uint32);
193*7f2fe78bSCy Schubert
194*7f2fe78bSCy Schubert printf("[");
195*7f2fe78bSCy Schubert for (i = 0; i < tlen; i++) {
196*7f2fe78bSCy Schubert printf("%d", (int)types[i]);
197*7f2fe78bSCy Schubert if (i + 1 < tlen)
198*7f2fe78bSCy Schubert printf(", ");
199*7f2fe78bSCy Schubert }
200*7f2fe78bSCy Schubert printf("]");
201*7f2fe78bSCy Schubert
202*7f2fe78bSCy Schubert free(types);
203*7f2fe78bSCy Schubert krb5_pac_free(ctx, pac);
204*7f2fe78bSCy Schubert }
205*7f2fe78bSCy Schubert
206*7f2fe78bSCy Schubert /* Decode and display authentication indicator authdata. */
207*7f2fe78bSCy Schubert static void
display_auth_indicator(krb5_authdata * ad)208*7f2fe78bSCy Schubert display_auth_indicator(krb5_authdata *ad)
209*7f2fe78bSCy Schubert {
210*7f2fe78bSCy Schubert krb5_data **strs = NULL, **p;
211*7f2fe78bSCy Schubert
212*7f2fe78bSCy Schubert check(k5_authind_decode(ad, &strs));
213*7f2fe78bSCy Schubert assert(strs != NULL);
214*7f2fe78bSCy Schubert
215*7f2fe78bSCy Schubert printf("[");
216*7f2fe78bSCy Schubert for (p = strs; *p != NULL; p++) {
217*7f2fe78bSCy Schubert printf("%.*s", (int)(*p)->length, (*p)->data);
218*7f2fe78bSCy Schubert if (*(p + 1) != NULL)
219*7f2fe78bSCy Schubert printf(", ");
220*7f2fe78bSCy Schubert }
221*7f2fe78bSCy Schubert printf("]");
222*7f2fe78bSCy Schubert k5_free_data_ptr_list(strs);
223*7f2fe78bSCy Schubert }
224*7f2fe78bSCy Schubert
225*7f2fe78bSCy Schubert /* Display ad as either a hex dump or ASCII text. */
226*7f2fe78bSCy Schubert static void
display_binary_or_ascii(krb5_authdata * ad)227*7f2fe78bSCy Schubert display_binary_or_ascii(krb5_authdata *ad)
228*7f2fe78bSCy Schubert {
229*7f2fe78bSCy Schubert krb5_boolean binary = FALSE;
230*7f2fe78bSCy Schubert unsigned char *p;
231*7f2fe78bSCy Schubert
232*7f2fe78bSCy Schubert for (p = ad->contents; p < ad->contents + ad->length; p++) {
233*7f2fe78bSCy Schubert if (!isascii(*p) || !isprint(*p))
234*7f2fe78bSCy Schubert binary = TRUE;
235*7f2fe78bSCy Schubert }
236*7f2fe78bSCy Schubert if (binary) {
237*7f2fe78bSCy Schubert for (p = ad->contents; p < ad->contents + ad->length; p++)
238*7f2fe78bSCy Schubert printf("%02X", *p);
239*7f2fe78bSCy Schubert } else {
240*7f2fe78bSCy Schubert printf("%.*s", (int)ad->length, ad->contents);
241*7f2fe78bSCy Schubert }
242*7f2fe78bSCy Schubert }
243*7f2fe78bSCy Schubert
244*7f2fe78bSCy Schubert /* Display the contents of an authdata element, prefixed by prefix_byte. skey
245*7f2fe78bSCy Schubert * must be the ticket session key. */
246*7f2fe78bSCy Schubert static void
display_authdata(krb5_authdata * ad,krb5_enc_tkt_part * enc_tkt,krb5_keyblock * tktkey,int prefix_byte,krb5_boolean pac_ok)247*7f2fe78bSCy Schubert display_authdata(krb5_authdata *ad, krb5_enc_tkt_part *enc_tkt,
248*7f2fe78bSCy Schubert krb5_keyblock *tktkey, int prefix_byte, krb5_boolean pac_ok)
249*7f2fe78bSCy Schubert {
250*7f2fe78bSCy Schubert krb5_authdata **inner_ad;
251*7f2fe78bSCy Schubert
252*7f2fe78bSCy Schubert if (ad->ad_type == KRB5_AUTHDATA_IF_RELEVANT ||
253*7f2fe78bSCy Schubert ad->ad_type == KRB5_AUTHDATA_MANDATORY_FOR_KDC ||
254*7f2fe78bSCy Schubert ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED ||
255*7f2fe78bSCy Schubert ad->ad_type == KRB5_AUTHDATA_CAMMAC) {
256*7f2fe78bSCy Schubert if (ad->ad_type != KRB5_AUTHDATA_IF_RELEVANT)
257*7f2fe78bSCy Schubert pac_ok = FALSE;
258*7f2fe78bSCy Schubert /* Decode and display the contents. */
259*7f2fe78bSCy Schubert inner_ad = get_container_contents(ad, enc_tkt->session, tktkey);
260*7f2fe78bSCy Schubert display_authdata_list(inner_ad, enc_tkt, tktkey, get_prefix_byte(ad),
261*7f2fe78bSCy Schubert pac_ok);
262*7f2fe78bSCy Schubert krb5_free_authdata(ctx, inner_ad);
263*7f2fe78bSCy Schubert return;
264*7f2fe78bSCy Schubert }
265*7f2fe78bSCy Schubert
266*7f2fe78bSCy Schubert assert(pac_ok || ad->ad_type != KRB5_AUTHDATA_WIN2K_PAC);
267*7f2fe78bSCy Schubert
268*7f2fe78bSCy Schubert printf("%c", prefix_byte);
269*7f2fe78bSCy Schubert printf("%d: ", (int)ad->ad_type);
270*7f2fe78bSCy Schubert
271*7f2fe78bSCy Schubert if (ad->ad_type == KRB5_AUTHDATA_WIN2K_PAC)
272*7f2fe78bSCy Schubert display_pac(ad, enc_tkt, tktkey);
273*7f2fe78bSCy Schubert else if (ad->ad_type == KRB5_AUTHDATA_AUTH_INDICATOR)
274*7f2fe78bSCy Schubert display_auth_indicator(ad);
275*7f2fe78bSCy Schubert else
276*7f2fe78bSCy Schubert display_binary_or_ascii(ad);
277*7f2fe78bSCy Schubert printf("\n");
278*7f2fe78bSCy Schubert }
279*7f2fe78bSCy Schubert
280*7f2fe78bSCy Schubert static void
display_authdata_list(krb5_authdata ** list,krb5_enc_tkt_part * tkt_enc,krb5_keyblock * tktkey,char prefix_byte,krb5_boolean pac_ok)281*7f2fe78bSCy Schubert display_authdata_list(krb5_authdata **list, krb5_enc_tkt_part *tkt_enc,
282*7f2fe78bSCy Schubert krb5_keyblock *tktkey, char prefix_byte,
283*7f2fe78bSCy Schubert krb5_boolean pac_ok)
284*7f2fe78bSCy Schubert {
285*7f2fe78bSCy Schubert if (list == NULL)
286*7f2fe78bSCy Schubert return;
287*7f2fe78bSCy Schubert /* Only expect a PAC in the first element, if at all. */
288*7f2fe78bSCy Schubert for (; *list != NULL; list++) {
289*7f2fe78bSCy Schubert display_authdata(*list, tkt_enc, tktkey, prefix_byte, pac_ok);
290*7f2fe78bSCy Schubert pac_ok = FALSE;
291*7f2fe78bSCy Schubert }
292*7f2fe78bSCy Schubert }
293*7f2fe78bSCy Schubert
294*7f2fe78bSCy Schubert int
main(int argc,char ** argv)295*7f2fe78bSCy Schubert main(int argc, char **argv)
296*7f2fe78bSCy Schubert {
297*7f2fe78bSCy Schubert const char *ccname = NULL, *clientname = NULL;
298*7f2fe78bSCy Schubert krb5_principal client, server;
299*7f2fe78bSCy Schubert krb5_ccache ccache;
300*7f2fe78bSCy Schubert krb5_keytab keytab;
301*7f2fe78bSCy Schubert krb5_creds in_creds, *creds;
302*7f2fe78bSCy Schubert krb5_ticket *ticket;
303*7f2fe78bSCy Schubert krb5_authdata **req_authdata = NULL, *ad;
304*7f2fe78bSCy Schubert krb5_keytab_entry ktent;
305*7f2fe78bSCy Schubert size_t count;
306*7f2fe78bSCy Schubert int c;
307*7f2fe78bSCy Schubert
308*7f2fe78bSCy Schubert check(krb5_init_context(&ctx));
309*7f2fe78bSCy Schubert
310*7f2fe78bSCy Schubert while ((c = getopt(argc, argv, "+c:p:")) != -1) {
311*7f2fe78bSCy Schubert switch (c) {
312*7f2fe78bSCy Schubert case 'c':
313*7f2fe78bSCy Schubert ccname = optarg;
314*7f2fe78bSCy Schubert break;
315*7f2fe78bSCy Schubert case 'p':
316*7f2fe78bSCy Schubert clientname = optarg;
317*7f2fe78bSCy Schubert break;
318*7f2fe78bSCy Schubert default:
319*7f2fe78bSCy Schubert abort();
320*7f2fe78bSCy Schubert }
321*7f2fe78bSCy Schubert }
322*7f2fe78bSCy Schubert argv += optind;
323*7f2fe78bSCy Schubert /* Parse arguments. */
324*7f2fe78bSCy Schubert assert(*argv != NULL);
325*7f2fe78bSCy Schubert check(krb5_parse_name(ctx, *argv++, &server));
326*7f2fe78bSCy Schubert
327*7f2fe78bSCy Schubert count = 0;
328*7f2fe78bSCy Schubert for (; argv[0] != NULL && argv[1] != NULL; argv += 2) {
329*7f2fe78bSCy Schubert ad = make_authdata(argv[0], argv[1]);
330*7f2fe78bSCy Schubert req_authdata = realloc(req_authdata,
331*7f2fe78bSCy Schubert (count + 2) * sizeof(*req_authdata));
332*7f2fe78bSCy Schubert assert(req_authdata != NULL);
333*7f2fe78bSCy Schubert req_authdata[count++] = ad;
334*7f2fe78bSCy Schubert req_authdata[count] = NULL;
335*7f2fe78bSCy Schubert }
336*7f2fe78bSCy Schubert assert(*argv == NULL);
337*7f2fe78bSCy Schubert
338*7f2fe78bSCy Schubert if (ccname != NULL)
339*7f2fe78bSCy Schubert check(krb5_cc_resolve(ctx, ccname, &ccache));
340*7f2fe78bSCy Schubert else
341*7f2fe78bSCy Schubert check(krb5_cc_default(ctx, &ccache));
342*7f2fe78bSCy Schubert
343*7f2fe78bSCy Schubert if (clientname != NULL)
344*7f2fe78bSCy Schubert check(krb5_parse_name(ctx, clientname, &client));
345*7f2fe78bSCy Schubert else
346*7f2fe78bSCy Schubert check(krb5_cc_get_principal(ctx, ccache, &client));
347*7f2fe78bSCy Schubert
348*7f2fe78bSCy Schubert memset(&in_creds, 0, sizeof(in_creds));
349*7f2fe78bSCy Schubert in_creds.client = client;
350*7f2fe78bSCy Schubert in_creds.server = server;
351*7f2fe78bSCy Schubert in_creds.authdata = req_authdata;
352*7f2fe78bSCy Schubert
353*7f2fe78bSCy Schubert check(krb5_get_credentials(ctx, KRB5_GC_NO_STORE, ccache, &in_creds,
354*7f2fe78bSCy Schubert &creds));
355*7f2fe78bSCy Schubert
356*7f2fe78bSCy Schubert assert(in_creds.authdata == NULL || creds->authdata != NULL);
357*7f2fe78bSCy Schubert
358*7f2fe78bSCy Schubert check(krb5_decode_ticket(&creds->ticket, &ticket));
359*7f2fe78bSCy Schubert check(krb5_kt_default(ctx, &keytab));
360*7f2fe78bSCy Schubert check(krb5_kt_get_entry(ctx, keytab, ticket->server, ticket->enc_part.kvno,
361*7f2fe78bSCy Schubert ticket->enc_part.enctype, &ktent));
362*7f2fe78bSCy Schubert check(krb5_decrypt_tkt_part(ctx, &ktent.key, ticket));
363*7f2fe78bSCy Schubert
364*7f2fe78bSCy Schubert display_authdata_list(ticket->enc_part2->authorization_data,
365*7f2fe78bSCy Schubert ticket->enc_part2, &ktent.key, ' ', TRUE);
366*7f2fe78bSCy Schubert
367*7f2fe78bSCy Schubert while (count > 0) {
368*7f2fe78bSCy Schubert free(req_authdata[--count]->contents);
369*7f2fe78bSCy Schubert free(req_authdata[count]);
370*7f2fe78bSCy Schubert }
371*7f2fe78bSCy Schubert free(req_authdata);
372*7f2fe78bSCy Schubert krb5_free_keytab_entry_contents(ctx, &ktent);
373*7f2fe78bSCy Schubert krb5_free_creds(ctx, creds);
374*7f2fe78bSCy Schubert krb5_free_ticket(ctx, ticket);
375*7f2fe78bSCy Schubert krb5_free_principal(ctx, client);
376*7f2fe78bSCy Schubert krb5_free_principal(ctx, server);
377*7f2fe78bSCy Schubert krb5_cc_close(ctx, ccache);
378*7f2fe78bSCy Schubert krb5_kt_close(ctx, keytab);
379*7f2fe78bSCy Schubert krb5_free_context(ctx);
380*7f2fe78bSCy Schubert return 0;
381*7f2fe78bSCy Schubert }
382