Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/kuser/kimpersonate.c
34860 views
1
/*
2
* Copyright (c) 2000 - 2007 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
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
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* 3. Neither the name of the Institute nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
20
*
21
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
* SUCH DAMAGE.
32
*/
33
34
#include "kuser_locl.h"
35
#include <parse_units.h>
36
37
static char *client_principal_str = NULL;
38
static krb5_principal client_principal;
39
static char *server_principal_str = NULL;
40
static krb5_principal server_principal;
41
42
static char *ccache_str = NULL;
43
44
static char *ticket_flags_str = NULL;
45
static TicketFlags ticket_flags;
46
static char *keytab_file = NULL;
47
static char *enctype_string = NULL;
48
static int expiration_time = 3600;
49
static struct getarg_strings client_addresses;
50
static int version_flag = 0;
51
static int help_flag = 0;
52
static int use_krb5 = 1;
53
54
static const char *enc_type = "des-cbc-md5";
55
56
/*
57
*
58
*/
59
60
static void
61
encode_ticket (krb5_context context,
62
EncryptionKey *skey,
63
krb5_enctype etype,
64
int skvno,
65
krb5_creds *cred)
66
{
67
size_t len, size;
68
char *buf;
69
krb5_error_code ret;
70
krb5_crypto crypto;
71
EncryptedData enc_part;
72
EncTicketPart et;
73
Ticket ticket;
74
75
memset (&enc_part, 0, sizeof(enc_part));
76
memset (&ticket, 0, sizeof(ticket));
77
78
/*
79
* Set up `enc_part'
80
*/
81
82
et.flags = cred->flags.b;
83
et.key = cred->session;
84
et.crealm = cred->client->realm;
85
copy_PrincipalName(&cred->client->name, &et.cname);
86
{
87
krb5_data empty_string;
88
89
krb5_data_zero(&empty_string);
90
et.transited.tr_type = DOMAIN_X500_COMPRESS;
91
et.transited.contents = empty_string;
92
}
93
et.authtime = cred->times.authtime;
94
et.starttime = NULL;
95
et.endtime = cred->times.endtime;
96
et.renew_till = NULL;
97
et.caddr = &cred->addresses;
98
et.authorization_data = NULL; /* XXX allow random authorization_data */
99
100
/*
101
* Encrypt `enc_part' of ticket with service key
102
*/
103
104
ASN1_MALLOC_ENCODE(EncTicketPart, buf, len, &et, &size, ret);
105
if (ret)
106
krb5_err(context, 1, ret, "EncTicketPart");
107
108
ret = krb5_crypto_init(context, skey, etype, &crypto);
109
if (ret)
110
krb5_err(context, 1, ret, "krb5_crypto_init");
111
ret = krb5_encrypt_EncryptedData (context,
112
crypto,
113
KRB5_KU_TICKET,
114
buf,
115
len,
116
skvno,
117
&ticket.enc_part);
118
if (ret)
119
krb5_err(context, 1, ret, "krb5_encrypt_EncryptedData");
120
121
free(buf);
122
krb5_crypto_destroy(context, crypto);
123
124
/*
125
* Encode ticket
126
*/
127
128
ticket.tkt_vno = 5;
129
ticket.realm = cred->server->realm;
130
copy_PrincipalName(&cred->server->name, &ticket.sname);
131
132
ASN1_MALLOC_ENCODE(Ticket, buf, len, &ticket, &size, ret);
133
if(ret)
134
krb5_err (context, 1, ret, "encode_Ticket");
135
136
krb5_data_copy(&cred->ticket, buf, len);
137
free(buf);
138
}
139
140
/*
141
*
142
*/
143
144
static int
145
create_krb5_tickets (krb5_context context, krb5_keytab kt)
146
{
147
krb5_error_code ret;
148
krb5_keytab_entry entry;
149
krb5_creds cred;
150
krb5_enctype etype;
151
krb5_ccache ccache;
152
153
memset (&cred, 0, sizeof(cred));
154
155
ret = krb5_string_to_enctype (context, enc_type, &etype);
156
if (ret)
157
krb5_err (context, 1, ret, "krb5_string_to_enctype");
158
ret = krb5_kt_get_entry (context, kt, server_principal,
159
0, etype, &entry);
160
if (ret)
161
krb5_err (context, 1, ret, "krb5_kt_get_entry");
162
163
/*
164
* setup cred
165
*/
166
167
168
ret = krb5_copy_principal (context, client_principal, &cred.client);
169
if (ret)
170
krb5_err (context, 1, ret, "krb5_copy_principal");
171
ret = krb5_copy_principal (context, server_principal, &cred.server);
172
if (ret)
173
krb5_err (context, 1, ret, "krb5_copy_principal");
174
krb5_generate_random_keyblock(context, etype, &cred.session);
175
176
cred.times.authtime = time(NULL);
177
cred.times.starttime = time(NULL);
178
cred.times.endtime = time(NULL) + expiration_time;
179
cred.times.renew_till = 0;
180
krb5_data_zero(&cred.second_ticket);
181
182
ret = krb5_get_all_client_addrs (context, &cred.addresses);
183
if (ret)
184
krb5_err (context, 1, ret, "krb5_get_all_client_addrs");
185
cred.flags.b = ticket_flags;
186
187
188
/*
189
* Encode encrypted part of ticket
190
*/
191
192
encode_ticket (context, &entry.keyblock, etype, entry.vno, &cred);
193
194
/*
195
* Write to cc
196
*/
197
198
if (ccache_str) {
199
ret = krb5_cc_resolve(context, ccache_str, &ccache);
200
if (ret)
201
krb5_err (context, 1, ret, "krb5_cc_resolve");
202
} else {
203
ret = krb5_cc_default (context, &ccache);
204
if (ret)
205
krb5_err (context, 1, ret, "krb5_cc_default");
206
}
207
208
ret = krb5_cc_initialize (context, ccache, cred.client);
209
if (ret)
210
krb5_err (context, 1, ret, "krb5_cc_initialize");
211
212
ret = krb5_cc_store_cred (context, ccache, &cred);
213
if (ret)
214
krb5_err (context, 1, ret, "krb5_cc_store_cred");
215
216
krb5_free_cred_contents (context, &cred);
217
krb5_cc_close (context, ccache);
218
219
return 0;
220
}
221
222
/*
223
*
224
*/
225
226
static void
227
setup_env (krb5_context context, krb5_keytab *kt)
228
{
229
krb5_error_code ret;
230
231
if (keytab_file)
232
ret = krb5_kt_resolve (context, keytab_file, kt);
233
else
234
ret = krb5_kt_default (context, kt);
235
if (ret)
236
krb5_err (context, 1, ret, "resolving keytab");
237
238
if (client_principal_str == NULL)
239
krb5_errx (context, 1, "missing client principal");
240
ret = krb5_parse_name (context, client_principal_str, &client_principal);
241
if (ret)
242
krb5_err (context, 1, ret, "resolvning client name");
243
244
if (server_principal_str == NULL)
245
krb5_errx (context, 1, "missing server principal");
246
ret = krb5_parse_name (context, server_principal_str, &server_principal);
247
if (ret)
248
krb5_err (context, 1, ret, "resolvning client name");
249
250
if (ticket_flags_str) {
251
int ticket_flags_int;
252
253
ticket_flags_int = parse_flags(ticket_flags_str,
254
asn1_TicketFlags_units(), 0);
255
if (ticket_flags_int <= 0) {
256
krb5_warnx (context, "bad ticket flags: `%s'", ticket_flags_str);
257
print_flags_table (asn1_TicketFlags_units(), stderr);
258
exit (1);
259
}
260
if (ticket_flags_int)
261
ticket_flags = int2TicketFlags (ticket_flags_int);
262
}
263
}
264
265
/*
266
*
267
*/
268
269
struct getargs args[] = {
270
{ "ccache", 0, arg_string, &ccache_str,
271
"name of kerberos 5 credential cache", "cache-name"},
272
{ "server", 's', arg_string, &server_principal_str,
273
"name of server principal", NULL },
274
{ "client", 'c', arg_string, &client_principal_str,
275
"name of client principal", NULL },
276
{ "keytab", 'k', arg_string, &keytab_file,
277
"name of keytab file", NULL },
278
{ "krb5", '5', arg_flag, &use_krb5,
279
"create a kerberos 5 ticket", NULL },
280
{ "expire-time", 'e', arg_integer, &expiration_time,
281
"lifetime of ticket in seconds", NULL },
282
{ "client-addresses", 'a', arg_strings, &client_addresses,
283
"addresses of client", NULL },
284
{ "enc-type", 't', arg_string, &enctype_string,
285
"encryption type", NULL },
286
{ "ticket-flags", 'f', arg_string, &ticket_flags_str,
287
"ticket flags for krb5 ticket", NULL },
288
{ "version", 0, arg_flag, &version_flag, "Print version",
289
NULL },
290
{ "help", 0, arg_flag, &help_flag, NULL,
291
NULL }
292
};
293
294
static void
295
usage (int ret)
296
{
297
arg_printusage (args,
298
sizeof(args) / sizeof(args[0]),
299
NULL,
300
"");
301
exit (ret);
302
}
303
304
int
305
main (int argc, char **argv)
306
{
307
int optidx = 0;
308
krb5_error_code ret;
309
krb5_context context;
310
krb5_keytab kt;
311
312
setprogname (argv[0]);
313
314
ret = krb5_init_context (&context);
315
if (ret)
316
errx(1, "krb5_init_context failed: %u", ret);
317
318
if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
319
usage(1);
320
321
if (help_flag)
322
usage(0);
323
324
if (version_flag) {
325
print_version(NULL);
326
return 0;
327
}
328
329
if (enctype_string)
330
enc_type = enctype_string;
331
332
setup_env(context, &kt);
333
334
if (use_krb5)
335
create_krb5_tickets(context, kt);
336
337
krb5_kt_close(context, kt);
338
339
return 0;
340
}
341
342