From 46f0769f2d1d773948bc1ce6ef4d44c4cdb1924f Mon Sep 17 00:00:00 2001 From: Assar Westerlund Date: Wed, 7 Jun 2000 11:11:44 +0000 Subject: [PATCH] add support for patterns of principals git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@8350 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/kadm5/acl.c | 137 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 106 insertions(+), 31 deletions(-) diff --git a/lib/kadm5/acl.c b/lib/kadm5/acl.c index 3a33cd535..e66a05e96 100644 --- a/lib/kadm5/acl.c +++ b/lib/kadm5/acl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -68,58 +68,110 @@ _kadm5_privs_to_string(u_int32_t privs, char *string, size_t len) return 0; } -kadm5_ret_t -_kadm5_acl_init(kadm5_server_context *context) -{ - FILE *f; - char buf[128]; - krb5_principal princ; - int flags; - krb5_error_code ret; - - krb5_parse_name(context->context, KADM5_ADMIN_SERVICE, &princ); - ret = krb5_principal_compare(context->context, context->caller, princ); - krb5_free_principal(context->context, princ); - if(ret != 0){ - context->acl_flags = KADM5_PRIV_ALL; - return 0; - } +/* + * retrieve the right for the current caller on `princ' (NULL means all) + * and store them in `flags' + * return 0 or an error. + */ - flags = -1; - f = fopen(context->config.acl_file, "r"); - if(f){ - while(fgets(buf, sizeof(buf), f)){ +static kadm5_ret_t +fetch_acl (kadm5_server_context *context, + krb5_const_principal princ, + unsigned *ret_flags) +{ + unsigned flags = -1; + FILE *f = fopen(context->config.acl_file, "r"); + krb5_error_code ret = 0; + + if(f != NULL){ + char buf[256]; + char princ_name[256]; + + if (princ != NULL) + krb5_unparse_name_fixed (context->context, princ, + princ_name, sizeof(princ_name)); + + while(fgets(buf, sizeof(buf), f) != NULL){ char *foo = NULL, *p; + krb5_principal this_princ; + p = strtok_r(buf, " \t\n", &foo); if(p == NULL) continue; - ret = krb5_parse_name(context->context, p, &princ); + ret = krb5_parse_name(context->context, p, &this_princ); if(ret) continue; if(!krb5_principal_compare(context->context, - context->caller, princ)){ - krb5_free_principal(context->context, princ); + context->caller, this_princ)) { + krb5_free_principal(context->context, this_princ); continue; } - krb5_free_principal(context->context, princ); - p = strtok_r(NULL, "\n", &foo); + krb5_free_principal(context->context, this_princ); + p = strtok_r(NULL, " \t\n", &foo); if(p == NULL) continue; ret = _kadm5_string_to_privs(p, &flags); - break; + if (ret) + break; + p = strtok_r(NULL, "\n", &foo); + if (p == NULL) { + if (princ == NULL) { + ret = 0; + break; + } else { + continue; + } + } + if(princ != NULL + && fnmatch (p, princ_name, FNM_PATHNAME) == 0) { + ret = _kadm5_string_to_privs(p, &flags); + break; + } } fclose(f); } if(flags == -1) flags = 0; - context->acl_flags = flags; - return 0; + if (ret == 0) + *ret_flags = flags; + return ret; } +/* + * set global acl flags in `context' for the current caller. + * return 0 on success or an error + */ + kadm5_ret_t -_kadm5_acl_check_permission(kadm5_server_context *context, unsigned op) +_kadm5_acl_init(kadm5_server_context *context) { - unsigned res = ~context->acl_flags & op; + krb5_principal princ; + krb5_error_code ret; + + ret = krb5_parse_name(context->context, KADM5_ADMIN_SERVICE, &princ); + if (ret) + return ret; + ret = krb5_principal_compare(context->context, context->caller, princ); + krb5_free_principal(context->context, princ); + if(ret != 0) { + context->acl_flags = KADM5_PRIV_ALL; + return 0; + } + + return fetch_acl (context, NULL, &context->acl_flags); +} + +/* + * check if `flags' allows `op' + * return 0 if OK or an error + */ + +static kadm5_ret_t +check_flags (unsigned op, + unsigned flags) +{ + unsigned res = ~flags & op; + if(res & KADM5_PRIV_GET) return KADM5_AUTH_GET; if(res & KADM5_PRIV_ADD) @@ -136,3 +188,26 @@ _kadm5_acl_check_permission(kadm5_server_context *context, unsigned op) return KADM5_AUTH_INSUFFICIENT; return 0; } + +/* + * return 0 if the current caller in `context' is allowed to perform + * `op' on `princ' and otherwise an error + * princ == NULL if it's not relevant. + */ + +kadm5_ret_t +_kadm5_acl_check_permission(kadm5_server_context *context, + unsigned op, + krb5_const_principal princ) +{ + kadm5_ret_t ret; + unsigned princ_flags; + + ret = check_flags (op, context->acl_flags); + if (ret == 0) + return ret; + ret = fetch_acl (context, princ, &princ_flags); + if (ret) + return ret; + return check_flags (op, princ_flags); +}