1b528cefcSMark Murray /* 24137ff4cSJacques Vidrine * 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*c19800e8SDoug Rabson RCSID("$Id: acl.c 17445 2006-05-05 10:37:46Z lha $"); 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 }, 47b528cefcSMark Murray { NULL } 48b528cefcSMark Murray }; 49b528cefcSMark Murray 50b528cefcSMark Murray kadm5_ret_t 51*c19800e8SDoug 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 62*c19800e8SDoug 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 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; 118*c19800e8SDoug 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 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 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 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