acl.c revision 72445
1124758Semax/* 2124758Semax * Copyright (c) 1997 - 2000 Kungliga Tekniska H�gskolan 3124758Semax * (Royal Institute of Technology, Stockholm, Sweden). 4124758Semax * All rights reserved. 5124758Semax * 6124758Semax * Redistribution and use in source and binary forms, with or without 7124758Semax * modification, are permitted provided that the following conditions 8124758Semax * are met: 9124758Semax * 10124758Semax * 1. Redistributions of source code must retain the above copyright 11124758Semax * notice, this list of conditions and the following disclaimer. 12124758Semax * 13124758Semax * 2. Redistributions in binary form must reproduce the above copyright 14124758Semax * notice, this list of conditions and the following disclaimer in the 15124758Semax * documentation and/or other materials provided with the distribution. 16124758Semax * 17124758Semax * 3. Neither the name of the Institute nor the names of its contributors 18124758Semax * may be used to endorse or promote products derived from this software 19124758Semax * without specific prior written permission. 20124758Semax * 21124758Semax * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22124758Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23124758Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24124758Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25124758Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26124758Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27124758Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28124758Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29124758Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30124758Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31124758Semax * SUCH DAMAGE. 32124758Semax */ 33124758Semax 34124758Semax#include "kadm5_locl.h" 35124758Semax 36124758SemaxRCSID("$Id: acl.c,v 1.12 2000/08/10 19:24:08 assar Exp $"); 37124758Semax 38124758Semaxstatic struct units acl_units[] = { 39124758Semax { "all", KADM5_PRIV_ALL }, 40124758Semax { "change-password",KADM5_PRIV_CPW }, 41124758Semax { "cpw", KADM5_PRIV_CPW }, 42124758Semax { "list", KADM5_PRIV_LIST }, 43124758Semax { "delete", KADM5_PRIV_DELETE }, 44139721Semax { "modify", KADM5_PRIV_MODIFY }, 45124758Semax { "add", KADM5_PRIV_ADD }, 46124758Semax { "get", KADM5_PRIV_GET }, 47124758Semax { NULL } 48124758Semax}; 49124758Semax 50124758Semaxkadm5_ret_t 51124758Semax_kadm5_string_to_privs(const char *s, u_int32_t* privs) 52124758Semax{ 53124758Semax int flags; 54124758Semax flags = parse_flags(s, acl_units, 0); 55124758Semax if(flags < 0) 56124758Semax return KADM5_FAILURE; 57124758Semax *privs = flags; 58124758Semax return 0; 59124758Semax} 60139721Semax 61139721Semaxkadm5_ret_t 62124758Semax_kadm5_privs_to_string(u_int32_t privs, char *string, size_t len) 63124758Semax{ 64124758Semax if(privs == 0) 65124758Semax strlcpy(string, "none", len); 66124758Semax else 67124758Semax unparse_flags(privs, acl_units + 1, string, len); 68124758Semax return 0; 69124758Semax} 70124758Semax 71124758Semax/* 72124758Semax * retrieve the right for the current caller on `princ' (NULL means all) 73124758Semax * and store them in `ret_flags' 74124758Semax * return 0 or an error. 75124758Semax */ 76124758Semax 77124758Semaxstatic kadm5_ret_t 78124758Semaxfetch_acl (kadm5_server_context *context, 79124758Semax krb5_const_principal princ, 80124758Semax unsigned *ret_flags) 81124758Semax{ 82124758Semax unsigned flags = -1; 83124758Semax FILE *f = fopen(context->config.acl_file, "r"); 84124758Semax krb5_error_code ret = 0; 85124758Semax 86124758Semax if(f != NULL) { 87124758Semax char buf[256]; 88124758Semax 89124758Semax while(fgets(buf, sizeof(buf), f) != NULL){ 90124758Semax char *foo = NULL, *p; 91124758Semax krb5_principal this_princ; 92124758Semax 93124758Semax flags = -1; 94124758Semax p = strtok_r(buf, " \t\n", &foo); 95124758Semax if(p == NULL) 96124758Semax continue; 97124758Semax ret = krb5_parse_name(context->context, p, &this_princ); 98124758Semax if(ret) 99124758Semax continue; 100124758Semax if(!krb5_principal_compare(context->context, 101124758Semax context->caller, this_princ)) { 102124758Semax krb5_free_principal(context->context, this_princ); 103124758Semax continue; 104124758Semax } 105124758Semax krb5_free_principal(context->context, this_princ); 106124758Semax p = strtok_r(NULL, " \t\n", &foo); 107124758Semax if(p == NULL) 108124758Semax continue; 109124758Semax ret = _kadm5_string_to_privs(p, &flags); 110124758Semax if (ret) 111124758Semax break; 112124758Semax p = strtok_r(NULL, "\n", &foo); 113124758Semax if (p == NULL) { 114124758Semax ret = 0; 115124758Semax break; 116124758Semax } 117124758Semax if (princ != NULL) { 118124758Semax krb5_principal pattern_princ; 119124758Semax krb5_boolean tmp; 120124758Semax 121124758Semax ret = krb5_parse_name (context->context, p, &pattern_princ); 122124758Semax if (ret) 123124758Semax break; 124124758Semax tmp = krb5_principal_match (context->context, 125124758Semax princ, pattern_princ); 126124758Semax krb5_free_principal (context->context, pattern_princ); 127124758Semax if (tmp) { 128124758Semax ret = 0; 129124758Semax break; 130124758Semax } 131124758Semax } 132124758Semax } 133124758Semax fclose(f); 134124758Semax } 135124758Semax if(flags == -1) 136124758Semax flags = 0; 137124758Semax if (ret == 0) 138124758Semax *ret_flags = flags; 139124758Semax return ret; 140124758Semax} 141124758Semax 142124758Semax/* 143124758Semax * set global acl flags in `context' for the current caller. 144124758Semax * return 0 on success or an error 145124758Semax */ 146124758Semax 147124758Semaxkadm5_ret_t 148124758Semax_kadm5_acl_init(kadm5_server_context *context) 149124758Semax{ 150139721Semax krb5_principal princ; 151139721Semax krb5_error_code ret; 152139721Semax 153124758Semax ret = krb5_parse_name(context->context, KADM5_ADMIN_SERVICE, &princ); 154124758Semax if (ret) 155124758Semax return ret; 156139721Semax ret = krb5_principal_compare(context->context, context->caller, princ); 157139721Semax krb5_free_principal(context->context, princ); 158139721Semax if(ret != 0) { 159139721Semax context->acl_flags = KADM5_PRIV_ALL; 160139721Semax return 0; 161139721Semax } 162139721Semax 163139721Semax return fetch_acl (context, NULL, &context->acl_flags); 164139721Semax} 165139721Semax 166139721Semax/* 167139721Semax * check if `flags' allows `op' 168139721Semax * return 0 if OK or an error 169139721Semax */ 170139721Semax 171139721Semaxstatic kadm5_ret_t 172139721Semaxcheck_flags (unsigned op, 173139721Semax unsigned flags) 174139721Semax{ 175139721Semax unsigned res = ~flags & op; 176139721Semax 177124758Semax if(res & KADM5_PRIV_GET) 178124758Semax return KADM5_AUTH_GET; 179124758Semax if(res & KADM5_PRIV_ADD) 180124758Semax return KADM5_AUTH_ADD; 181124758Semax if(res & KADM5_PRIV_MODIFY) 182124758Semax return KADM5_AUTH_MODIFY; 183124758Semax if(res & KADM5_PRIV_DELETE) 184124758Semax return KADM5_AUTH_DELETE; 185124758Semax if(res & KADM5_PRIV_CPW) 186124758Semax return KADM5_AUTH_CHANGEPW; 187124758Semax if(res & KADM5_PRIV_LIST) 188139721Semax return KADM5_AUTH_LIST; 189139721Semax if(res) 190139721Semax return KADM5_AUTH_INSUFFICIENT; 191139721Semax return 0; 192139721Semax} 193139721Semax 194124758Semax/* 195124758Semax * return 0 if the current caller in `context' is allowed to perform 196124758Semax * `op' on `princ' and otherwise an error 197124758Semax * princ == NULL if it's not relevant. 198124758Semax */ 199124758Semax 200124758Semaxkadm5_ret_t 201124758Semax_kadm5_acl_check_permission(kadm5_server_context *context, 202124758Semax unsigned op, 203124758Semax krb5_const_principal princ) 204124758Semax{ 205124758Semax kadm5_ret_t ret; 206124758Semax unsigned princ_flags; 207124758Semax 208124758Semax ret = check_flags (op, context->acl_flags); 209124758Semax if (ret == 0) 210124758Semax return ret; 211124758Semax ret = fetch_acl (context, princ, &princ_flags); 212124758Semax if (ret) 213124758Semax return ret; 214124758Semax return check_flags (op, princ_flags); 215124758Semax} 216124758Semax