1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* kadmin/server/auth_acl.c - ACL kadm5_auth module */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright 1995-2004, 2007, 2008, 2017 by the Massachusetts Institute of
5*7f2fe78bSCy Schubert * Technology. All Rights Reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert * permission. Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
24*7f2fe78bSCy Schubert * or implied warranty.
25*7f2fe78bSCy Schubert */
26*7f2fe78bSCy Schubert
27*7f2fe78bSCy Schubert #include "k5-int.h"
28*7f2fe78bSCy Schubert #include <syslog.h>
29*7f2fe78bSCy Schubert #include <kadm5/admin.h>
30*7f2fe78bSCy Schubert #include <krb5/kadm5_auth_plugin.h>
31*7f2fe78bSCy Schubert #include "adm_proto.h"
32*7f2fe78bSCy Schubert #include <ctype.h>
33*7f2fe78bSCy Schubert #include "auth.h"
34*7f2fe78bSCy Schubert
35*7f2fe78bSCy Schubert /*
36*7f2fe78bSCy Schubert * Access control bits.
37*7f2fe78bSCy Schubert */
38*7f2fe78bSCy Schubert #define ACL_ADD 1
39*7f2fe78bSCy Schubert #define ACL_DELETE 2
40*7f2fe78bSCy Schubert #define ACL_MODIFY 4
41*7f2fe78bSCy Schubert #define ACL_CHANGEPW 8
42*7f2fe78bSCy Schubert /* #define ACL_CHANGE_OWN_PW 16 */
43*7f2fe78bSCy Schubert #define ACL_INQUIRE 32
44*7f2fe78bSCy Schubert #define ACL_EXTRACT 64
45*7f2fe78bSCy Schubert #define ACL_LIST 128
46*7f2fe78bSCy Schubert #define ACL_SETKEY 256
47*7f2fe78bSCy Schubert #define ACL_IPROP 512
48*7f2fe78bSCy Schubert
49*7f2fe78bSCy Schubert #define ACL_ALL_MASK (ACL_ADD | \
50*7f2fe78bSCy Schubert ACL_DELETE | \
51*7f2fe78bSCy Schubert ACL_MODIFY | \
52*7f2fe78bSCy Schubert ACL_CHANGEPW | \
53*7f2fe78bSCy Schubert ACL_INQUIRE | \
54*7f2fe78bSCy Schubert ACL_LIST | \
55*7f2fe78bSCy Schubert ACL_IPROP | \
56*7f2fe78bSCy Schubert ACL_SETKEY)
57*7f2fe78bSCy Schubert
58*7f2fe78bSCy Schubert struct acl_op_table {
59*7f2fe78bSCy Schubert char op;
60*7f2fe78bSCy Schubert uint32_t mask;
61*7f2fe78bSCy Schubert };
62*7f2fe78bSCy Schubert
63*7f2fe78bSCy Schubert struct acl_entry {
64*7f2fe78bSCy Schubert struct acl_entry *next;
65*7f2fe78bSCy Schubert krb5_principal client;
66*7f2fe78bSCy Schubert uint32_t op_allowed;
67*7f2fe78bSCy Schubert krb5_principal target;
68*7f2fe78bSCy Schubert struct kadm5_auth_restrictions *rs;
69*7f2fe78bSCy Schubert };
70*7f2fe78bSCy Schubert
71*7f2fe78bSCy Schubert static const struct acl_op_table acl_op_table[] = {
72*7f2fe78bSCy Schubert { 'a', ACL_ADD },
73*7f2fe78bSCy Schubert { 'd', ACL_DELETE },
74*7f2fe78bSCy Schubert { 'm', ACL_MODIFY },
75*7f2fe78bSCy Schubert { 'c', ACL_CHANGEPW },
76*7f2fe78bSCy Schubert { 'i', ACL_INQUIRE },
77*7f2fe78bSCy Schubert { 'l', ACL_LIST },
78*7f2fe78bSCy Schubert { 'p', ACL_IPROP },
79*7f2fe78bSCy Schubert { 's', ACL_SETKEY },
80*7f2fe78bSCy Schubert { 'x', ACL_ALL_MASK },
81*7f2fe78bSCy Schubert { '*', ACL_ALL_MASK },
82*7f2fe78bSCy Schubert { 'e', ACL_EXTRACT },
83*7f2fe78bSCy Schubert { '\0', 0 }
84*7f2fe78bSCy Schubert };
85*7f2fe78bSCy Schubert
86*7f2fe78bSCy Schubert struct wildstate {
87*7f2fe78bSCy Schubert int nwild;
88*7f2fe78bSCy Schubert const krb5_data *backref[9];
89*7f2fe78bSCy Schubert };
90*7f2fe78bSCy Schubert
91*7f2fe78bSCy Schubert struct acl_state {
92*7f2fe78bSCy Schubert struct acl_entry *list;
93*7f2fe78bSCy Schubert };
94*7f2fe78bSCy Schubert
95*7f2fe78bSCy Schubert /*
96*7f2fe78bSCy Schubert * Get a line from the ACL file. Lines ending with \ are continued on the next
97*7f2fe78bSCy Schubert * line. The caller should set *lineno to 1 and *incr to 0 before the first
98*7f2fe78bSCy Schubert * call. On successful return, *lineno will be the line number of the line
99*7f2fe78bSCy Schubert * read. Return a pointer to the line on success, or NULL on end of file or
100*7f2fe78bSCy Schubert * read failure.
101*7f2fe78bSCy Schubert */
102*7f2fe78bSCy Schubert static char *
get_line(FILE * fp,const char * fname,int * lineno,int * incr)103*7f2fe78bSCy Schubert get_line(FILE *fp, const char *fname, int *lineno, int *incr)
104*7f2fe78bSCy Schubert {
105*7f2fe78bSCy Schubert const int chunksize = 128;
106*7f2fe78bSCy Schubert struct k5buf buf;
107*7f2fe78bSCy Schubert size_t old_len;
108*7f2fe78bSCy Schubert char *p;
109*7f2fe78bSCy Schubert
110*7f2fe78bSCy Schubert /* Increment *lineno by the number of newlines from the last line. */
111*7f2fe78bSCy Schubert *lineno += *incr;
112*7f2fe78bSCy Schubert *incr = 0;
113*7f2fe78bSCy Schubert
114*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
115*7f2fe78bSCy Schubert for (;;) {
116*7f2fe78bSCy Schubert /* Read at least part of a line into the buffer. */
117*7f2fe78bSCy Schubert old_len = buf.len;
118*7f2fe78bSCy Schubert p = k5_buf_get_space(&buf, chunksize);
119*7f2fe78bSCy Schubert if (p == NULL)
120*7f2fe78bSCy Schubert return NULL;
121*7f2fe78bSCy Schubert
122*7f2fe78bSCy Schubert if (fgets(p, chunksize, fp) == NULL) {
123*7f2fe78bSCy Schubert /* We reached the end. Return a final unterminated line, if there
124*7f2fe78bSCy Schubert * is one and it's not a comment. */
125*7f2fe78bSCy Schubert k5_buf_truncate(&buf, old_len);
126*7f2fe78bSCy Schubert if (buf.len > 0 && *(char *)buf.data != '#')
127*7f2fe78bSCy Schubert return buf.data;
128*7f2fe78bSCy Schubert k5_buf_free(&buf);
129*7f2fe78bSCy Schubert return NULL;
130*7f2fe78bSCy Schubert }
131*7f2fe78bSCy Schubert
132*7f2fe78bSCy Schubert /* Set the buffer length based on the actual amount read. */
133*7f2fe78bSCy Schubert k5_buf_truncate(&buf, old_len + strlen(p));
134*7f2fe78bSCy Schubert
135*7f2fe78bSCy Schubert p = buf.data;
136*7f2fe78bSCy Schubert if (buf.len > 0 && p[buf.len - 1] == '\n') {
137*7f2fe78bSCy Schubert /* We have a complete raw line in the buffer. */
138*7f2fe78bSCy Schubert (*incr)++;
139*7f2fe78bSCy Schubert k5_buf_truncate(&buf, buf.len - 1);
140*7f2fe78bSCy Schubert if (buf.len > 0 && p[buf.len - 1] == '\\') {
141*7f2fe78bSCy Schubert /* This line has a continuation marker; keep reading. */
142*7f2fe78bSCy Schubert k5_buf_truncate(&buf, buf.len - 1);
143*7f2fe78bSCy Schubert } else if (buf.len == 0 || *p == '#') {
144*7f2fe78bSCy Schubert /* This line is empty or a comment. Start over. */
145*7f2fe78bSCy Schubert *lineno += *incr;
146*7f2fe78bSCy Schubert *incr = 0;
147*7f2fe78bSCy Schubert k5_buf_truncate(&buf, 0);
148*7f2fe78bSCy Schubert } else {
149*7f2fe78bSCy Schubert return k5_buf_cstring(&buf);
150*7f2fe78bSCy Schubert }
151*7f2fe78bSCy Schubert }
152*7f2fe78bSCy Schubert }
153*7f2fe78bSCy Schubert }
154*7f2fe78bSCy Schubert
155*7f2fe78bSCy Schubert /*
156*7f2fe78bSCy Schubert * Parse a restrictions field. Return NULL on failure.
157*7f2fe78bSCy Schubert *
158*7f2fe78bSCy Schubert * Allowed restrictions are:
159*7f2fe78bSCy Schubert * [+-]flagname (recognized by krb5_flagspec_to_mask)
160*7f2fe78bSCy Schubert * flag is forced to indicated value
161*7f2fe78bSCy Schubert * -clearpolicy policy is forced clear
162*7f2fe78bSCy Schubert * -policy pol policy is forced to be "pol"
163*7f2fe78bSCy Schubert * -{expire,pwexpire,maxlife,maxrenewlife} deltat
164*7f2fe78bSCy Schubert * associated value will be forced to
165*7f2fe78bSCy Schubert * MIN(deltat, requested value)
166*7f2fe78bSCy Schubert */
167*7f2fe78bSCy Schubert static struct kadm5_auth_restrictions *
parse_restrictions(const char * str,const char * fname)168*7f2fe78bSCy Schubert parse_restrictions(const char *str, const char *fname)
169*7f2fe78bSCy Schubert {
170*7f2fe78bSCy Schubert char *copy = NULL, *token, *arg, *save;
171*7f2fe78bSCy Schubert const char *delims = "\t\n\f\v\r ,";
172*7f2fe78bSCy Schubert krb5_deltat delta;
173*7f2fe78bSCy Schubert struct kadm5_auth_restrictions *rs;
174*7f2fe78bSCy Schubert
175*7f2fe78bSCy Schubert copy = strdup(str);
176*7f2fe78bSCy Schubert if (copy == NULL)
177*7f2fe78bSCy Schubert return NULL;
178*7f2fe78bSCy Schubert
179*7f2fe78bSCy Schubert rs = calloc(1, sizeof(*rs));
180*7f2fe78bSCy Schubert if (rs == NULL) {
181*7f2fe78bSCy Schubert free(copy);
182*7f2fe78bSCy Schubert return NULL;
183*7f2fe78bSCy Schubert }
184*7f2fe78bSCy Schubert
185*7f2fe78bSCy Schubert rs->forbid_attrs = ~(krb5_flags)0;
186*7f2fe78bSCy Schubert for (token = strtok_r(copy, delims, &save); token != NULL;
187*7f2fe78bSCy Schubert token = strtok_r(NULL, delims, &save)) {
188*7f2fe78bSCy Schubert
189*7f2fe78bSCy Schubert if (krb5_flagspec_to_mask(token, &rs->require_attrs,
190*7f2fe78bSCy Schubert &rs->forbid_attrs) == 0) {
191*7f2fe78bSCy Schubert rs->mask |= KADM5_ATTRIBUTES;
192*7f2fe78bSCy Schubert continue;
193*7f2fe78bSCy Schubert }
194*7f2fe78bSCy Schubert
195*7f2fe78bSCy Schubert if (strcmp(token, "-clearpolicy") == 0) {
196*7f2fe78bSCy Schubert rs->mask |= KADM5_POLICY_CLR;
197*7f2fe78bSCy Schubert continue;
198*7f2fe78bSCy Schubert }
199*7f2fe78bSCy Schubert
200*7f2fe78bSCy Schubert /* Everything else needs an argument. */
201*7f2fe78bSCy Schubert arg = strtok_r(NULL, delims, &save);
202*7f2fe78bSCy Schubert if (arg == NULL)
203*7f2fe78bSCy Schubert goto error;
204*7f2fe78bSCy Schubert
205*7f2fe78bSCy Schubert if (strcmp(token, "-policy") == 0) {
206*7f2fe78bSCy Schubert if (rs->policy != NULL)
207*7f2fe78bSCy Schubert goto error;
208*7f2fe78bSCy Schubert rs->policy = strdup(arg);
209*7f2fe78bSCy Schubert if (rs->policy == NULL)
210*7f2fe78bSCy Schubert goto error;
211*7f2fe78bSCy Schubert rs->mask |= KADM5_POLICY;
212*7f2fe78bSCy Schubert continue;
213*7f2fe78bSCy Schubert }
214*7f2fe78bSCy Schubert
215*7f2fe78bSCy Schubert /* All other arguments must be a deltat. */
216*7f2fe78bSCy Schubert if (krb5_string_to_deltat(arg, &delta) != 0)
217*7f2fe78bSCy Schubert goto error;
218*7f2fe78bSCy Schubert
219*7f2fe78bSCy Schubert if (strcmp(token, "-expire") == 0) {
220*7f2fe78bSCy Schubert rs->princ_lifetime = delta;
221*7f2fe78bSCy Schubert rs->mask |= KADM5_PRINC_EXPIRE_TIME;
222*7f2fe78bSCy Schubert } else if (strcmp(token, "-pwexpire") == 0) {
223*7f2fe78bSCy Schubert rs->pw_lifetime = delta;
224*7f2fe78bSCy Schubert rs->mask |= KADM5_PW_EXPIRATION;
225*7f2fe78bSCy Schubert } else if (strcmp(token, "-maxlife") == 0) {
226*7f2fe78bSCy Schubert rs->max_life = delta;
227*7f2fe78bSCy Schubert rs->mask |= KADM5_MAX_LIFE;
228*7f2fe78bSCy Schubert } else if (strcmp(token, "-maxrenewlife") == 0) {
229*7f2fe78bSCy Schubert rs->max_renewable_life = delta;
230*7f2fe78bSCy Schubert rs->mask |= KADM5_MAX_RLIFE;
231*7f2fe78bSCy Schubert } else {
232*7f2fe78bSCy Schubert goto error;
233*7f2fe78bSCy Schubert }
234*7f2fe78bSCy Schubert }
235*7f2fe78bSCy Schubert
236*7f2fe78bSCy Schubert free(copy);
237*7f2fe78bSCy Schubert return rs;
238*7f2fe78bSCy Schubert
239*7f2fe78bSCy Schubert error:
240*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR, _("%s: invalid restrictions: %s"), fname, str);
241*7f2fe78bSCy Schubert free(copy);
242*7f2fe78bSCy Schubert free(rs->policy);
243*7f2fe78bSCy Schubert free(rs);
244*7f2fe78bSCy Schubert return NULL;
245*7f2fe78bSCy Schubert }
246*7f2fe78bSCy Schubert
247*7f2fe78bSCy Schubert static void
free_acl_entry(struct acl_entry * entry)248*7f2fe78bSCy Schubert free_acl_entry(struct acl_entry *entry)
249*7f2fe78bSCy Schubert {
250*7f2fe78bSCy Schubert krb5_free_principal(NULL, entry->client);
251*7f2fe78bSCy Schubert krb5_free_principal(NULL, entry->target);
252*7f2fe78bSCy Schubert if (entry->rs != NULL) {
253*7f2fe78bSCy Schubert free(entry->rs->policy);
254*7f2fe78bSCy Schubert free(entry->rs);
255*7f2fe78bSCy Schubert }
256*7f2fe78bSCy Schubert free(entry);
257*7f2fe78bSCy Schubert }
258*7f2fe78bSCy Schubert
259*7f2fe78bSCy Schubert /* Parse the four fields of an ACL entry and return a structure representing
260*7f2fe78bSCy Schubert * it. Log a message and return NULL on error. */
261*7f2fe78bSCy Schubert static struct acl_entry *
parse_entry(krb5_context context,const char * client,const char * ops,const char * target,const char * rs,const char * line,const char * fname)262*7f2fe78bSCy Schubert parse_entry(krb5_context context, const char *client, const char *ops,
263*7f2fe78bSCy Schubert const char *target, const char *rs, const char *line,
264*7f2fe78bSCy Schubert const char *fname)
265*7f2fe78bSCy Schubert {
266*7f2fe78bSCy Schubert struct acl_entry *entry;
267*7f2fe78bSCy Schubert const char *op;
268*7f2fe78bSCy Schubert char rop;
269*7f2fe78bSCy Schubert int t;
270*7f2fe78bSCy Schubert
271*7f2fe78bSCy Schubert entry = calloc(1, sizeof(*entry));
272*7f2fe78bSCy Schubert if (entry == NULL)
273*7f2fe78bSCy Schubert return NULL;
274*7f2fe78bSCy Schubert
275*7f2fe78bSCy Schubert for (op = ops; *op; op++) {
276*7f2fe78bSCy Schubert rop = isupper((unsigned char)*op) ? tolower((unsigned char)*op) : *op;
277*7f2fe78bSCy Schubert for (t = 0; acl_op_table[t].op; t++) {
278*7f2fe78bSCy Schubert if (rop == acl_op_table[t].op) {
279*7f2fe78bSCy Schubert if (rop == *op)
280*7f2fe78bSCy Schubert entry->op_allowed |= acl_op_table[t].mask;
281*7f2fe78bSCy Schubert else
282*7f2fe78bSCy Schubert entry->op_allowed &= ~acl_op_table[t].mask;
283*7f2fe78bSCy Schubert break;
284*7f2fe78bSCy Schubert }
285*7f2fe78bSCy Schubert }
286*7f2fe78bSCy Schubert if (!acl_op_table[t].op) {
287*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR,
288*7f2fe78bSCy Schubert _("Unrecognized ACL operation '%c' in %s"),
289*7f2fe78bSCy Schubert *op, line);
290*7f2fe78bSCy Schubert goto error;
291*7f2fe78bSCy Schubert }
292*7f2fe78bSCy Schubert }
293*7f2fe78bSCy Schubert
294*7f2fe78bSCy Schubert if (strcmp(client, "*") != 0) {
295*7f2fe78bSCy Schubert if (krb5_parse_name(context, client, &entry->client) != 0) {
296*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR, _("Cannot parse client principal '%s'"),
297*7f2fe78bSCy Schubert client);
298*7f2fe78bSCy Schubert goto error;
299*7f2fe78bSCy Schubert }
300*7f2fe78bSCy Schubert }
301*7f2fe78bSCy Schubert
302*7f2fe78bSCy Schubert if (target != NULL && strcmp(target, "*") != 0) {
303*7f2fe78bSCy Schubert if (krb5_parse_name(context, target, &entry->target) != 0) {
304*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR, _("Cannot parse target principal '%s'"),
305*7f2fe78bSCy Schubert target);
306*7f2fe78bSCy Schubert goto error;
307*7f2fe78bSCy Schubert }
308*7f2fe78bSCy Schubert }
309*7f2fe78bSCy Schubert
310*7f2fe78bSCy Schubert if (rs != NULL) {
311*7f2fe78bSCy Schubert entry->rs = parse_restrictions(rs, fname);
312*7f2fe78bSCy Schubert if (entry->rs == NULL)
313*7f2fe78bSCy Schubert goto error;
314*7f2fe78bSCy Schubert }
315*7f2fe78bSCy Schubert
316*7f2fe78bSCy Schubert return entry;
317*7f2fe78bSCy Schubert
318*7f2fe78bSCy Schubert error:
319*7f2fe78bSCy Schubert free_acl_entry(entry);
320*7f2fe78bSCy Schubert return NULL;
321*7f2fe78bSCy Schubert }
322*7f2fe78bSCy Schubert
323*7f2fe78bSCy Schubert /* Parse the contents of an ACL line. */
324*7f2fe78bSCy Schubert static struct acl_entry *
parse_line(krb5_context context,const char * line,const char * fname)325*7f2fe78bSCy Schubert parse_line(krb5_context context, const char *line, const char *fname)
326*7f2fe78bSCy Schubert {
327*7f2fe78bSCy Schubert struct acl_entry *entry = NULL;
328*7f2fe78bSCy Schubert char *copy;
329*7f2fe78bSCy Schubert char *client, *client_end, *ops, *ops_end, *target, *target_end, *rs, *end;
330*7f2fe78bSCy Schubert const char *ws = "\t\n\f\v\r ,";
331*7f2fe78bSCy Schubert
332*7f2fe78bSCy Schubert /*
333*7f2fe78bSCy Schubert * Format:
334*7f2fe78bSCy Schubert * entry ::= [<whitespace>] <principal> <whitespace> <opstring>
335*7f2fe78bSCy Schubert * [<whitespace> <target> [<whitespace> <restrictions>
336*7f2fe78bSCy Schubert * [<whitespace>]]]
337*7f2fe78bSCy Schubert */
338*7f2fe78bSCy Schubert
339*7f2fe78bSCy Schubert /* Make a copy and remove any trailing whitespace. */
340*7f2fe78bSCy Schubert copy = strdup(line);
341*7f2fe78bSCy Schubert if (copy == NULL)
342*7f2fe78bSCy Schubert return NULL;
343*7f2fe78bSCy Schubert end = copy + strlen(copy);
344*7f2fe78bSCy Schubert while (end > copy && isspace(end[-1]))
345*7f2fe78bSCy Schubert *--end = '\0';
346*7f2fe78bSCy Schubert
347*7f2fe78bSCy Schubert /* Find the beginning and end of each field. The end of restrictions is
348*7f2fe78bSCy Schubert * the end of copy. */
349*7f2fe78bSCy Schubert client = copy + strspn(copy, ws);
350*7f2fe78bSCy Schubert client_end = client + strcspn(client, ws);
351*7f2fe78bSCy Schubert ops = client_end + strspn(client_end, ws);
352*7f2fe78bSCy Schubert ops_end = ops + strcspn(ops, ws);
353*7f2fe78bSCy Schubert target = ops_end + strspn(ops_end, ws);
354*7f2fe78bSCy Schubert target_end = target + strcspn(target, ws);
355*7f2fe78bSCy Schubert rs = target_end + strspn(target_end, ws);
356*7f2fe78bSCy Schubert
357*7f2fe78bSCy Schubert /* Terminate the first three fields. */
358*7f2fe78bSCy Schubert *client_end = *ops_end = *target_end = '\0';
359*7f2fe78bSCy Schubert
360*7f2fe78bSCy Schubert /* The last two fields are optional; represent them as NULL if not present.
361*7f2fe78bSCy Schubert * The first two fields are required. */
362*7f2fe78bSCy Schubert if (*target == '\0')
363*7f2fe78bSCy Schubert target = NULL;
364*7f2fe78bSCy Schubert if (*rs == '\0')
365*7f2fe78bSCy Schubert rs = NULL;
366*7f2fe78bSCy Schubert if (*client != '\0' && *ops != '\0')
367*7f2fe78bSCy Schubert entry = parse_entry(context, client, ops, target, rs, line, fname);
368*7f2fe78bSCy Schubert free(copy);
369*7f2fe78bSCy Schubert return entry;
370*7f2fe78bSCy Schubert }
371*7f2fe78bSCy Schubert
372*7f2fe78bSCy Schubert /* Free all ACL entries. */
373*7f2fe78bSCy Schubert static void
free_acl_entries(struct acl_state * state)374*7f2fe78bSCy Schubert free_acl_entries(struct acl_state *state)
375*7f2fe78bSCy Schubert {
376*7f2fe78bSCy Schubert struct acl_entry *entry, *next;
377*7f2fe78bSCy Schubert
378*7f2fe78bSCy Schubert for (entry = state->list; entry != NULL; entry = next) {
379*7f2fe78bSCy Schubert next = entry->next;
380*7f2fe78bSCy Schubert free_acl_entry(entry);
381*7f2fe78bSCy Schubert }
382*7f2fe78bSCy Schubert state->list = NULL;
383*7f2fe78bSCy Schubert }
384*7f2fe78bSCy Schubert
385*7f2fe78bSCy Schubert /* Open and parse the ACL file. */
386*7f2fe78bSCy Schubert static krb5_error_code
load_acl_file(krb5_context context,const char * fname,struct acl_state * state)387*7f2fe78bSCy Schubert load_acl_file(krb5_context context, const char *fname, struct acl_state *state)
388*7f2fe78bSCy Schubert {
389*7f2fe78bSCy Schubert krb5_error_code ret;
390*7f2fe78bSCy Schubert FILE *fp;
391*7f2fe78bSCy Schubert char *line;
392*7f2fe78bSCy Schubert struct acl_entry **entry_slot;
393*7f2fe78bSCy Schubert int lineno, incr;
394*7f2fe78bSCy Schubert
395*7f2fe78bSCy Schubert state->list = NULL;
396*7f2fe78bSCy Schubert
397*7f2fe78bSCy Schubert /* Open the ACL file for reading. */
398*7f2fe78bSCy Schubert fp = fopen(fname, "r");
399*7f2fe78bSCy Schubert if (fp == NULL) {
400*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR, _("%s while opening ACL file %s"),
401*7f2fe78bSCy Schubert error_message(errno), fname);
402*7f2fe78bSCy Schubert ret = errno;
403*7f2fe78bSCy Schubert k5_setmsg(context, errno, _("Cannot open %s: %s"), fname,
404*7f2fe78bSCy Schubert error_message(ret));
405*7f2fe78bSCy Schubert return ret;
406*7f2fe78bSCy Schubert }
407*7f2fe78bSCy Schubert
408*7f2fe78bSCy Schubert set_cloexec_file(fp);
409*7f2fe78bSCy Schubert lineno = 1;
410*7f2fe78bSCy Schubert incr = 0;
411*7f2fe78bSCy Schubert entry_slot = &state->list;
412*7f2fe78bSCy Schubert
413*7f2fe78bSCy Schubert /* Get a non-comment line. */
414*7f2fe78bSCy Schubert while ((line = get_line(fp, fname, &lineno, &incr)) != NULL) {
415*7f2fe78bSCy Schubert /* Parse it. Fail out on syntax error. */
416*7f2fe78bSCy Schubert *entry_slot = parse_line(context, line, fname);
417*7f2fe78bSCy Schubert if (*entry_slot == NULL) {
418*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR,
419*7f2fe78bSCy Schubert _("%s: syntax error at line %d <%.10s...>"),
420*7f2fe78bSCy Schubert fname, lineno, line);
421*7f2fe78bSCy Schubert k5_setmsg(context, EINVAL,
422*7f2fe78bSCy Schubert _("%s: syntax error at line %d <%.10s...>"),
423*7f2fe78bSCy Schubert fname, lineno, line);
424*7f2fe78bSCy Schubert free_acl_entries(state);
425*7f2fe78bSCy Schubert free(line);
426*7f2fe78bSCy Schubert fclose(fp);
427*7f2fe78bSCy Schubert return EINVAL;
428*7f2fe78bSCy Schubert }
429*7f2fe78bSCy Schubert entry_slot = &(*entry_slot)->next;
430*7f2fe78bSCy Schubert free(line);
431*7f2fe78bSCy Schubert }
432*7f2fe78bSCy Schubert
433*7f2fe78bSCy Schubert fclose(fp);
434*7f2fe78bSCy Schubert return 0;
435*7f2fe78bSCy Schubert }
436*7f2fe78bSCy Schubert
437*7f2fe78bSCy Schubert /*
438*7f2fe78bSCy Schubert * See if two data entries match. If e1 is a wildcard (matching a whole
439*7f2fe78bSCy Schubert * component only) and targetflag is false, save an alias to e2 into
440*7f2fe78bSCy Schubert * ws->backref. If e1 is a back-reference and targetflag is true, compare the
441*7f2fe78bSCy Schubert * appropriate entry in ws->backref to e2. If ws is NULL, do not store or
442*7f2fe78bSCy Schubert * match back-references.
443*7f2fe78bSCy Schubert */
444*7f2fe78bSCy Schubert static krb5_boolean
match_data(const krb5_data * e1,const krb5_data * e2,krb5_boolean targetflag,struct wildstate * ws)445*7f2fe78bSCy Schubert match_data(const krb5_data *e1, const krb5_data *e2, krb5_boolean targetflag,
446*7f2fe78bSCy Schubert struct wildstate *ws)
447*7f2fe78bSCy Schubert {
448*7f2fe78bSCy Schubert int n;
449*7f2fe78bSCy Schubert
450*7f2fe78bSCy Schubert if (data_eq_string(*e1, "*")) {
451*7f2fe78bSCy Schubert if (ws != NULL && !targetflag) {
452*7f2fe78bSCy Schubert if (ws->nwild < 9)
453*7f2fe78bSCy Schubert ws->backref[ws->nwild++] = e2;
454*7f2fe78bSCy Schubert }
455*7f2fe78bSCy Schubert return TRUE;
456*7f2fe78bSCy Schubert }
457*7f2fe78bSCy Schubert
458*7f2fe78bSCy Schubert if (ws != NULL && targetflag && e1->length == 2 && e1->data[0] == '*' &&
459*7f2fe78bSCy Schubert e1->data[1] >= '1' && e1->data[1] <= '9') {
460*7f2fe78bSCy Schubert n = e1->data[1] - '1';
461*7f2fe78bSCy Schubert if (n >= ws->nwild)
462*7f2fe78bSCy Schubert return FALSE;
463*7f2fe78bSCy Schubert return data_eq(*e2, *ws->backref[n]);
464*7f2fe78bSCy Schubert } else {
465*7f2fe78bSCy Schubert return data_eq(*e2, *e1);
466*7f2fe78bSCy Schubert }
467*7f2fe78bSCy Schubert }
468*7f2fe78bSCy Schubert
469*7f2fe78bSCy Schubert /* Return true if p1 matches p2. p1 may contain wildcards if targetflag is
470*7f2fe78bSCy Schubert * false, or backreferences if it is true. */
471*7f2fe78bSCy Schubert static krb5_boolean
match_princ(krb5_const_principal p1,krb5_const_principal p2,krb5_boolean targetflag,struct wildstate * ws)472*7f2fe78bSCy Schubert match_princ(krb5_const_principal p1, krb5_const_principal p2,
473*7f2fe78bSCy Schubert krb5_boolean targetflag, struct wildstate *ws)
474*7f2fe78bSCy Schubert {
475*7f2fe78bSCy Schubert int i;
476*7f2fe78bSCy Schubert
477*7f2fe78bSCy Schubert /* The principals must be of the same length. */
478*7f2fe78bSCy Schubert if (p1->length != p2->length)
479*7f2fe78bSCy Schubert return FALSE;
480*7f2fe78bSCy Schubert
481*7f2fe78bSCy Schubert /* The realm must match, and does not interact with wildcard state. */
482*7f2fe78bSCy Schubert if (!match_data(&p1->realm, &p2->realm, targetflag, NULL))
483*7f2fe78bSCy Schubert return FALSE;
484*7f2fe78bSCy Schubert
485*7f2fe78bSCy Schubert /* All components of the principals must match. */
486*7f2fe78bSCy Schubert for (i = 0; i < p1->length; i++) {
487*7f2fe78bSCy Schubert if (!match_data(&p1->data[i], &p2->data[i], targetflag, ws))
488*7f2fe78bSCy Schubert return FALSE;
489*7f2fe78bSCy Schubert }
490*7f2fe78bSCy Schubert
491*7f2fe78bSCy Schubert return TRUE;
492*7f2fe78bSCy Schubert }
493*7f2fe78bSCy Schubert
494*7f2fe78bSCy Schubert /* Find an ACL entry matching principal and target_principal. Return NULL if
495*7f2fe78bSCy Schubert * none is found. */
496*7f2fe78bSCy Schubert static struct acl_entry *
find_entry(struct acl_state * state,krb5_const_principal client,krb5_const_principal target)497*7f2fe78bSCy Schubert find_entry(struct acl_state *state, krb5_const_principal client,
498*7f2fe78bSCy Schubert krb5_const_principal target)
499*7f2fe78bSCy Schubert {
500*7f2fe78bSCy Schubert struct acl_entry *entry;
501*7f2fe78bSCy Schubert struct wildstate ws;
502*7f2fe78bSCy Schubert
503*7f2fe78bSCy Schubert for (entry = state->list; entry != NULL; entry = entry->next) {
504*7f2fe78bSCy Schubert memset(&ws, 0, sizeof(ws));
505*7f2fe78bSCy Schubert if (entry->client != NULL) {
506*7f2fe78bSCy Schubert if (!match_princ(entry->client, client, FALSE, &ws))
507*7f2fe78bSCy Schubert continue;
508*7f2fe78bSCy Schubert }
509*7f2fe78bSCy Schubert
510*7f2fe78bSCy Schubert if (entry->target != NULL) {
511*7f2fe78bSCy Schubert if (target == NULL)
512*7f2fe78bSCy Schubert continue;
513*7f2fe78bSCy Schubert if (!match_princ(entry->target, target, TRUE, &ws))
514*7f2fe78bSCy Schubert continue;
515*7f2fe78bSCy Schubert }
516*7f2fe78bSCy Schubert
517*7f2fe78bSCy Schubert return entry;
518*7f2fe78bSCy Schubert }
519*7f2fe78bSCy Schubert
520*7f2fe78bSCy Schubert return NULL;
521*7f2fe78bSCy Schubert }
522*7f2fe78bSCy Schubert
523*7f2fe78bSCy Schubert /* Return true if op is permitted for this principal. Set *rs_out (if not
524*7f2fe78bSCy Schubert * NULL) according to any restrictions in the ACL entry. */
525*7f2fe78bSCy Schubert static krb5_error_code
acl_check(kadm5_auth_moddata data,uint32_t op,krb5_const_principal client,krb5_const_principal target,struct kadm5_auth_restrictions ** rs_out)526*7f2fe78bSCy Schubert acl_check(kadm5_auth_moddata data, uint32_t op, krb5_const_principal client,
527*7f2fe78bSCy Schubert krb5_const_principal target, struct kadm5_auth_restrictions **rs_out)
528*7f2fe78bSCy Schubert {
529*7f2fe78bSCy Schubert struct acl_entry *entry;
530*7f2fe78bSCy Schubert
531*7f2fe78bSCy Schubert if (rs_out != NULL)
532*7f2fe78bSCy Schubert *rs_out = NULL;
533*7f2fe78bSCy Schubert
534*7f2fe78bSCy Schubert entry = find_entry((struct acl_state *)data, client, target);
535*7f2fe78bSCy Schubert if (entry == NULL)
536*7f2fe78bSCy Schubert return KRB5_PLUGIN_NO_HANDLE;
537*7f2fe78bSCy Schubert if (!(entry->op_allowed & op))
538*7f2fe78bSCy Schubert return KRB5_PLUGIN_NO_HANDLE;
539*7f2fe78bSCy Schubert
540*7f2fe78bSCy Schubert if (rs_out != NULL && entry->rs != NULL && entry->rs->mask)
541*7f2fe78bSCy Schubert *rs_out = entry->rs;
542*7f2fe78bSCy Schubert
543*7f2fe78bSCy Schubert return 0;
544*7f2fe78bSCy Schubert }
545*7f2fe78bSCy Schubert
546*7f2fe78bSCy Schubert static krb5_error_code
acl_init(krb5_context context,const char * acl_file,kadm5_auth_moddata * data_out)547*7f2fe78bSCy Schubert acl_init(krb5_context context, const char *acl_file,
548*7f2fe78bSCy Schubert kadm5_auth_moddata *data_out)
549*7f2fe78bSCy Schubert {
550*7f2fe78bSCy Schubert krb5_error_code ret;
551*7f2fe78bSCy Schubert struct acl_state *state;
552*7f2fe78bSCy Schubert
553*7f2fe78bSCy Schubert *data_out = NULL;
554*7f2fe78bSCy Schubert if (acl_file == NULL)
555*7f2fe78bSCy Schubert return KRB5_PLUGIN_NO_HANDLE;
556*7f2fe78bSCy Schubert state = malloc(sizeof(*state));
557*7f2fe78bSCy Schubert state->list = NULL;
558*7f2fe78bSCy Schubert ret = load_acl_file(context, acl_file, state);
559*7f2fe78bSCy Schubert if (ret) {
560*7f2fe78bSCy Schubert free(state);
561*7f2fe78bSCy Schubert return ret;
562*7f2fe78bSCy Schubert }
563*7f2fe78bSCy Schubert *data_out = (kadm5_auth_moddata)state;
564*7f2fe78bSCy Schubert return 0;
565*7f2fe78bSCy Schubert }
566*7f2fe78bSCy Schubert
567*7f2fe78bSCy Schubert static void
acl_fini(krb5_context context,kadm5_auth_moddata data)568*7f2fe78bSCy Schubert acl_fini(krb5_context context, kadm5_auth_moddata data)
569*7f2fe78bSCy Schubert {
570*7f2fe78bSCy Schubert if (data == NULL)
571*7f2fe78bSCy Schubert return;
572*7f2fe78bSCy Schubert free_acl_entries((struct acl_state *)data);
573*7f2fe78bSCy Schubert free(data);
574*7f2fe78bSCy Schubert }
575*7f2fe78bSCy Schubert
576*7f2fe78bSCy Schubert static krb5_error_code
acl_addprinc(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target,const struct _kadm5_principal_ent_t * ent,long mask,struct kadm5_auth_restrictions ** rs_out)577*7f2fe78bSCy Schubert acl_addprinc(krb5_context context, kadm5_auth_moddata data,
578*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target,
579*7f2fe78bSCy Schubert const struct _kadm5_principal_ent_t *ent, long mask,
580*7f2fe78bSCy Schubert struct kadm5_auth_restrictions **rs_out)
581*7f2fe78bSCy Schubert {
582*7f2fe78bSCy Schubert return acl_check(data, ACL_ADD, client, target, rs_out);
583*7f2fe78bSCy Schubert }
584*7f2fe78bSCy Schubert
585*7f2fe78bSCy Schubert static krb5_error_code
acl_modprinc(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target,const struct _kadm5_principal_ent_t * ent,long mask,struct kadm5_auth_restrictions ** rs_out)586*7f2fe78bSCy Schubert acl_modprinc(krb5_context context, kadm5_auth_moddata data,
587*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target,
588*7f2fe78bSCy Schubert const struct _kadm5_principal_ent_t *ent, long mask,
589*7f2fe78bSCy Schubert struct kadm5_auth_restrictions **rs_out)
590*7f2fe78bSCy Schubert {
591*7f2fe78bSCy Schubert return acl_check(data, ACL_MODIFY, client, target, rs_out);
592*7f2fe78bSCy Schubert }
593*7f2fe78bSCy Schubert
594*7f2fe78bSCy Schubert static krb5_error_code
acl_setstr(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target,const char * key,const char * value)595*7f2fe78bSCy Schubert acl_setstr(krb5_context context, kadm5_auth_moddata data,
596*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target,
597*7f2fe78bSCy Schubert const char *key, const char *value)
598*7f2fe78bSCy Schubert {
599*7f2fe78bSCy Schubert return acl_check(data, ACL_MODIFY, client, target, NULL);
600*7f2fe78bSCy Schubert }
601*7f2fe78bSCy Schubert
602*7f2fe78bSCy Schubert static krb5_error_code
acl_cpw(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target)603*7f2fe78bSCy Schubert acl_cpw(krb5_context context, kadm5_auth_moddata data,
604*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target)
605*7f2fe78bSCy Schubert {
606*7f2fe78bSCy Schubert return acl_check(data, ACL_CHANGEPW, client, target, NULL);
607*7f2fe78bSCy Schubert }
608*7f2fe78bSCy Schubert
609*7f2fe78bSCy Schubert static krb5_error_code
acl_chrand(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target)610*7f2fe78bSCy Schubert acl_chrand(krb5_context context, kadm5_auth_moddata data,
611*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target)
612*7f2fe78bSCy Schubert {
613*7f2fe78bSCy Schubert return acl_check(data, ACL_CHANGEPW, client, target, NULL);
614*7f2fe78bSCy Schubert }
615*7f2fe78bSCy Schubert
616*7f2fe78bSCy Schubert static krb5_error_code
acl_setkey(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target)617*7f2fe78bSCy Schubert acl_setkey(krb5_context context, kadm5_auth_moddata data,
618*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target)
619*7f2fe78bSCy Schubert {
620*7f2fe78bSCy Schubert return acl_check(data, ACL_SETKEY, client, target, NULL);
621*7f2fe78bSCy Schubert }
622*7f2fe78bSCy Schubert
623*7f2fe78bSCy Schubert static krb5_error_code
acl_purgekeys(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target)624*7f2fe78bSCy Schubert acl_purgekeys(krb5_context context, kadm5_auth_moddata data,
625*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target)
626*7f2fe78bSCy Schubert {
627*7f2fe78bSCy Schubert return acl_check(data, ACL_MODIFY, client, target, NULL);
628*7f2fe78bSCy Schubert }
629*7f2fe78bSCy Schubert
630*7f2fe78bSCy Schubert static krb5_error_code
acl_delprinc(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target)631*7f2fe78bSCy Schubert acl_delprinc(krb5_context context, kadm5_auth_moddata data,
632*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target)
633*7f2fe78bSCy Schubert {
634*7f2fe78bSCy Schubert return acl_check(data, ACL_DELETE, client, target, NULL);
635*7f2fe78bSCy Schubert }
636*7f2fe78bSCy Schubert
637*7f2fe78bSCy Schubert static krb5_error_code
acl_renprinc(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal src,krb5_const_principal dest)638*7f2fe78bSCy Schubert acl_renprinc(krb5_context context, kadm5_auth_moddata data,
639*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal src,
640*7f2fe78bSCy Schubert krb5_const_principal dest)
641*7f2fe78bSCy Schubert {
642*7f2fe78bSCy Schubert struct kadm5_auth_restrictions *rs;
643*7f2fe78bSCy Schubert
644*7f2fe78bSCy Schubert if (acl_check(data, ACL_DELETE, client, src, NULL) == 0 &&
645*7f2fe78bSCy Schubert acl_check(data, ACL_ADD, client, dest, &rs) == 0 && rs == NULL)
646*7f2fe78bSCy Schubert return 0;
647*7f2fe78bSCy Schubert return KRB5_PLUGIN_NO_HANDLE;
648*7f2fe78bSCy Schubert }
649*7f2fe78bSCy Schubert
650*7f2fe78bSCy Schubert static krb5_error_code
acl_getprinc(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target)651*7f2fe78bSCy Schubert acl_getprinc(krb5_context context, kadm5_auth_moddata data,
652*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target)
653*7f2fe78bSCy Schubert {
654*7f2fe78bSCy Schubert return acl_check(data, ACL_INQUIRE, client, target, NULL);
655*7f2fe78bSCy Schubert }
656*7f2fe78bSCy Schubert
657*7f2fe78bSCy Schubert static krb5_error_code
acl_getstrs(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target)658*7f2fe78bSCy Schubert acl_getstrs(krb5_context context, kadm5_auth_moddata data,
659*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target)
660*7f2fe78bSCy Schubert {
661*7f2fe78bSCy Schubert return acl_check(data, ACL_INQUIRE, client, target, NULL);
662*7f2fe78bSCy Schubert }
663*7f2fe78bSCy Schubert
664*7f2fe78bSCy Schubert static krb5_error_code
acl_extract(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,krb5_const_principal target)665*7f2fe78bSCy Schubert acl_extract(krb5_context context, kadm5_auth_moddata data,
666*7f2fe78bSCy Schubert krb5_const_principal client, krb5_const_principal target)
667*7f2fe78bSCy Schubert {
668*7f2fe78bSCy Schubert return acl_check(data, ACL_EXTRACT, client, target, NULL);
669*7f2fe78bSCy Schubert }
670*7f2fe78bSCy Schubert
671*7f2fe78bSCy Schubert static krb5_error_code
acl_listprincs(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client)672*7f2fe78bSCy Schubert acl_listprincs(krb5_context context, kadm5_auth_moddata data,
673*7f2fe78bSCy Schubert krb5_const_principal client)
674*7f2fe78bSCy Schubert {
675*7f2fe78bSCy Schubert return acl_check(data, ACL_LIST, client, NULL, NULL);
676*7f2fe78bSCy Schubert }
677*7f2fe78bSCy Schubert
678*7f2fe78bSCy Schubert static krb5_error_code
acl_addpol(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,const char * policy,const struct _kadm5_policy_ent_t * ent,long mask)679*7f2fe78bSCy Schubert acl_addpol(krb5_context context, kadm5_auth_moddata data,
680*7f2fe78bSCy Schubert krb5_const_principal client, const char *policy,
681*7f2fe78bSCy Schubert const struct _kadm5_policy_ent_t *ent, long mask)
682*7f2fe78bSCy Schubert {
683*7f2fe78bSCy Schubert return acl_check(data, ACL_ADD, client, NULL, NULL);
684*7f2fe78bSCy Schubert }
685*7f2fe78bSCy Schubert
686*7f2fe78bSCy Schubert static krb5_error_code
acl_modpol(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,const char * policy,const struct _kadm5_policy_ent_t * ent,long mask)687*7f2fe78bSCy Schubert acl_modpol(krb5_context context, kadm5_auth_moddata data,
688*7f2fe78bSCy Schubert krb5_const_principal client, const char *policy,
689*7f2fe78bSCy Schubert const struct _kadm5_policy_ent_t *ent, long mask)
690*7f2fe78bSCy Schubert {
691*7f2fe78bSCy Schubert return acl_check(data, ACL_MODIFY, client, NULL, NULL);
692*7f2fe78bSCy Schubert }
693*7f2fe78bSCy Schubert
694*7f2fe78bSCy Schubert static krb5_error_code
acl_delpol(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,const char * policy)695*7f2fe78bSCy Schubert acl_delpol(krb5_context context, kadm5_auth_moddata data,
696*7f2fe78bSCy Schubert krb5_const_principal client, const char *policy)
697*7f2fe78bSCy Schubert {
698*7f2fe78bSCy Schubert return acl_check(data, ACL_DELETE, client, NULL, NULL);
699*7f2fe78bSCy Schubert }
700*7f2fe78bSCy Schubert
701*7f2fe78bSCy Schubert static krb5_error_code
acl_getpol(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client,const char * policy,const char * client_policy)702*7f2fe78bSCy Schubert acl_getpol(krb5_context context, kadm5_auth_moddata data,
703*7f2fe78bSCy Schubert krb5_const_principal client, const char *policy,
704*7f2fe78bSCy Schubert const char *client_policy)
705*7f2fe78bSCy Schubert {
706*7f2fe78bSCy Schubert return acl_check(data, ACL_INQUIRE, client, NULL, NULL);
707*7f2fe78bSCy Schubert }
708*7f2fe78bSCy Schubert
709*7f2fe78bSCy Schubert static krb5_error_code
acl_listpols(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client)710*7f2fe78bSCy Schubert acl_listpols(krb5_context context, kadm5_auth_moddata data,
711*7f2fe78bSCy Schubert krb5_const_principal client)
712*7f2fe78bSCy Schubert {
713*7f2fe78bSCy Schubert return acl_check(data, ACL_LIST, client, NULL, NULL);
714*7f2fe78bSCy Schubert }
715*7f2fe78bSCy Schubert
716*7f2fe78bSCy Schubert static krb5_error_code
acl_iprop(krb5_context context,kadm5_auth_moddata data,krb5_const_principal client)717*7f2fe78bSCy Schubert acl_iprop(krb5_context context, kadm5_auth_moddata data,
718*7f2fe78bSCy Schubert krb5_const_principal client)
719*7f2fe78bSCy Schubert {
720*7f2fe78bSCy Schubert return acl_check(data, ACL_IPROP, client, NULL, NULL);
721*7f2fe78bSCy Schubert }
722*7f2fe78bSCy Schubert
723*7f2fe78bSCy Schubert krb5_error_code
kadm5_auth_acl_initvt(krb5_context context,int maj_ver,int min_ver,krb5_plugin_vtable vtable)724*7f2fe78bSCy Schubert kadm5_auth_acl_initvt(krb5_context context, int maj_ver, int min_ver,
725*7f2fe78bSCy Schubert krb5_plugin_vtable vtable)
726*7f2fe78bSCy Schubert {
727*7f2fe78bSCy Schubert kadm5_auth_vtable vt;
728*7f2fe78bSCy Schubert
729*7f2fe78bSCy Schubert if (maj_ver != 1)
730*7f2fe78bSCy Schubert return KRB5_PLUGIN_VER_NOTSUPP;
731*7f2fe78bSCy Schubert vt = (kadm5_auth_vtable)vtable;
732*7f2fe78bSCy Schubert vt->name = "acl";
733*7f2fe78bSCy Schubert vt->init = acl_init;
734*7f2fe78bSCy Schubert vt->fini = acl_fini;
735*7f2fe78bSCy Schubert vt->addprinc = acl_addprinc;
736*7f2fe78bSCy Schubert vt->modprinc = acl_modprinc;
737*7f2fe78bSCy Schubert vt->setstr = acl_setstr;
738*7f2fe78bSCy Schubert vt->cpw = acl_cpw;
739*7f2fe78bSCy Schubert vt->chrand = acl_chrand;
740*7f2fe78bSCy Schubert vt->setkey = acl_setkey;
741*7f2fe78bSCy Schubert vt->purgekeys = acl_purgekeys;
742*7f2fe78bSCy Schubert vt->delprinc = acl_delprinc;
743*7f2fe78bSCy Schubert vt->renprinc = acl_renprinc;
744*7f2fe78bSCy Schubert vt->getprinc = acl_getprinc;
745*7f2fe78bSCy Schubert vt->getstrs = acl_getstrs;
746*7f2fe78bSCy Schubert vt->extract = acl_extract;
747*7f2fe78bSCy Schubert vt->listprincs = acl_listprincs;
748*7f2fe78bSCy Schubert vt->addpol = acl_addpol;
749*7f2fe78bSCy Schubert vt->modpol = acl_modpol;
750*7f2fe78bSCy Schubert vt->delpol = acl_delpol;
751*7f2fe78bSCy Schubert vt->getpol = acl_getpol;
752*7f2fe78bSCy Schubert vt->listpols = acl_listpols;
753*7f2fe78bSCy Schubert vt->iprop = acl_iprop;
754*7f2fe78bSCy Schubert return 0;
755*7f2fe78bSCy Schubert }
756