xref: /freebsd/crypto/krb5/src/tests/s4u2proxy.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* tests/s4u2proxy.c - S4U2Proxy test harness */
3 /*
4  * Copyright (C) 2015 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 /*
34  * Usage: s4u2proxy evccname targetname [ad-type ad-contents]
35  *
36  * evccname contains an evidence ticket.  The default ccache contains a TGT for
37  * the intermediate service.  The default keytab contains a key for the
38  * intermediate service.  An S4U2Proxy request is made to get a ticket from
39  * evccname's default principal to the target service.  The resulting cred is
40  * stored in the default ccache.
41  */
42 
43 #include <k5-int.h>
44 
45 static krb5_context ctx;
46 
47 static void
check(krb5_error_code code)48 check(krb5_error_code code)
49 {
50     const char *errmsg;
51 
52     if (code) {
53         errmsg = krb5_get_error_message(ctx, code);
54         fprintf(stderr, "%s\n", errmsg);
55         krb5_free_error_message(ctx, errmsg);
56         exit(1);
57     }
58 }
59 
60 static krb5_authdata **
make_request_authdata(int type,const char * contents)61 make_request_authdata(int type, const char *contents)
62 {
63     krb5_authdata *ad;
64     krb5_authdata **req_authdata;
65 
66     ad = malloc(sizeof(*ad));
67     assert(ad != NULL);
68     ad->magic = KV5M_AUTHDATA;
69     ad->ad_type = type;
70     ad->length = strlen(contents);
71     ad->contents = (unsigned char *)strdup(contents);
72     assert(ad->contents != NULL);
73 
74     req_authdata = malloc(2 * sizeof(*req_authdata));
75     assert(req_authdata != NULL);
76     req_authdata[0] = ad;
77     req_authdata[1] = NULL;
78 
79     return req_authdata;
80 }
81 
82 int
main(int argc,char ** argv)83 main(int argc, char **argv)
84 {
85     krb5_context context;
86     krb5_ccache defcc, evcc;
87     krb5_principal client_name, int_name, target_name;
88     krb5_keytab defkt;
89     krb5_creds mcred, ev_cred, *new_cred;
90     krb5_ticket *ev_ticket;
91     krb5_authdata **req_authdata = NULL;
92 
93     if (argc == 5) {
94         req_authdata = make_request_authdata(atoi(argv[3]), argv[4]);
95         argc -= 2;
96     }
97 
98     assert(argc == 3);
99     check(krb5_init_context(&context));
100 
101     /* Open the default ccache, evidence ticket ccache, and default keytab. */
102     check(krb5_cc_default(context, &defcc));
103     check(krb5_cc_resolve(context, argv[1], &evcc));
104     check(krb5_kt_default(context, &defkt));
105 
106     /* Determine the client name, intermediate name, and target name. */
107     check(krb5_cc_get_principal(context, evcc, &client_name));
108     check(krb5_cc_get_principal(context, defcc, &int_name));
109     check(krb5_parse_name(context, argv[2], &target_name));
110 
111     /* Retrieve and decrypt the evidence ticket. */
112     memset(&mcred, 0, sizeof(mcred));
113     mcred.client = client_name;
114     mcred.server = int_name;
115     check(krb5_cc_retrieve_cred(context, evcc, 0, &mcred, &ev_cred));
116     check(krb5_decode_ticket(&ev_cred.ticket, &ev_ticket));
117     check(krb5_server_decrypt_ticket_keytab(context, defkt, ev_ticket));
118 
119     /* Make an S4U2Proxy request for the target service. */
120     mcred.client = client_name;
121     mcred.server = target_name;
122     mcred.authdata = req_authdata;
123     check(krb5_get_credentials_for_proxy(context, KRB5_GC_NO_STORE |
124                                          KRB5_GC_CANONICALIZE, defcc,
125                                          &mcred, ev_ticket, &new_cred));
126 
127     assert(data_eq(new_cred->second_ticket, ev_cred.ticket));
128     assert(new_cred->second_ticket.length != 0);
129 
130     /* Store the new cred in the default ccache. */
131     check(krb5_cc_store_cred(context, defcc, new_cred));
132 
133     assert(req_authdata == NULL || new_cred->authdata != NULL);
134 
135     krb5_cc_close(context, defcc);
136     krb5_cc_close(context, evcc);
137     krb5_kt_close(context, defkt);
138     krb5_free_principal(context, client_name);
139     krb5_free_principal(context, int_name);
140     krb5_free_principal(context, target_name);
141     krb5_free_cred_contents(context, &ev_cred);
142     krb5_free_ticket(context, ev_ticket);
143     krb5_free_creds(context, new_cred);
144     krb5_free_authdata(context, req_authdata);
145     krb5_free_context(context);
146     return 0;
147 }
148