1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "kadm5_locl.h"
35b528cefcSMark Murray
36*ae771770SStanislav Sedov RCSID("$Id$");
37b528cefcSMark Murray
38b528cefcSMark Murray static struct units acl_units[] = {
39b528cefcSMark Murray { "all", KADM5_PRIV_ALL },
40b528cefcSMark Murray { "change-password",KADM5_PRIV_CPW },
41b528cefcSMark Murray { "cpw", KADM5_PRIV_CPW },
42b528cefcSMark Murray { "list", KADM5_PRIV_LIST },
43b528cefcSMark Murray { "delete", KADM5_PRIV_DELETE },
44b528cefcSMark Murray { "modify", KADM5_PRIV_MODIFY },
45b528cefcSMark Murray { "add", KADM5_PRIV_ADD },
46b528cefcSMark Murray { "get", KADM5_PRIV_GET },
47*ae771770SStanislav Sedov { NULL, 0 }
48b528cefcSMark Murray };
49b528cefcSMark Murray
50b528cefcSMark Murray kadm5_ret_t
_kadm5_string_to_privs(const char * s,uint32_t * privs)51c19800e8SDoug Rabson _kadm5_string_to_privs(const char *s, uint32_t* privs)
52b528cefcSMark Murray {
53b528cefcSMark Murray int flags;
54b528cefcSMark Murray flags = parse_flags(s, acl_units, 0);
55b528cefcSMark Murray if(flags < 0)
56b528cefcSMark Murray return KADM5_FAILURE;
57b528cefcSMark Murray *privs = flags;
58b528cefcSMark Murray return 0;
59b528cefcSMark Murray }
60b528cefcSMark Murray
61b528cefcSMark Murray kadm5_ret_t
_kadm5_privs_to_string(uint32_t privs,char * string,size_t len)62c19800e8SDoug Rabson _kadm5_privs_to_string(uint32_t privs, char *string, size_t len)
63b528cefcSMark Murray {
64b528cefcSMark Murray if(privs == 0)
65b528cefcSMark Murray strlcpy(string, "none", len);
66b528cefcSMark Murray else
67b528cefcSMark Murray unparse_flags(privs, acl_units + 1, string, len);
68b528cefcSMark Murray return 0;
69b528cefcSMark Murray }
70b528cefcSMark Murray
715e9cd1aeSAssar Westerlund /*
725e9cd1aeSAssar Westerlund * retrieve the right for the current caller on `princ' (NULL means all)
735e9cd1aeSAssar Westerlund * and store them in `ret_flags'
745e9cd1aeSAssar Westerlund * return 0 or an error.
755e9cd1aeSAssar Westerlund */
765e9cd1aeSAssar Westerlund
775e9cd1aeSAssar Westerlund static kadm5_ret_t
fetch_acl(kadm5_server_context * context,krb5_const_principal princ,unsigned * ret_flags)785e9cd1aeSAssar Westerlund fetch_acl (kadm5_server_context *context,
795e9cd1aeSAssar Westerlund krb5_const_principal princ,
805e9cd1aeSAssar Westerlund unsigned *ret_flags)
815e9cd1aeSAssar Westerlund {
824137ff4cSJacques Vidrine FILE *f;
835e9cd1aeSAssar Westerlund krb5_error_code ret = 0;
845e9cd1aeSAssar Westerlund char buf[256];
855e9cd1aeSAssar Westerlund
864137ff4cSJacques Vidrine *ret_flags = 0;
874137ff4cSJacques Vidrine
884137ff4cSJacques Vidrine /* no acl file -> no rights */
894137ff4cSJacques Vidrine f = fopen(context->config.acl_file, "r");
904137ff4cSJacques Vidrine if (f == NULL)
914137ff4cSJacques Vidrine return 0;
924137ff4cSJacques Vidrine
935e9cd1aeSAssar Westerlund while(fgets(buf, sizeof(buf), f) != NULL) {
945e9cd1aeSAssar Westerlund char *foo = NULL, *p;
955e9cd1aeSAssar Westerlund krb5_principal this_princ;
964137ff4cSJacques Vidrine unsigned flags = 0;
975e9cd1aeSAssar Westerlund
985e9cd1aeSAssar Westerlund p = strtok_r(buf, " \t\n", &foo);
995e9cd1aeSAssar Westerlund if(p == NULL)
1005e9cd1aeSAssar Westerlund continue;
1014137ff4cSJacques Vidrine if (*p == '#') /* comment */
1024137ff4cSJacques Vidrine continue;
1035e9cd1aeSAssar Westerlund ret = krb5_parse_name(context->context, p, &this_princ);
1045e9cd1aeSAssar Westerlund if(ret)
1054137ff4cSJacques Vidrine break;
1065e9cd1aeSAssar Westerlund if(!krb5_principal_compare(context->context,
1075e9cd1aeSAssar Westerlund context->caller, this_princ)) {
1085e9cd1aeSAssar Westerlund krb5_free_principal(context->context, this_princ);
1095e9cd1aeSAssar Westerlund continue;
1105e9cd1aeSAssar Westerlund }
1115e9cd1aeSAssar Westerlund krb5_free_principal(context->context, this_princ);
1125e9cd1aeSAssar Westerlund p = strtok_r(NULL, " \t\n", &foo);
1135e9cd1aeSAssar Westerlund if(p == NULL)
1145e9cd1aeSAssar Westerlund continue;
1155e9cd1aeSAssar Westerlund ret = _kadm5_string_to_privs(p, &flags);
1165e9cd1aeSAssar Westerlund if (ret)
1175e9cd1aeSAssar Westerlund break;
118c19800e8SDoug Rabson p = strtok_r(NULL, " \t\n", &foo);
1195e9cd1aeSAssar Westerlund if (p == NULL) {
1204137ff4cSJacques Vidrine *ret_flags = flags;
1215e9cd1aeSAssar Westerlund break;
1225e9cd1aeSAssar Westerlund }
1235e9cd1aeSAssar Westerlund if (princ != NULL) {
1245e9cd1aeSAssar Westerlund krb5_principal pattern_princ;
1254137ff4cSJacques Vidrine krb5_boolean match;
1265e9cd1aeSAssar Westerlund
1275e9cd1aeSAssar Westerlund ret = krb5_parse_name (context->context, p, &pattern_princ);
1285e9cd1aeSAssar Westerlund if (ret)
1295e9cd1aeSAssar Westerlund break;
1304137ff4cSJacques Vidrine match = krb5_principal_match (context->context,
1315e9cd1aeSAssar Westerlund princ, pattern_princ);
1325e9cd1aeSAssar Westerlund krb5_free_principal (context->context, pattern_princ);
1334137ff4cSJacques Vidrine if (match) {
1344137ff4cSJacques Vidrine *ret_flags = flags;
1355e9cd1aeSAssar Westerlund break;
1365e9cd1aeSAssar Westerlund }
1375e9cd1aeSAssar Westerlund }
1385e9cd1aeSAssar Westerlund }
1395e9cd1aeSAssar Westerlund fclose(f);
1405e9cd1aeSAssar Westerlund return ret;
1415e9cd1aeSAssar Westerlund }
1425e9cd1aeSAssar Westerlund
1435e9cd1aeSAssar Westerlund /*
1445e9cd1aeSAssar Westerlund * set global acl flags in `context' for the current caller.
1455e9cd1aeSAssar Westerlund * return 0 on success or an error
1465e9cd1aeSAssar Westerlund */
1475e9cd1aeSAssar Westerlund
148b528cefcSMark Murray kadm5_ret_t
_kadm5_acl_init(kadm5_server_context * context)149b528cefcSMark Murray _kadm5_acl_init(kadm5_server_context *context)
150b528cefcSMark Murray {
151b528cefcSMark Murray krb5_principal princ;
152b528cefcSMark Murray krb5_error_code ret;
153b528cefcSMark Murray
1545e9cd1aeSAssar Westerlund ret = krb5_parse_name(context->context, KADM5_ADMIN_SERVICE, &princ);
1555e9cd1aeSAssar Westerlund if (ret)
1565e9cd1aeSAssar Westerlund return ret;
157b528cefcSMark Murray ret = krb5_principal_compare(context->context, context->caller, princ);
158b528cefcSMark Murray krb5_free_principal(context->context, princ);
159b528cefcSMark Murray if(ret != 0) {
160b528cefcSMark Murray context->acl_flags = KADM5_PRIV_ALL;
161b528cefcSMark Murray return 0;
162b528cefcSMark Murray }
163b528cefcSMark Murray
1645e9cd1aeSAssar Westerlund return fetch_acl (context, NULL, &context->acl_flags);
165b528cefcSMark Murray }
166b528cefcSMark Murray
1675e9cd1aeSAssar Westerlund /*
1685e9cd1aeSAssar Westerlund * check if `flags' allows `op'
1695e9cd1aeSAssar Westerlund * return 0 if OK or an error
1705e9cd1aeSAssar Westerlund */
1715e9cd1aeSAssar Westerlund
1725e9cd1aeSAssar Westerlund static kadm5_ret_t
check_flags(unsigned op,unsigned flags)1735e9cd1aeSAssar Westerlund check_flags (unsigned op,
1745e9cd1aeSAssar Westerlund unsigned flags)
175b528cefcSMark Murray {
1765e9cd1aeSAssar Westerlund unsigned res = ~flags & op;
1775e9cd1aeSAssar Westerlund
178b528cefcSMark Murray if(res & KADM5_PRIV_GET)
179b528cefcSMark Murray return KADM5_AUTH_GET;
180b528cefcSMark Murray if(res & KADM5_PRIV_ADD)
181b528cefcSMark Murray return KADM5_AUTH_ADD;
182b528cefcSMark Murray if(res & KADM5_PRIV_MODIFY)
183b528cefcSMark Murray return KADM5_AUTH_MODIFY;
184b528cefcSMark Murray if(res & KADM5_PRIV_DELETE)
185b528cefcSMark Murray return KADM5_AUTH_DELETE;
186b528cefcSMark Murray if(res & KADM5_PRIV_CPW)
187b528cefcSMark Murray return KADM5_AUTH_CHANGEPW;
188b528cefcSMark Murray if(res & KADM5_PRIV_LIST)
189b528cefcSMark Murray return KADM5_AUTH_LIST;
190b528cefcSMark Murray if(res)
191b528cefcSMark Murray return KADM5_AUTH_INSUFFICIENT;
192b528cefcSMark Murray return 0;
193b528cefcSMark Murray }
1945e9cd1aeSAssar Westerlund
1955e9cd1aeSAssar Westerlund /*
1965e9cd1aeSAssar Westerlund * return 0 if the current caller in `context' is allowed to perform
1975e9cd1aeSAssar Westerlund * `op' on `princ' and otherwise an error
1985e9cd1aeSAssar Westerlund * princ == NULL if it's not relevant.
1995e9cd1aeSAssar Westerlund */
2005e9cd1aeSAssar Westerlund
2015e9cd1aeSAssar Westerlund kadm5_ret_t
_kadm5_acl_check_permission(kadm5_server_context * context,unsigned op,krb5_const_principal princ)2025e9cd1aeSAssar Westerlund _kadm5_acl_check_permission(kadm5_server_context *context,
2035e9cd1aeSAssar Westerlund unsigned op,
2045e9cd1aeSAssar Westerlund krb5_const_principal princ)
2055e9cd1aeSAssar Westerlund {
2065e9cd1aeSAssar Westerlund kadm5_ret_t ret;
2075e9cd1aeSAssar Westerlund unsigned princ_flags;
2085e9cd1aeSAssar Westerlund
2095e9cd1aeSAssar Westerlund ret = check_flags (op, context->acl_flags);
2105e9cd1aeSAssar Westerlund if (ret == 0)
2115e9cd1aeSAssar Westerlund return ret;
2125e9cd1aeSAssar Westerlund ret = fetch_acl (context, princ, &princ_flags);
2135e9cd1aeSAssar Westerlund if (ret)
2145e9cd1aeSAssar Westerlund return ret;
2155e9cd1aeSAssar Westerlund return check_flags (op, princ_flags);
2165e9cd1aeSAssar Westerlund }
217