Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/plugins/preauth/test/kdctest.c
34907 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* plugins/preauth/test/kdctest.c - Test kdcpreauth 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. Currently, the
35
* kdcpreauth module does the following:
36
*
37
* - When generating initial method-data, it retrieves the "teststring"
38
* attribute from the client principal and sends it to the client, encrypted
39
* in the reply key. (The plain text "no key" is sent if there is no reply
40
* key; the encrypted message "no attr" is sent if there is no string
41
* attribute.) It also sets a cookie containing "method-data".
42
*
43
* - If the "err" attribute is set on the client principal, the verify method
44
* returns an KDC_ERR_ETYPE_NOSUPP error on the first try, with the contents
45
* of the err attribute as pa-data. If the client tries again with the
46
* padata value "tryagain", the verify method preuthenticates successfully
47
* with no additional processing.
48
*
49
* - If the "failopt" attribute is set on the client principal, the verify
50
* method returns KDC_ERR_PREAUTH_FAILED on optimistic preauth attempts.
51
*
52
* - If the "2rt" attribute is set on client principal, the verify method sends
53
* the client a KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error with the contents of
54
* the 2rt attribute as pa-data, and sets a cookie containing "more". If the
55
* "fail2rt" attribute is set on the client principal, the client's second
56
* try results in a KDC_ERR_PREAUTH_FAILED error.
57
*
58
* - It receives a space-separated list from the clpreauth module and asserts
59
* each string as an authentication indicator. It always succeeds in
60
* pre-authenticating the request.
61
*/
62
63
#include "k5-int.h"
64
#include <krb5/kdcpreauth_plugin.h>
65
#include "common.h"
66
67
#define TEST_PA_TYPE -123
68
69
static krb5_preauthtype pa_types[] = { TEST_PA_TYPE, 0 };
70
71
static void
72
test_edata(krb5_context context, krb5_kdc_req *req,
73
krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
74
krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
75
krb5_kdcpreauth_edata_respond_fn respond, void *arg)
76
{
77
krb5_error_code ret;
78
const krb5_keyblock *k = cb->client_keyblock(context, rock);
79
krb5_pa_data *pa;
80
size_t enclen;
81
krb5_enc_data enc;
82
krb5_data d;
83
char *attr;
84
85
ret = cb->get_string(context, rock, "teststring", &attr);
86
assert(!ret);
87
if (k != NULL) {
88
d = string2data((attr != NULL) ? attr : "no attr");
89
ret = krb5_c_encrypt_length(context, k->enctype, d.length, &enclen);
90
assert(!ret);
91
ret = alloc_data(&enc.ciphertext, enclen);
92
assert(!ret);
93
ret = krb5_c_encrypt(context, k, 1024, NULL, &d, &enc);
94
assert(!ret);
95
pa = make_pa(enc.ciphertext.data, enc.ciphertext.length);
96
free(enc.ciphertext.data);
97
} else {
98
pa = make_pa("no key", 6);
99
}
100
101
/* Exercise setting a cookie information from the edata method. */
102
d = string2data("method-data");
103
ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d);
104
assert(!ret);
105
106
cb->free_string(context, rock, attr);
107
(*respond)(arg, 0, pa);
108
}
109
110
static void
111
test_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
112
krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data,
113
krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
114
krb5_kdcpreauth_moddata moddata,
115
krb5_kdcpreauth_verify_respond_fn respond, void *arg)
116
{
117
krb5_error_code ret;
118
krb5_boolean second_round_trip = FALSE, optimistic = FALSE;
119
krb5_pa_data **list = NULL;
120
krb5_data cookie_data, d;
121
char *str, *ind, *toksave = NULL;
122
char *attr_err, *attr_2rt, *attr_fail2rt, *attr_failopt;
123
124
ret = cb->get_string(context, rock, "err", &attr_err);
125
assert(!ret);
126
ret = cb->get_string(context, rock, "2rt", &attr_2rt);
127
assert(!ret);
128
ret = cb->get_string(context, rock, "fail2rt", &attr_fail2rt);
129
assert(!ret);
130
ret = cb->get_string(context, rock, "failopt", &attr_failopt);
131
assert(!ret);
132
133
/* Check the incoming cookie value. */
134
if (!cb->get_cookie(context, rock, TEST_PA_TYPE, &cookie_data)) {
135
/* Make sure we are seeing optimistic preauth and not a lost cookie. */
136
d = make_data(data->contents, data->length);
137
assert(data_eq_string(d, "optimistic"));
138
optimistic = TRUE;
139
} else if (data_eq_string(cookie_data, "more")) {
140
second_round_trip = TRUE;
141
} else {
142
assert(data_eq_string(cookie_data, "method-data") ||
143
data_eq_string(cookie_data, "err"));
144
}
145
146
if (attr_err != NULL) {
147
d = make_data(data->contents, data->length);
148
if (data_eq_string(d, "tryagain")) {
149
/* Authenticate successfully. */
150
enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
151
} else {
152
d = string2data("err");
153
ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d);
154
assert(!ret);
155
ret = KRB5KDC_ERR_ETYPE_NOSUPP;
156
list = make_pa_list(attr_err, strlen(attr_err));
157
}
158
} else if (attr_2rt != NULL && !second_round_trip) {
159
d = string2data("more");
160
ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d);
161
assert(!ret);
162
ret = KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED;
163
list = make_pa_list(attr_2rt, strlen(attr_2rt));
164
} else if ((attr_fail2rt != NULL && second_round_trip) ||
165
(attr_failopt != NULL && optimistic)) {
166
ret = KRB5KDC_ERR_PREAUTH_FAILED;
167
} else {
168
/* Parse and assert the indicators. */
169
str = k5memdup0(data->contents, data->length, &ret);
170
if (ret)
171
abort();
172
ind = strtok_r(str, " ", &toksave);
173
while (ind != NULL) {
174
cb->add_auth_indicator(context, rock, ind);
175
ind = strtok_r(NULL, " ", &toksave);
176
}
177
free(str);
178
enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
179
}
180
181
cb->free_string(context, rock, attr_err);
182
cb->free_string(context, rock, attr_2rt);
183
cb->free_string(context, rock, attr_fail2rt);
184
cb->free_string(context, rock, attr_failopt);
185
(*respond)(arg, ret, NULL, list, NULL);
186
}
187
188
static krb5_error_code
189
test_return(krb5_context context, krb5_pa_data *padata, krb5_data *req_pkt,
190
krb5_kdc_req *request, krb5_kdc_rep *reply,
191
krb5_keyblock *encrypting_key, krb5_pa_data **send_pa_out,
192
krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
193
krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq)
194
{
195
const krb5_keyblock *k = cb->client_keyblock(context, rock);
196
197
assert(k == encrypting_key || k == NULL);
198
return 0;
199
}
200
201
krb5_error_code
202
kdcpreauth_test_initvt(krb5_context context, int maj_ver,
203
int min_ver, krb5_plugin_vtable vtable);
204
205
krb5_error_code
206
kdcpreauth_test_initvt(krb5_context context, int maj_ver,
207
int min_ver, krb5_plugin_vtable vtable)
208
{
209
krb5_kdcpreauth_vtable vt;
210
211
if (maj_ver != 1)
212
return KRB5_PLUGIN_VER_NOTSUPP;
213
vt = (krb5_kdcpreauth_vtable)vtable;
214
vt->name = "test";
215
vt->pa_type_list = pa_types;
216
vt->edata = test_edata;
217
vt->verify = test_verify;
218
vt->return_padata = test_return;
219
return 0;
220
}
221
222