Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/plugins/preauth/test/cltest.c
34890 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* plugins/preauth/test/cltest.c - Test clpreauth module */
3
/*
4
* Copyright (C) 2015, 2017 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
* This module is used to test preauth interface features. At this time, the
35
* clpreauth module does the following:
36
*
37
* - It decrypts a message from the initial KDC pa-data using the reply key and
38
* prints it to stdout. (The unencrypted message "no key" can also be
39
* displayed.)
40
*
41
* - If a second round trip is requested, it prints the pa-data contents
42
* accompanying the second round trip request.
43
*
44
* - It pulls an "indicators" attribute from the gic preauth options and sends
45
* it to the server, instructing the kdcpreauth module to assert one or more
46
* space-separated authentication indicators. (This string is sent on both
47
* round trips if a second round trip is requested.)
48
*
49
* - If a KDC_ERR_ENCTYPE_NOSUPP error with e-data is received, it prints the
50
* accompanying error padata and sends a follow-up request containing
51
* "tryagain".
52
*
53
* - If the "fail_optimistic", "fail_2rt", or "fail_tryagain" gic options are
54
* set, it fails with a recognizable error string at the requested point in
55
* processing.
56
*
57
* - If the "disable_fallback" gic option is set, fallback is disabled when a
58
* client message is generated.
59
*/
60
61
#include "k5-int.h"
62
#include <krb5/clpreauth_plugin.h>
63
#include "common.h"
64
65
static krb5_preauthtype pa_types[] = { TEST_PA_TYPE, 0 };
66
67
struct client_state {
68
char *indicators;
69
krb5_boolean fail_optimistic;
70
krb5_boolean fail_2rt;
71
krb5_boolean fail_tryagain;
72
krb5_boolean disable_fallback;
73
};
74
75
struct client_request_state {
76
krb5_boolean second_round_trip;
77
};
78
79
static krb5_error_code
80
test_init(krb5_context context, krb5_clpreauth_moddata *moddata_out)
81
{
82
struct client_state *st;
83
84
st = malloc(sizeof(*st));
85
assert(st != NULL);
86
st->indicators = NULL;
87
st->fail_optimistic = st->fail_2rt = st->fail_tryagain = FALSE;
88
st->disable_fallback = FALSE;
89
*moddata_out = (krb5_clpreauth_moddata)st;
90
return 0;
91
}
92
93
static void
94
test_fini(krb5_context context, krb5_clpreauth_moddata moddata)
95
{
96
struct client_state *st = (struct client_state *)moddata;
97
98
free(st->indicators);
99
free(st);
100
}
101
102
static void
103
test_request_init(krb5_context context, krb5_clpreauth_moddata moddata,
104
krb5_clpreauth_modreq *modreq_out)
105
{
106
struct client_request_state *reqst;
107
108
reqst = malloc(sizeof(*reqst));
109
assert(reqst != NULL);
110
reqst->second_round_trip = FALSE;
111
*modreq_out = (krb5_clpreauth_modreq)reqst;
112
}
113
114
static void
115
test_request_fini(krb5_context context, krb5_clpreauth_moddata moddata,
116
krb5_clpreauth_modreq modreq)
117
{
118
free(modreq);
119
}
120
121
static krb5_error_code
122
test_process(krb5_context context, krb5_clpreauth_moddata moddata,
123
krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
124
krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
125
krb5_kdc_req *request, krb5_data *encoded_request_body,
126
krb5_data *encoded_previous_request, krb5_pa_data *pa_data,
127
krb5_prompter_fct prompter, void *prompter_data,
128
krb5_pa_data ***out_pa_data)
129
{
130
struct client_state *st = (struct client_state *)moddata;
131
struct client_request_state *reqst = (struct client_request_state *)modreq;
132
krb5_error_code ret;
133
krb5_keyblock *k;
134
krb5_enc_data enc;
135
krb5_data plain;
136
const char *indstr;
137
138
if (pa_data->length == 0) {
139
/* This is an optimistic preauth test. Send a recognizable padata
140
* value so the KDC knows not to expect a cookie. */
141
if (st->fail_optimistic) {
142
k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced optimistic fail");
143
return KRB5_PREAUTH_FAILED;
144
}
145
*out_pa_data = make_pa_list("optimistic", 10);
146
if (st->disable_fallback)
147
cb->disable_fallback(context, rock);
148
return 0;
149
} else if (reqst->second_round_trip) {
150
printf("2rt: %.*s\n", pa_data->length, pa_data->contents);
151
if (st->fail_2rt) {
152
k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced 2rt fail");
153
return KRB5_PREAUTH_FAILED;
154
}
155
} else if (pa_data->length == 6 &&
156
memcmp(pa_data->contents, "no key", 6) == 0) {
157
printf("no key\n");
158
} else {
159
/* This fails during s4u_identify_user(), so don't assert. */
160
ret = cb->get_as_key(context, rock, &k);
161
if (ret)
162
return ret;
163
ret = alloc_data(&plain, pa_data->length);
164
assert(!ret);
165
enc.enctype = k->enctype;
166
enc.ciphertext = make_data(pa_data->contents, pa_data->length);
167
ret = krb5_c_decrypt(context, k, 1024, NULL, &enc, &plain);
168
assert(!ret);
169
printf("%.*s\n", plain.length, plain.data);
170
free(plain.data);
171
}
172
reqst->second_round_trip = TRUE;
173
174
indstr = (st->indicators != NULL) ? st->indicators : "";
175
*out_pa_data = make_pa_list(indstr, strlen(indstr));
176
if (st->disable_fallback)
177
cb->disable_fallback(context, rock);
178
return 0;
179
}
180
181
static krb5_error_code
182
test_tryagain(krb5_context context, krb5_clpreauth_moddata moddata,
183
krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
184
krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
185
krb5_kdc_req *request, krb5_data *enc_req, krb5_data *enc_prev,
186
krb5_preauthtype pa_type, krb5_error *error,
187
krb5_pa_data **padata, krb5_prompter_fct prompter,
188
void *prompter_data, krb5_pa_data ***padata_out)
189
{
190
struct client_state *st = (struct client_state *)moddata;
191
int i;
192
193
*padata_out = NULL;
194
if (st->fail_tryagain) {
195
k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced tryagain fail");
196
return KRB5_PREAUTH_FAILED;
197
}
198
if (error->error != KDC_ERR_ENCTYPE_NOSUPP)
199
return KRB5_PREAUTH_FAILED;
200
for (i = 0; padata[i] != NULL; i++) {
201
if (padata[i]->pa_type == TEST_PA_TYPE)
202
printf("tryagain: %.*s\n", padata[i]->length, padata[i]->contents);
203
}
204
*padata_out = make_pa_list("tryagain", 8);
205
return 0;
206
}
207
208
static krb5_error_code
209
test_gic_opt(krb5_context kcontext, krb5_clpreauth_moddata moddata,
210
krb5_get_init_creds_opt *opt, const char *attr, const char *value)
211
{
212
struct client_state *st = (struct client_state *)moddata;
213
214
if (strcmp(attr, "indicators") == 0) {
215
free(st->indicators);
216
st->indicators = strdup(value);
217
assert(st->indicators != NULL);
218
} else if (strcmp(attr, "fail_optimistic") == 0) {
219
st->fail_optimistic = TRUE;
220
} else if (strcmp(attr, "fail_2rt") == 0) {
221
st->fail_2rt = TRUE;
222
} else if (strcmp(attr, "fail_tryagain") == 0) {
223
st->fail_tryagain = TRUE;
224
} else if (strcmp(attr, "disable_fallback") == 0) {
225
st->disable_fallback = TRUE;
226
}
227
return 0;
228
}
229
230
krb5_error_code
231
clpreauth_test_initvt(krb5_context context, int maj_ver,
232
int min_ver, krb5_plugin_vtable vtable);
233
234
krb5_error_code
235
clpreauth_test_initvt(krb5_context context, int maj_ver,
236
int min_ver, krb5_plugin_vtable vtable)
237
{
238
krb5_clpreauth_vtable vt;
239
240
if (maj_ver != 1)
241
return KRB5_PLUGIN_VER_NOTSUPP;
242
vt = (krb5_clpreauth_vtable)vtable;
243
vt->name = "test";
244
vt->pa_type_list = pa_types;
245
vt->init = test_init;
246
vt->fini = test_fini;
247
vt->request_init = test_request_init;
248
vt->request_fini = test_request_fini;
249
vt->process = test_process;
250
vt->tryagain = test_tryagain;
251
vt->gic_opts = test_gic_opt;
252
return 0;
253
}
254
255