Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/plugins/kadm5_auth/test/main.c
34907 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* plugins/kadm5_auth/test/main.c - test modules for kadm5_auth interface */
3
/*
4
* Copyright (C) 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 file implements two testing kadm5_auth modules, the welcomer and the
35
* bouncer. The welcomer implements permissive behavior, while the bouncer
36
* implements restrictive behavior.
37
*
38
* Module data objects and restrictions are adequately tested by the acl
39
* module, so we do not test them here. Focus instead on the ability to
40
* examine principal and policy objects and to perform DB operations.
41
*/
42
43
#include "k5-int.h"
44
#include <kadm5/admin.h>
45
#include <krb5/kadm5_auth_plugin.h>
46
47
krb5_error_code
48
kadm5_auth_welcomer_initvt(krb5_context context, int maj_ver, int min_ver,
49
krb5_plugin_vtable vtable);
50
krb5_error_code
51
kadm5_auth_bouncer_initvt(krb5_context context, int maj_ver, int min_ver,
52
krb5_plugin_vtable vtable);
53
54
/* The welcomer authorizes all getprinc operations, since kadmin uses them as a
55
* precursor to modprinc. */
56
static krb5_error_code
57
welcomer_getprinc(krb5_context context, kadm5_auth_moddata data,
58
krb5_const_principal client, krb5_const_principal target)
59
{
60
return 0;
61
}
62
63
/* The welcomer authorizes addprinc operations which set a policy "VIP". */
64
static krb5_error_code
65
welcomer_addprinc(krb5_context context, kadm5_auth_moddata data,
66
krb5_const_principal client, krb5_const_principal target,
67
const struct _kadm5_principal_ent_t *ent, long mask,
68
struct kadm5_auth_restrictions **rs_out)
69
{
70
if ((mask & KADM5_POLICY) && strcmp(ent->policy, "VIP") == 0)
71
return 0;
72
return KRB5_PLUGIN_NO_HANDLE;
73
}
74
75
/* The bouncer denies addprinc operations which include a maximum lifetime. */
76
static krb5_error_code
77
bouncer_addprinc(krb5_context context, kadm5_auth_moddata data,
78
krb5_const_principal client, krb5_const_principal target,
79
const struct _kadm5_principal_ent_t *ent, long mask,
80
struct kadm5_auth_restrictions **rs_out)
81
{
82
return (mask & KADM5_MAX_LIFE) ? EPERM : KRB5_PLUGIN_NO_HANDLE;
83
}
84
85
/* The welcomer authorizes modprinc operations which only set maxrenewlife. */
86
static krb5_error_code
87
welcomer_modprinc(krb5_context context, kadm5_auth_moddata data,
88
krb5_const_principal client, krb5_const_principal target,
89
const struct _kadm5_principal_ent_t *ent, long mask,
90
struct kadm5_auth_restrictions **rs_out)
91
{
92
return (mask == KADM5_MAX_RLIFE) ? 0 : KRB5_PLUGIN_NO_HANDLE;
93
}
94
95
/* The bouncer denies modprinc operations if the target principal has an even
96
* number of components. */
97
static krb5_error_code
98
bouncer_modprinc(krb5_context context, kadm5_auth_moddata data,
99
krb5_const_principal client, krb5_const_principal target,
100
const struct _kadm5_principal_ent_t *ent, long mask,
101
struct kadm5_auth_restrictions **rs_out)
102
{
103
return (target->length % 2 == 0) ? EPERM : KRB5_PLUGIN_NO_HANDLE;
104
}
105
106
/* The welcomer authorizes setstr operations for the attribute "note". */
107
static krb5_error_code
108
welcomer_setstr(krb5_context context, kadm5_auth_moddata data,
109
krb5_const_principal client, krb5_const_principal target,
110
const char *key, const char *value)
111
{
112
return (strcmp(key, "note") == 0) ? 0 : KRB5_PLUGIN_NO_HANDLE;
113
}
114
115
/* The bouncer denies setstr operations if the value is more than 10 bytes. */
116
static krb5_error_code
117
bouncer_setstr(krb5_context context, kadm5_auth_moddata data,
118
krb5_const_principal client, krb5_const_principal target,
119
const char *key, const char *value)
120
{
121
return (strlen(value) > 10) ? EPERM : KRB5_PLUGIN_NO_HANDLE;
122
}
123
124
/* The welcomer authorizes delprinc operations if the target principal starts
125
* with "d". */
126
static krb5_error_code
127
welcomer_delprinc(krb5_context context, kadm5_auth_moddata data,
128
krb5_const_principal client, krb5_const_principal target)
129
{
130
if (target->length > 0 && target->data[0].length > 0 &&
131
*target->data[0].data == 'd')
132
return 0;
133
return KRB5_PLUGIN_NO_HANDLE;
134
}
135
136
/* The bouncer denies delprinc operations if the target principal has the
137
* "nodelete" string attribute. */
138
static krb5_error_code
139
bouncer_delprinc(krb5_context context, kadm5_auth_moddata data,
140
krb5_const_principal client, krb5_const_principal target)
141
{
142
krb5_error_code ret;
143
krb5_db_entry *ent;
144
char *val = NULL;
145
146
if (krb5_db_get_principal(context, target, 0, &ent) != 0)
147
return EPERM;
148
ret = krb5_dbe_get_string(context, ent, "nodelete", &val);
149
krb5_db_free_principal(context, ent);
150
ret = (ret != 0 || val != NULL) ? EPERM : KRB5_PLUGIN_NO_HANDLE;
151
krb5_dbe_free_string(context, val);
152
return ret;
153
}
154
155
/* The welcomer authorizes rename operations if the first components of the
156
* principals have the same length. */
157
static krb5_error_code
158
welcomer_renprinc(krb5_context context, kadm5_auth_moddata data,
159
krb5_const_principal client, krb5_const_principal src,
160
krb5_const_principal dest)
161
{
162
if (src->length > 0 && dest->length > 0 &&
163
src->data[0].length == dest->data[0].length)
164
return 0;
165
return KRB5_PLUGIN_NO_HANDLE;
166
}
167
168
/* The bouncer denies rename operations if the source principal starts with
169
* "a". */
170
static krb5_error_code
171
bouncer_renprinc(krb5_context context, kadm5_auth_moddata data,
172
krb5_const_principal client, krb5_const_principal src,
173
krb5_const_principal dest)
174
{
175
if (src->length > 0 && src->data[0].length > 0 &&
176
*src->data[0].data == 'a')
177
return EPERM;
178
return KRB5_PLUGIN_NO_HANDLE;
179
}
180
181
/* The welcomer authorizes addpol operations which set a minlength of 3. */
182
static krb5_error_code
183
welcomer_addpol(krb5_context context, kadm5_auth_moddata data,
184
krb5_const_principal client, const char *policy,
185
const struct _kadm5_policy_ent_t *ent, long mask)
186
{
187
if ((mask & KADM5_PW_MIN_LENGTH) && ent->pw_min_length == 3)
188
return 0;
189
return KRB5_PLUGIN_NO_HANDLE;
190
}
191
192
/* The bouncer denies addpol operations if the name is 3 bytes or less. */
193
static krb5_error_code
194
bouncer_addpol(krb5_context context, kadm5_auth_moddata data,
195
krb5_const_principal client, const char *policy,
196
const struct _kadm5_policy_ent_t *ent, long mask)
197
{
198
return (strlen(policy) <= 3) ? EPERM : KRB5_PLUGIN_NO_HANDLE;
199
}
200
201
/* The welcomer authorizes modpol operations which only change min_life. */
202
static krb5_error_code
203
welcomer_modpol(krb5_context context, kadm5_auth_moddata data,
204
krb5_const_principal client, const char *policy,
205
const struct _kadm5_policy_ent_t *ent, long mask)
206
{
207
return (mask == KADM5_PW_MIN_LIFE) ? 0 : KRB5_PLUGIN_NO_HANDLE;
208
}
209
210
/* The bouncer denies modpol operations which set pw_min_life above 10. */
211
static krb5_error_code
212
bouncer_modpol(krb5_context context, kadm5_auth_moddata data,
213
krb5_const_principal client, const char *policy,
214
const struct _kadm5_policy_ent_t *ent, long mask)
215
{
216
if ((mask & KADM5_PW_MIN_LIFE) && ent->pw_min_life > 10)
217
return EPERM;
218
return KRB5_PLUGIN_NO_HANDLE;
219
}
220
221
/* The welcomer authorizes getpol operations if the policy and client principal
222
* policy have the same length. */
223
static krb5_error_code
224
welcomer_getpol(krb5_context context, kadm5_auth_moddata data,
225
krb5_const_principal client, const char *policy,
226
const char *client_policy)
227
{
228
if (client_policy != NULL && strlen(policy) == strlen(client_policy))
229
return 0;
230
return KRB5_PLUGIN_NO_HANDLE;
231
}
232
233
/* The bouncer denies getpol operations if the policy name begins with 'x'. */
234
static krb5_error_code
235
bouncer_getpol(krb5_context context, kadm5_auth_moddata data,
236
krb5_const_principal client, const char *policy,
237
const char *client_policy)
238
{
239
return (*policy == 'x') ? EPERM : KRB5_PLUGIN_NO_HANDLE;
240
}
241
242
/* The welcomer counts end calls by incrementing the "ends" string attribute on
243
* the "opcount" principal, if it exists. */
244
static void
245
welcomer_end(krb5_context context, kadm5_auth_moddata data)
246
{
247
krb5_principal princ = NULL;
248
krb5_db_entry *ent = NULL;
249
char *val = NULL, buf[10];
250
251
if (krb5_parse_name(context, "opcount", &princ) != 0)
252
goto cleanup;
253
if (krb5_db_get_principal(context, princ, 0, &ent) != 0)
254
goto cleanup;
255
if (krb5_dbe_get_string(context, ent, "ends", &val) != 0 || val == NULL)
256
goto cleanup;
257
snprintf(buf, sizeof(buf), "%d", atoi(val) + 1);
258
if (krb5_dbe_set_string(context, ent, "ends", buf) != 0)
259
goto cleanup;
260
ent->mask = KADM5_TL_DATA;
261
krb5_db_put_principal(context, ent);
262
263
cleanup:
264
krb5_dbe_free_string(context, val);
265
krb5_db_free_principal(context, ent);
266
krb5_free_principal(context, princ);
267
}
268
269
krb5_error_code
270
kadm5_auth_welcomer_initvt(krb5_context context, int maj_ver, int min_ver,
271
krb5_plugin_vtable vtable)
272
{
273
kadm5_auth_vtable vt = (kadm5_auth_vtable)vtable;
274
275
vt->name = "welcomer";
276
vt->addprinc = welcomer_addprinc;
277
vt->modprinc = welcomer_modprinc;
278
vt->setstr = welcomer_setstr;
279
vt->delprinc = welcomer_delprinc;
280
vt->renprinc = welcomer_renprinc;
281
vt->getprinc = welcomer_getprinc;
282
vt->addpol = welcomer_addpol;
283
vt->modpol = welcomer_modpol;
284
vt->getpol = welcomer_getpol;
285
vt->end = welcomer_end;
286
return 0;
287
}
288
289
krb5_error_code
290
kadm5_auth_bouncer_initvt(krb5_context context, int maj_ver, int min_ver,
291
krb5_plugin_vtable vtable)
292
{
293
kadm5_auth_vtable vt = (kadm5_auth_vtable)vtable;
294
295
vt->name = "bouncer";
296
vt->addprinc = bouncer_addprinc;
297
vt->modprinc = bouncer_modprinc;
298
vt->setstr = bouncer_setstr;
299
vt->delprinc = bouncer_delprinc;
300
vt->renprinc = bouncer_renprinc;
301
vt->addpol = bouncer_addpol;
302
vt->modpol = bouncer_modpol;
303
vt->getpol = bouncer_getpol;
304
return 0;
305
}
306
307