1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3 * Copyright (C) 2019 by the Massachusetts Institute of Technology.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Usage: s4u2self user self out_cache [ad-type ad-contents]
34 *
35 * The default ccache contains a TGT for the intermediate service self. An
36 * S4U2Self request is made to self. The resulting cred is stored in
37 * out_cache.
38 */
39
40 #include <k5-int.h>
41
42 static krb5_context ctx;
43
44 static void
check(krb5_error_code code)45 check(krb5_error_code code)
46 {
47 const char *errmsg;
48
49 if (code) {
50 errmsg = krb5_get_error_message(ctx, code);
51 fprintf(stderr, "%s\n", errmsg);
52 krb5_free_error_message(ctx, errmsg);
53 exit(1);
54 }
55 }
56
57 static krb5_authdata **
make_request_authdata(int type,const char * contents)58 make_request_authdata(int type, const char *contents)
59 {
60 krb5_authdata *ad;
61 krb5_authdata **req_authdata;
62
63 ad = malloc(sizeof(*ad));
64 assert(ad != NULL);
65 ad->magic = KV5M_AUTHDATA;
66 ad->ad_type = type;
67 ad->length = strlen(contents);
68 ad->contents = (unsigned char *)strdup(contents);
69 assert(ad->contents != NULL);
70
71 req_authdata = malloc(2 * sizeof(*req_authdata));
72 assert(req_authdata != NULL);
73 req_authdata[0] = ad;
74 req_authdata[1] = NULL;
75
76 return req_authdata;
77 }
78
79 int
main(int argc,char ** argv)80 main(int argc, char **argv)
81 {
82 krb5_context context;
83 krb5_ccache defcc, ocache;
84 krb5_principal client, self;
85 krb5_creds mcred, *new_cred;
86 krb5_authdata **req_authdata = NULL;
87
88 if (argc == 6) {
89 req_authdata = make_request_authdata(atoi(argv[4]), argv[5]);
90 argc -= 2;
91 }
92
93 assert(argc == 4);
94 check(krb5_init_context(&context));
95
96 /* Open the default ccache. */
97 check(krb5_cc_default(context, &defcc));
98
99 check(krb5_parse_name(context, argv[1], &client));
100 check(krb5_parse_name(context, argv[2], &self));
101
102 memset(&mcred, 0, sizeof(mcred));
103 mcred.client = client;
104 mcred.server = self;
105 mcred.authdata = req_authdata;
106 check(krb5_get_credentials_for_user(context, KRB5_GC_NO_STORE |
107 KRB5_GC_CANONICALIZE, defcc,
108 &mcred, NULL, &new_cred));
109
110 if (strcmp(argv[3], "-") == 0) {
111 check(krb5_cc_store_cred(context, defcc, new_cred));
112 } else {
113 check(krb5_cc_resolve(context, argv[3], &ocache));
114 check(krb5_cc_initialize(context, ocache, new_cred->client));
115 check(krb5_cc_store_cred(context, ocache, new_cred));
116 krb5_cc_close(context, ocache);
117 }
118
119 assert(req_authdata == NULL || new_cred->authdata != NULL);
120
121 krb5_cc_close(context, defcc);
122 krb5_free_principal(context, client);
123 krb5_free_principal(context, self);
124 krb5_free_creds(context, new_cred);
125 krb5_free_authdata(context, req_authdata);
126 krb5_free_context(context);
127 return 0;
128 }
129