Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/plugins/certauth/test/main.c
34890 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* plugins/certauth/main.c - certauth plugin test modules. */
3
/*
4
* Copyright (C) 2017 by Red Hat, Inc.
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
#include <k5-int.h>
34
#include <kdb.h>
35
#include "krb5/certauth_plugin.h"
36
37
struct krb5_certauth_moddata_st {
38
int initialized;
39
};
40
41
/* Test module 1 passes with an indicator. */
42
static krb5_error_code
43
test1_authorize(krb5_context context, krb5_certauth_moddata moddata,
44
const uint8_t *cert, size_t cert_len,
45
krb5_const_principal princ, const void *opts,
46
const struct _krb5_db_entry_new *db_entry,
47
char ***authinds_out)
48
{
49
char **ais = NULL;
50
51
ais = calloc(2, sizeof(*ais));
52
assert(ais != NULL);
53
ais[0] = strdup("test1");
54
assert(ais[0] != NULL);
55
*authinds_out = ais;
56
return KRB5_PLUGIN_NO_HANDLE;
57
}
58
59
static void
60
test_free_ind(krb5_context context, krb5_certauth_moddata moddata,
61
char **authinds)
62
{
63
size_t i;
64
65
if (authinds == NULL)
66
return;
67
for (i = 0; authinds[i] != NULL; i++)
68
free(authinds[i]);
69
free(authinds);
70
}
71
72
/* A basic moddata test. */
73
static krb5_error_code
74
test2_init(krb5_context context, krb5_certauth_moddata *moddata_out)
75
{
76
krb5_certauth_moddata mod;
77
78
mod = calloc(1, sizeof(*mod));
79
assert(mod != NULL);
80
mod->initialized = 1;
81
*moddata_out = mod;
82
return 0;
83
}
84
85
static void
86
test2_fini(krb5_context context, krb5_certauth_moddata moddata)
87
{
88
free(moddata);
89
}
90
91
/* Return true if cert appears to contain the CN name, based on a search of the
92
* DER encoding. */
93
static krb5_boolean
94
has_cn(krb5_context context, const uint8_t *cert, size_t cert_len,
95
const char *name)
96
{
97
krb5_boolean match = FALSE;
98
uint8_t name_len, cntag[5] = "\x06\x03\x55\x04\x03";
99
const uint8_t *c;
100
struct k5buf buf;
101
size_t c_left;
102
103
/* Construct a DER search string of the CN AttributeType encoding followed
104
* by a UTF8String encoding containing name as the AttributeValue. */
105
k5_buf_init_dynamic(&buf);
106
k5_buf_add_len(&buf, cntag, sizeof(cntag));
107
k5_buf_add(&buf, "\x0C");
108
assert(strlen(name) < 128);
109
name_len = strlen(name);
110
k5_buf_add_len(&buf, &name_len, 1);
111
k5_buf_add_len(&buf, name, name_len);
112
assert(k5_buf_status(&buf) == 0);
113
114
/* Check for the CN needle in the certificate haystack. */
115
c_left = cert_len;
116
c = memchr(cert, *cntag, c_left);
117
while (c != NULL) {
118
c_left = cert_len - (c - cert);
119
if (buf.len > c_left)
120
break;
121
if (memcmp(c, buf.data, buf.len) == 0) {
122
match = TRUE;
123
break;
124
}
125
assert(c_left >= 1);
126
c = memchr(c + 1, *cntag, c_left - 1);
127
}
128
129
k5_buf_free(&buf);
130
return match;
131
}
132
133
/*
134
* Test module 2 passes if the principal name is "nocert". Otherwise it
135
* returns OK if the CN of the cert matches the principal name, with indicators
136
* of the module name and princ, and errors if the certificate does not match.
137
*/
138
static krb5_error_code
139
test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
140
const uint8_t *cert, size_t cert_len,
141
krb5_const_principal princ, const void *opts,
142
const struct _krb5_db_entry_new *db_entry,
143
char ***authinds_out)
144
{
145
krb5_error_code ret;
146
char *name = NULL, **ais = NULL;
147
148
*authinds_out = NULL;
149
150
assert(moddata != NULL && moddata->initialized);
151
152
ret = krb5_unparse_name_flags(context, princ,
153
KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
154
if (ret)
155
goto cleanup;
156
if (strcmp(name, "nocert") == 0) {
157
ret = KRB5_PLUGIN_NO_HANDLE;
158
goto cleanup;
159
}
160
161
if (!has_cn(context, cert, cert_len, name)) {
162
ret = KRB5KDC_ERR_CERTIFICATE_MISMATCH;
163
goto cleanup;
164
}
165
166
/* Create an indicator list with the module name and CN. */
167
ais = calloc(3, sizeof(*ais));
168
assert(ais != NULL);
169
ais[0] = strdup("test2");
170
ais[1] = strdup(name);
171
assert(ais[0] != NULL && ais[1] != NULL);
172
*authinds_out = ais;
173
174
ais = NULL;
175
176
cleanup:
177
krb5_free_unparsed_name(context, name);
178
return ret;
179
}
180
181
/*
182
* Test module 3 reads the "hwauth" string attribute on db_entry, and adds an
183
* authentication indicator of "hwauth:<value>" if the attribute is set. It
184
* returns KRB5_CERTAUTH_HWAUTH if the value is "ok", and
185
* KRB5_CERTAUTH_HWAUTH_PASS if the value is "pass". Otherwise it passes.
186
*/
187
static krb5_error_code
188
test3_authorize(krb5_context context, krb5_certauth_moddata moddata,
189
const uint8_t *cert, size_t cert_len,
190
krb5_const_principal princ, const void *opts,
191
const struct _krb5_db_entry_new *db_entry,
192
char ***authinds_out)
193
{
194
krb5_error_code ret;
195
char *strval = NULL, **ais = NULL;
196
197
ret = krb5_dbe_get_string(context, (krb5_db_entry *)db_entry, "hwauth",
198
&strval);
199
if (ret)
200
return ret;
201
if (strval != NULL && strcmp(strval, "ok") == 0)
202
ret = KRB5_CERTAUTH_HWAUTH;
203
else if (strval != NULL && strcmp(strval, "pass") == 0)
204
ret = KRB5_CERTAUTH_HWAUTH_PASS;
205
else
206
ret = KRB5_PLUGIN_NO_HANDLE;
207
208
if (strval != NULL) {
209
ais = calloc(2, sizeof(*ais));
210
assert(ais != NULL);
211
if (asprintf(&ais[0], "hwauth:%s", strval) < 0)
212
abort();
213
assert(ais[0] != NULL);
214
}
215
216
*authinds_out = ais;
217
ais = NULL;
218
219
krb5_dbe_free_string(context, strval);
220
return ret;
221
}
222
223
krb5_error_code
224
certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,
225
krb5_plugin_vtable vtable);
226
krb5_error_code
227
certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,
228
krb5_plugin_vtable vtable)
229
{
230
krb5_certauth_vtable vt;
231
232
if (maj_ver != 1)
233
return KRB5_PLUGIN_VER_NOTSUPP;
234
vt = (krb5_certauth_vtable)vtable;
235
vt->name = "test1";
236
vt->authorize = test1_authorize;
237
vt->free_ind = test_free_ind;
238
return 0;
239
}
240
241
krb5_error_code
242
certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,
243
krb5_plugin_vtable vtable);
244
krb5_error_code
245
certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,
246
krb5_plugin_vtable vtable)
247
{
248
krb5_certauth_vtable vt;
249
250
if (maj_ver != 1)
251
return KRB5_PLUGIN_VER_NOTSUPP;
252
vt = (krb5_certauth_vtable)vtable;
253
vt->name = "test2";
254
vt->authorize = test2_authorize;
255
vt->init = test2_init;
256
vt->fini = test2_fini;
257
vt->free_ind = test_free_ind;
258
return 0;
259
}
260
261
krb5_error_code
262
certauth_test3_initvt(krb5_context context, int maj_ver, int min_ver,
263
krb5_plugin_vtable vtable);
264
265
krb5_error_code
266
certauth_test3_initvt(krb5_context context, int maj_ver, int min_ver,
267
krb5_plugin_vtable vtable)
268
{
269
krb5_certauth_vtable vt;
270
271
if (maj_ver != 1)
272
return KRB5_PLUGIN_VER_NOTSUPP;
273
vt = (krb5_certauth_vtable)vtable;
274
vt->name = "test3";
275
vt->authorize = test3_authorize;
276
vt->free_ind = test_free_ind;
277
return 0;
278
}
279
280