Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/tests/hammer/kdc5_hammer.c
34914 views
1
/* tests/hammer/kdc5_hammer.c */
2
/*
3
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
4
* All Rights Reserved.
5
*
6
* Export of this software from the United States of America may
7
* require a specific license from the United States Government.
8
* It is the responsibility of any person or organization contemplating
9
* export to obtain such a license before exporting.
10
*
11
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12
* distribute this software and its documentation for any purpose and
13
* without fee is hereby granted, provided that the above copyright
14
* notice appear in all copies and that both that copyright notice and
15
* this permission notice appear in supporting documentation, and that
16
* the name of M.I.T. not be used in advertising or publicity pertaining
17
* to distribution of the software without specific, written prior
18
* permission. Furthermore if you modify this software you must label
19
* your software as modified software and not distribute it in such a
20
* fashion that it might be confused with the original M.I.T. software.
21
* M.I.T. makes no representations about the suitability of
22
* this software for any purpose. It is provided "as is" without express
23
* or implied warranty.
24
*/
25
26
#include "k5-int.h"
27
#include "com_err.h"
28
#include <sys/time.h>
29
30
#define KRB5_DEFAULT_OPTIONS 0
31
#define KRB5_DEFAULT_LIFE 60*60*8 /* 8 hours */
32
#define KRB5_RENEWABLE_LIFE 60*60*2 /* 2 hours */
33
34
struct h_timer {
35
float ht_cumulative;
36
float ht_min;
37
float ht_max;
38
krb5_int32 ht_observations;
39
};
40
41
extern int optind;
42
extern char *optarg;
43
char *prog;
44
45
static int brief;
46
static char *cur_realm = 0;
47
static int do_timer = 0;
48
49
krb5_data tgtname = {
50
0,
51
KRB5_TGS_NAME_SIZE,
52
KRB5_TGS_NAME
53
};
54
55
int verify_cs_pair
56
(krb5_context,
57
char *,
58
krb5_principal,
59
char *,
60
char *,
61
int, int, int,
62
krb5_ccache);
63
64
int get_tgt
65
(krb5_context,
66
char *,
67
krb5_principal *,
68
krb5_ccache);
69
70
static void
71
usage(char *who, int status)
72
{
73
fprintf(stderr,
74
"usage: %s -p prefix -n num_to_check [-c cachename] [-r realmname]\n",
75
who);
76
fprintf(stderr, "\t [-D depth]\n");
77
fprintf(stderr, "\t [-P preauth type] [-R repeat_count] [-t] [-b] [-v] \n");
78
79
exit(status);
80
}
81
82
static krb5_preauthtype * patype = NULL, patypedata[2] = { 0, -1 };
83
static krb5_context test_context;
84
85
struct timeval tstart_time, tend_time;
86
struct timezone dontcare;
87
88
struct h_timer in_tkt_times = { 0.0, 1000000.0, -1.0, 0 };
89
struct h_timer tgs_req_times = { 0.0, 1000000.0, -1.0, 0 };
90
/*
91
* Timer macros.
92
*/
93
#define swatch_on() ((void) gettimeofday(&tstart_time, &dontcare))
94
#define swatch_eltime() ((gettimeofday(&tend_time, &dontcare)) ? -1.0 : \
95
(((float) (tend_time.tv_sec - \
96
tstart_time.tv_sec)) + \
97
(((float) (tend_time.tv_usec - \
98
tstart_time.tv_usec))/1000000.0)))
99
100
int
101
main(int argc, char **argv)
102
{
103
krb5_ccache ccache = NULL;
104
char *cache_name = NULL; /* -f option */
105
int option;
106
int errflg = 0;
107
krb5_error_code code;
108
int num_to_check, n, i, j, repeat_count, counter;
109
int n_tried, errors;
110
char prefix[BUFSIZ], client[4096], server[4096];
111
int depth;
112
char ctmp[4096], ctmp2[BUFSIZ], stmp[4096], stmp2[BUFSIZ];
113
krb5_principal client_princ;
114
krb5_error_code retval;
115
116
krb5_init_context(&test_context);
117
118
if (strrchr(argv[0], '/'))
119
prog = strrchr(argv[0], '/')+1;
120
else
121
prog = argv[0];
122
123
num_to_check = 0;
124
depth = 1;
125
repeat_count = 1;
126
brief = 0;
127
n_tried = 0;
128
errors = 0;
129
130
while ((option = getopt(argc, argv, "D:p:n:c:R:P:e:bvr:t")) != -1) {
131
switch (option) {
132
case 't':
133
do_timer = 1;
134
break;
135
case 'b':
136
brief = 1;
137
break;
138
case 'v':
139
brief = 0;
140
break;
141
case 'R':
142
repeat_count = atoi(optarg); /* how many times? */
143
break;
144
case 'r':
145
cur_realm = optarg;
146
break;
147
case 'D':
148
depth = atoi(optarg); /* how deep to go */
149
break;
150
case 'p': /* prefix name to check */
151
strncpy(prefix, optarg, sizeof(prefix) - 1);
152
prefix[sizeof(prefix) - 1] = '\0';
153
break;
154
case 'n': /* how many to check */
155
num_to_check = atoi(optarg);
156
break;
157
case 'P':
158
patypedata[0] = atoi(optarg);
159
patype = patypedata;
160
break;
161
case 'c':
162
if (ccache == NULL) {
163
cache_name = optarg;
164
165
code = krb5_cc_resolve (test_context, cache_name, &ccache);
166
if (code != 0) {
167
com_err (prog, code, "resolving %s", cache_name);
168
errflg++;
169
}
170
} else {
171
fprintf(stderr, "Only one -c option allowed\n");
172
errflg++;
173
}
174
break;
175
case '?':
176
default:
177
errflg++;
178
break;
179
}
180
}
181
182
if (!(num_to_check && prefix[0]) || errflg)
183
usage(prog, 1);
184
185
if (!cur_realm) {
186
if ((retval = krb5_get_default_realm(test_context, &cur_realm))) {
187
com_err(prog, retval, "while retrieving default realm name");
188
exit(1);
189
}
190
}
191
192
if (ccache == NULL) {
193
if ((code = krb5_cc_default(test_context, &ccache))) {
194
com_err(prog, code, "while getting default ccache");
195
exit(1);
196
}
197
}
198
199
memset(ctmp, 0, sizeof(ctmp));
200
memset(stmp, 0, sizeof(stmp));
201
202
for (counter = 0; counter < repeat_count; counter++) {
203
fprintf(stderr, "\nRound %d\n", counter);
204
205
for (n = 1; n <= num_to_check; n++) {
206
/* build the new principal name */
207
/* we can't pick random names because we need to generate all the names
208
again given a prefix and count to test the db lib and kdb */
209
ctmp[0] = '\0';
210
for (i = 1; i <= depth; i++) {
211
(void) snprintf(ctmp2, sizeof(ctmp2), "%s%s%d-DEPTH-%d",
212
(i != 1) ? "/" : "", prefix, n, i);
213
ctmp2[sizeof(ctmp2) - 1] = '\0';
214
strncat(ctmp, ctmp2, sizeof(ctmp) - 1 - strlen(ctmp));
215
ctmp[sizeof(ctmp) - 1] = '\0';
216
snprintf(client, sizeof(client), "%s@%s", ctmp, cur_realm);
217
218
if (get_tgt (test_context, client, &client_princ, ccache)) {
219
errors++;
220
n_tried++;
221
continue;
222
}
223
n_tried++;
224
225
stmp[0] = '\0';
226
for (j = 1; j <= depth; j++) {
227
(void) snprintf(stmp2, sizeof(stmp2), "%s%s%d-DEPTH-%d",
228
(j != 1) ? "/" : "", prefix, n, j);
229
stmp2[sizeof (stmp2) - 1] = '\0';
230
strncat(stmp, stmp2, sizeof(stmp) - 1 - strlen(stmp));
231
stmp[sizeof(stmp) - 1] = '\0';
232
snprintf(server, sizeof(server), "%s@%s", stmp, cur_realm);
233
if (verify_cs_pair(test_context, client, client_princ,
234
stmp, cur_realm, n, i, j, ccache))
235
errors++;
236
n_tried++;
237
}
238
krb5_free_principal(test_context, client_princ);
239
}
240
}
241
}
242
fprintf (stderr, "\nTried %d. Got %d errors.\n", n_tried, errors);
243
if (do_timer) {
244
if (in_tkt_times.ht_observations)
245
fprintf(stderr,
246
"%8d AS_REQ requests: %9.6f average (min: %9.6f, max:%9.6f)\n",
247
in_tkt_times.ht_observations,
248
in_tkt_times.ht_cumulative /
249
(float) in_tkt_times.ht_observations,
250
in_tkt_times.ht_min,
251
in_tkt_times.ht_max);
252
if (tgs_req_times.ht_observations)
253
fprintf(stderr,
254
"%8d TGS_REQ requests: %9.6f average (min: %9.6f, max:%9.6f)\n",
255
tgs_req_times.ht_observations,
256
tgs_req_times.ht_cumulative /
257
(float) tgs_req_times.ht_observations,
258
tgs_req_times.ht_min,
259
tgs_req_times.ht_max);
260
}
261
262
(void) krb5_cc_close(test_context, ccache);
263
264
krb5_free_context(test_context);
265
266
exit(errors);
267
}
268
269
270
static krb5_error_code
271
get_server_key(krb5_context context, krb5_principal server,
272
krb5_enctype enctype, krb5_keyblock **key)
273
{
274
krb5_error_code retval;
275
krb5_encrypt_block eblock;
276
char * string;
277
krb5_data salt;
278
krb5_data pwd;
279
280
*key = NULL;
281
282
if ((retval = krb5_principal2salt(context, server, &salt)))
283
return retval;
284
285
if ((retval = krb5_unparse_name(context, server, &string)))
286
goto cleanup_salt;
287
288
pwd.data = string;
289
pwd.length = strlen(string);
290
291
if ((*key = (krb5_keyblock *)malloc(sizeof(krb5_keyblock)))) {
292
krb5_use_enctype(context, &eblock, enctype);
293
retval = krb5_string_to_key(context, &eblock, *key, &pwd, &salt);
294
if (retval) {
295
free(*key);
296
*key = NULL;
297
}
298
} else
299
retval = ENOMEM;
300
301
free(string);
302
303
cleanup_salt:
304
free(salt.data);
305
return retval;
306
}
307
308
int
309
verify_cs_pair(krb5_context context, char *p_client_str,
310
krb5_principal p_client, char *service, char *hostname,
311
int p_num, int c_depth, int s_depth, krb5_ccache ccache)
312
{
313
krb5_error_code retval;
314
krb5_creds creds;
315
krb5_creds * credsp = NULL;
316
krb5_ticket * ticket = NULL;
317
krb5_keyblock * keyblock = NULL;
318
krb5_auth_context auth_context = NULL;
319
krb5_data request_data = empty_data();
320
char * sname;
321
float dt;
322
323
if (brief)
324
fprintf(stderr, "\tprinc (%d) client (%d) for server (%d)\n",
325
p_num, c_depth, s_depth);
326
else
327
fprintf(stderr, "\tclient %s for server %s\n", p_client_str,
328
service);
329
330
/* Initialize variables */
331
memset(&creds, 0, sizeof(creds));
332
333
/* Do client side */
334
if (asprintf(&sname, "%s@%s", service, hostname) >= 0) {
335
retval = krb5_parse_name(context, sname, &creds.server);
336
free(sname);
337
}
338
else
339
retval = ENOMEM;
340
if (retval)
341
return(retval);
342
343
/* obtain ticket & session key */
344
if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) {
345
com_err(prog, retval, "while getting client princ for %s", hostname);
346
return retval;
347
}
348
349
if ((retval = krb5_get_credentials(context, 0,
350
ccache, &creds, &credsp))) {
351
com_err(prog, retval, "while getting creds for %s", hostname);
352
return retval;
353
}
354
355
if (do_timer)
356
swatch_on();
357
358
if ((retval = krb5_mk_req_extended(context, &auth_context, 0, NULL,
359
credsp, &request_data))) {
360
com_err(prog, retval, "while preparing AP_REQ for %s", hostname);
361
goto cleanup;
362
}
363
364
krb5_auth_con_free(context, auth_context);
365
auth_context = NULL;
366
367
/* Do server side now */
368
if ((retval = get_server_key(context, credsp->server,
369
credsp->keyblock.enctype, &keyblock))) {
370
com_err(prog, retval, "while getting server key for %s", hostname);
371
goto cleanup;
372
}
373
374
if (krb5_auth_con_init(context, &auth_context)) {
375
com_err(prog, retval, "while creating auth_context for %s", hostname);
376
goto cleanup;
377
}
378
379
if (krb5_auth_con_setuseruserkey(context, auth_context, keyblock)) {
380
com_err(prog, retval, "while setting auth_context key %s", hostname);
381
goto cleanup;
382
}
383
384
if ((retval = krb5_rd_req(context, &auth_context, &request_data,
385
NULL /* server */, 0, NULL, &ticket))) {
386
com_err(prog, retval, "while decoding AP_REQ for %s", hostname);
387
goto cleanup;
388
}
389
390
if (do_timer) {
391
dt = swatch_eltime();
392
tgs_req_times.ht_cumulative += dt;
393
tgs_req_times.ht_observations++;
394
if (dt > tgs_req_times.ht_max)
395
tgs_req_times.ht_max = dt;
396
if (dt < tgs_req_times.ht_min)
397
tgs_req_times.ht_min = dt;
398
}
399
400
if (!(krb5_principal_compare(context,ticket->enc_part2->client,p_client))){
401
char *returned_client;
402
if ((retval = krb5_unparse_name(context, ticket->enc_part2->client,
403
&returned_client)))
404
com_err (prog, retval,
405
"Client not as expected, but cannot unparse client name");
406
else
407
com_err (prog, 0, "Client not as expected (%s).", returned_client);
408
retval = KRB5_PRINC_NOMATCH;
409
free(returned_client);
410
} else {
411
retval = 0;
412
}
413
414
cleanup:
415
krb5_free_cred_contents(context, &creds);
416
krb5_free_ticket(context, ticket);
417
krb5_auth_con_free(context, auth_context);
418
krb5_free_keyblock(context, keyblock);
419
krb5_free_data_contents(context, &request_data);
420
krb5_free_creds(context, credsp);
421
422
return retval;
423
}
424
425
int
426
get_tgt(krb5_context context, char *p_client_str, krb5_principal *p_client,
427
krb5_ccache ccache)
428
{
429
long lifetime = KRB5_DEFAULT_LIFE; /* -l option */
430
krb5_error_code code;
431
krb5_creds my_creds;
432
krb5_timestamp start;
433
float dt;
434
krb5_get_init_creds_opt *options;
435
436
if (!brief)
437
fprintf(stderr, "\tgetting TGT for %s\n", p_client_str);
438
439
if ((code = krb5_timeofday(context, &start))) {
440
com_err(prog, code, "while getting time of day");
441
return(-1);
442
}
443
444
memset(&my_creds, 0, sizeof(my_creds));
445
446
if ((code = krb5_parse_name (context, p_client_str, p_client))) {
447
com_err (prog, code, "when parsing name %s", p_client_str);
448
return(-1);
449
}
450
451
code = krb5_cc_initialize (context, ccache, *p_client);
452
if (code != 0) {
453
com_err (prog, code, "when initializing cache");
454
return(-1);
455
}
456
457
if (do_timer)
458
swatch_on();
459
460
code = krb5_get_init_creds_opt_alloc(context, &options);
461
if (code != 0) {
462
com_err(prog, code, "when allocating init cred options");
463
return(-1);
464
}
465
466
krb5_get_init_creds_opt_set_tkt_life(options, lifetime);
467
468
code = krb5_get_init_creds_opt_set_out_ccache(context, options, ccache);
469
if (code != 0) {
470
com_err(prog, code, "when setting init cred output ccache");
471
return(-1);
472
}
473
474
code = krb5_get_init_creds_password(context, &my_creds, *p_client,
475
p_client_str, NULL, NULL, 0, NULL,
476
options);
477
if (do_timer) {
478
dt = swatch_eltime();
479
in_tkt_times.ht_cumulative += dt;
480
in_tkt_times.ht_observations++;
481
if (dt > in_tkt_times.ht_max)
482
in_tkt_times.ht_max = dt;
483
if (dt < in_tkt_times.ht_min)
484
in_tkt_times.ht_min = dt;
485
}
486
krb5_get_init_creds_opt_free(context, options);
487
krb5_free_cred_contents(context, &my_creds);
488
if (code != 0) {
489
com_err (prog, code, "while getting initial credentials");
490
return(-1);
491
}
492
493
return(0);
494
}
495
496