krb5 commit: Modernize auth_acl.c

Greg Hudson ghudson at mit.edu
Mon Jul 3 00:21:14 EDT 2017


https://github.com/krb5/krb5/commit/0def80f767b9a2cdfbc19d3a61433d1edd7a7998
commit 0def80f767b9a2cdfbc19d3a61433d1edd7a7998
Author: Greg Hudson <ghudson at mit.edu>
Date:   Wed Jun 21 10:38:41 2017 -0400

    Modernize auth_acl.c
    
    Change auth_acl.c to match current coding conventions.  Use more
    consistent identifier names, and drop the kadm5int_ prefix as the code
    is now part of kadmind.  Remove the acl_inited, acl_debug_level, and
    acl_catchall_entry variables.  Move global state into a structure, to
    make it easier to migrate to a module handle later.  Move
    parse_restrictions() above parse_line() so it can later be used from
    parse_line() without a forward declaration.  Rewrite get_line() and
    parse_line() to avoid the use of fixed-sized static buffers and
    sscanf().  Add a parse_entry() helper to make memory management in
    parse_line() easier.  Add a free_acl_entry() helper (split out from
    free_acl_entries()) to make error handling in parse_entry() easier.
    Add a match_princ() helper to simplify find_entry().
    
    Remove the GSS name translation wrapper in auth_acl.c.  In the server
    stubs, use handle->current_caller for the client principal.  In the
    iprop RPCs(), add a wrapper to parse the client display name before
    calling acl_check().

 src/kadmin/server/auth_acl.c     | 1154 ++++++++++++++++----------------------
 src/kadmin/server/auth_acl.h     |   66 +--
 src/kadmin/server/deps           |   37 +-
 src/kadmin/server/ipropd_svc.c   |   25 +-
 src/kadmin/server/misc.c         |    3 +-
 src/kadmin/server/ovsec_kadmd.c  |    4 +-
 src/kadmin/server/server_stubs.c |  137 ++---
 7 files changed, 596 insertions(+), 830 deletions(-)

diff --git a/src/kadmin/server/auth_acl.c b/src/kadmin/server/auth_acl.c
index ea89af0..e0c18f6 100644
--- a/src/kadmin/server/auth_acl.c
+++ b/src/kadmin/server/auth_acl.c
@@ -1,8 +1,8 @@
 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /* kadmin/server/auth_acl.c */
 /*
- * Copyright 1995-2004, 2007, 2008 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
+ * Copyright 1995-2004, 2007, 2008, 2017 by the Massachusetts Institute of
+ * Technology.  All Rights Reserved.
  *
  * Export of this software from the United States of America may
  *   require a specific license from the United States Government.
@@ -26,243 +26,119 @@
 
 #include "k5-int.h"
 #include <syslog.h>
-#include <sys/param.h>
-#include <gssapi/gssapi_generic.h>
-#include <kadm5/server_internal.h>
 #include <kadm5/admin.h>
 #include "adm_proto.h"
 #include "auth_acl.h"
 #include <ctype.h>
 
-typedef struct _acl_op_table {
-    char        ao_op;
-    krb5_int32  ao_mask;
-} aop_t;
-
-typedef struct _acl_entry {
-    struct _acl_entry   *ae_next;
-    char                *ae_name;
-    krb5_boolean        ae_name_bad;
-    krb5_principal      ae_principal;
-    krb5_int32          ae_op_allowed;
-    char                *ae_target;
-    krb5_boolean        ae_target_bad;
-    krb5_principal      ae_target_princ;
-    char                *ae_restriction_string;
-    /* eg: "-maxlife 3h -service +proxiable" */
-    krb5_boolean        ae_restriction_bad;
-    restriction_t       *ae_restrictions;
-} aent_t;
-
-static const aop_t acl_op_table[] = {
-    { 'a',      ACL_ADD },
-    { 'd',      ACL_DELETE },
-    { 'm',      ACL_MODIFY },
-    { 'c',      ACL_CHANGEPW },
-    { 'i',      ACL_INQUIRE },
-    { 'l',      ACL_LIST },
-    { 'p',      ACL_IPROP },
-    { 's',      ACL_SETKEY },
-    { 'x',      ACL_ALL_MASK },
-    { '*',      ACL_ALL_MASK },
-    { 'e',      ACL_EXTRACT },
-    { '\0',     0 }
+struct acl_op_table {
+    char op;
+    uint32_t mask;
 };
 
-typedef struct _wildstate {
+struct acl_entry {
+    struct acl_entry *next;
+    char *client_string;
+    krb5_boolean client_bad;
+    krb5_principal client;
+    uint32_t op_allowed;
+    char *target_string;
+    krb5_boolean target_bad;
+    krb5_principal target;
+    char *rs_string;
+    krb5_boolean rs_bad;
+    struct kadm5_auth_restrictions *rs;
+};
+
+static const struct acl_op_table acl_op_table[] = {
+    { 'a', ACL_ADD },
+    { 'd', ACL_DELETE },
+    { 'm', ACL_MODIFY },
+    { 'c', ACL_CHANGEPW },
+    { 'i', ACL_INQUIRE },
+    { 'l', ACL_LIST },
+    { 'p', ACL_IPROP },
+    { 's', ACL_SETKEY },
+    { 'x', ACL_ALL_MASK },
+    { '*', ACL_ALL_MASK },
+    { 'e', ACL_EXTRACT },
+    { '\0', 0 }
+};
+
+struct wildstate {
     int nwild;
     const krb5_data *backref[9];
-} wildstate_t;
-
-static aent_t   *acl_list_head = (aent_t *) NULL;
-static aent_t   *acl_list_tail = (aent_t *) NULL;
+};
 
-static const char *acl_acl_file = (char *) NULL;
-static int acl_inited = 0;
-static int acl_debug_level = 0;
-/*
- * This is the catchall entry.  If nothing else appropriate is found, or in
- * the case where the ACL file is not present, this entry controls what can
- * be done.
- */
-static const char *acl_catchall_entry = NULL;
+struct acl_state {
+    struct acl_entry *list;
+    const char *fname;
+};
 
-static const char *acl_line2long_msg = N_("%s: line %d too long, truncated");
-static const char *acl_op_bad_msg = N_("Unrecognized ACL operation '%c' in "
-                                       "%s");
-static const char *acl_syn_err_msg = N_("%s: syntax error at line %d "
-                                        "<%.10s...>");
-static const char *acl_cantopen_msg = N_("%s while opening ACL file %s");
+static struct acl_state aclstate;
 
 /*
- * kadm5int_acl_get_line() - Get a line from the ACL file.
- *                      Lines ending with \ are continued on the next line
+ * Get a line from the ACL file.  Lines ending with \ are continued on the next
+ * line.  The caller should set *lineno to 1 and *incr to 0 before the first
+ * call.  On successful return, *lineno will be the line number of the line
+ * read.  Return a pointer to the line on success, or NULL on end of file or
+ * read failure.
  */
 static char *
-kadm5int_acl_get_line(fp, lnp)
-    FILE        *fp;
-    int         *lnp;           /* caller should set to 1 before first call */
+get_line(FILE *fp, const char *fname, int *lineno, int *incr)
 {
-    int         i, domore;
-    static int  line_incr = 0;
-    static char acl_buf[BUFSIZ];
-
-    for (domore = 1; domore && !feof(fp); ) {
-        *lnp += line_incr;
-        line_incr = 0;
-        /* Copy in the line, with continuations */
-        for (i = 0; ((i < BUFSIZ) && !feof(fp)); i++) {
-            int byte;
-            byte = fgetc(fp);
-            acl_buf[i] = byte;
-            if (byte == EOF) {
-                if (i > 0 && acl_buf[i-1] == '\\')
-                    i--;
-                break;          /* it gets nulled-out below */
-            }
-            else if (acl_buf[i] == '\n') {
-                if (i == 0 || acl_buf[i-1] != '\\')
-                    break;      /* empty line or normal end of line */
-                else {
-                    i -= 2;     /* back up over "\\\n" and continue */
-                    line_incr++;
-                }
-            }
-        }
-        /* Check if we exceeded our buffer size */
-        if (i == sizeof acl_buf && (i--, !feof(fp))) {
-            int c1 = acl_buf[i], c2;
-
-            krb5_klog_syslog(LOG_ERR, _(acl_line2long_msg), acl_acl_file,
-                             *lnp);
-            while ((c2 = fgetc(fp)) != EOF) {
-                if (c2 == '\n') {
-                    if (c1 != '\\')
-                        break;
-                    line_incr++;
-                }
-                c1 = c2;
-            }
+    const int chunksize = 128;
+    struct k5buf buf;
+    size_t old_len;
+    char *p;
+
+    /* Increment *lineno by the number of newlines from the last line. */
+    *lineno += *incr;
+    *incr = 0;
+
+    k5_buf_init_dynamic(&buf);
+    for (;;) {
+        /* Read at least part of a line into the buffer. */
+        old_len = buf.len;
+        p = k5_buf_get_space(&buf, chunksize);
+        if (p == NULL)
+            return NULL;
+
+        if (fgets(p, chunksize, fp) == NULL) {
+            /* We reached the end.  Return a final unterminated line, if there
+             * is one and it's not a comment. */
+            k5_buf_truncate(&buf, old_len);
+            if (buf.len > 0 && *(char *)buf.data != '#')
+                return buf.data;
+            k5_buf_free(&buf);
+            return NULL;
         }
-        acl_buf[i] = '\0';
-        if (acl_buf[0] == (char) EOF)   /* ptooey */
-            acl_buf[0] = '\0';
-        else
-            line_incr++;
-        if ((acl_buf[0] != '#') && (acl_buf[0] != '\0'))
-            domore = 0;
-    }
-    if (domore || (strlen(acl_buf) == 0))
-        return((char *) NULL);
-    else
-        return(acl_buf);
-}
-
-/*
- * kadm5int_acl_parse_line() - Parse the contents of an ACL line.
- */
-static aent_t *
-kadm5int_acl_parse_line(lp)
-    const char *lp;
-{
-    static char acle_principal[BUFSIZ];
-    static char acle_ops[BUFSIZ];
-    static char acle_object[BUFSIZ];
-    static char acle_restrictions[BUFSIZ];
-    aent_t      *acle;
-    char        *op;
-    int         t, found, opok, nmatch;
-
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("* kadm5int_acl_parse_line(line=%20s)\n", lp));
-    /*
-     * Format is still simple:
-     *  entry ::= [<whitespace>] <principal> <whitespace> <opstring>
-     *            [<whitespace> <target> [<whitespace> <restrictions>
-     *                                    [<whitespace>]]]
-     */
-    acle = (aent_t *) NULL;
-    acle_object[0] = '\0';
-    nmatch = sscanf(lp, "%s %s %s %[^\n]", acle_principal, acle_ops,
-                    acle_object, acle_restrictions);
-    if (nmatch >= 2) {
-        acle = (aent_t *) malloc(sizeof(aent_t));
-        if (acle) {
-            acle->ae_next = (aent_t *) NULL;
-            acle->ae_op_allowed = (krb5_int32) 0;
-            acle->ae_target =
-                (nmatch >= 3) ? strdup(acle_object) : (char *) NULL;
-            acle->ae_target_bad = 0;
-            acle->ae_target_princ = (krb5_principal) NULL;
-            opok = 1;
-            for (op=acle_ops; *op; op++) {
-                char rop;
-
-                rop = (isupper((unsigned char) *op)) ? tolower((unsigned char) *op) : *op;
-                found = 0;
-                for (t=0; acl_op_table[t].ao_op; t++) {
-                    if (rop == acl_op_table[t].ao_op) {
-                        found = 1;
-                        if (rop == *op)
-                            acle->ae_op_allowed |= acl_op_table[t].ao_mask;
-                        else
-                            acle->ae_op_allowed &= ~acl_op_table[t].ao_mask;
-                    }
-                }
-                if (!found) {
-                    krb5_klog_syslog(LOG_ERR, _(acl_op_bad_msg), *op, lp);
-                    opok = 0;
-                }
-            }
-            if (opok) {
-                acle->ae_name = strdup(acle_principal);
-                if (acle->ae_name) {
-                    acle->ae_principal = (krb5_principal) NULL;
-                    acle->ae_name_bad = 0;
-                    DPRINT(DEBUG_ACL, acl_debug_level,
-                           ("A ACL entry %s -> opmask %x\n",
-                            acle->ae_name, acle->ae_op_allowed));
-                }
-                else {
-                    if (acle->ae_target)
-                        free(acle->ae_target);
-                    free(acle);
-                    acle = (aent_t *) NULL;
-                }
-            }
-            else {
-                if (acle->ae_target)
-                    free(acle->ae_target);
-                free(acle);
-                acle = (aent_t *) NULL;
-            }
 
-            if (acle) {
-                if ( nmatch >= 4 ) {
-                    char        *trailing;
-
-                    trailing = &acle_restrictions[strlen(acle_restrictions)-1];
-                    while ( isspace((int) *trailing) )
-                        trailing--;
-                    trailing[1] = '\0';
-                    acle->ae_restriction_string =
-                        strdup(acle_restrictions);
-                }
-                else {
-                    acle->ae_restriction_string = (char *) NULL;
-                }
-                acle->ae_restriction_bad = 0;
-                acle->ae_restrictions = (restriction_t *) NULL;
+        /* Set the buffer length based on the actual amount read. */
+        k5_buf_truncate(&buf, old_len + strlen(p));
+
+        p = buf.data;
+        if (buf.len > 0 && p[buf.len - 1] == '\n') {
+            /* We have a complete raw line in the buffer. */
+            (*incr)++;
+            k5_buf_truncate(&buf, buf.len - 1);
+            if (buf.len > 0 && p[buf.len - 1] == '\\') {
+                /* This line has a continuation marker; keep reading. */
+                k5_buf_truncate(&buf, buf.len - 1);
+            } else if (buf.len == 0 || *p == '#') {
+                /* This line is empty or a comment.  Start over. */
+                *lineno += *incr;
+                *incr = 0;
+                k5_buf_truncate(&buf, 0);
+            } else {
+                return buf.data;
             }
         }
     }
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("X kadm5int_acl_parse_line() = %x\n", (long) acle));
-    return(acle);
 }
 
 /*
- * kadm5int_acl_parse_restrictions() - Parse optional restrictions field
+ * Parse a restrictions field.  Return NULL on failure.
  *
  * Allowed restrictions are:
  *      [+-]flagname            (recognized by krb5_flagspec_to_mask)
@@ -272,539 +148,477 @@ kadm5int_acl_parse_line(lp)
  *      -{expire,pwexpire,maxlife,maxrenewlife} deltat
  *                              associated value will be forced to
  *                              MIN(deltat, requested value)
- *
- * Returns: 0 on success, or system errors
  */
-static krb5_error_code
-kadm5int_acl_parse_restrictions(s, rpp)
-    char                *s;
-    restriction_t       **rpp;
+static struct kadm5_auth_restrictions *
+parse_restrictions(const char *str, const char *fname)
 {
-    char                *sp = NULL, *tp, *ap, *save;
-    static const char   *delims = "\t\n\f\v\r ,";
-    krb5_deltat         dt;
-    krb5_error_code     code;
-
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("* kadm5int_acl_parse_restrictions(s=%20s, rpp=0x%08x)\n", s, (long)rpp));
-
-    *rpp = (restriction_t *) NULL;
-    code = 0;
-    if (s) {
-        if (!(sp = strdup(s))   /* Don't munge the original */
-            || !(*rpp = (restriction_t *) malloc(sizeof(restriction_t)))) {
-            code = ENOMEM;
+    char *copy = NULL, *token, *arg, *save;
+    const char *delims = "\t\n\f\v\r ,";
+    krb5_deltat delta;
+    struct kadm5_auth_restrictions *rs;
+
+    copy = strdup(str);
+    if (copy == NULL)
+        return NULL;
+
+    rs = calloc(1, sizeof(*rs));
+    if (rs == NULL) {
+        free(copy);
+        return NULL;
+    }
+
+    rs->forbid_attrs = ~(krb5_flags)0;
+    for (token = strtok_r(copy, delims, &save); token != NULL;
+         token = strtok_r(NULL, delims, &save)) {
+
+        if (krb5_flagspec_to_mask(token, &rs->require_attrs,
+                                  &rs->forbid_attrs) == 0) {
+            rs->mask |= KADM5_ATTRIBUTES;
+            continue;
+        }
+
+        if (strcmp(token, "-clearpolicy") == 0) {
+            rs->mask |= KADM5_POLICY_CLR;
+            continue;
+        }
+
+        /* Everything else needs an argument. */
+        arg = strtok_r(NULL, delims, &save);
+        if (arg == NULL)
+            goto error;
+
+        if (strcmp(token, "-policy") == 0) {
+            if (rs->policy != NULL)
+                goto error;
+            rs->policy = strdup(arg);
+            if (rs->policy == NULL)
+                goto error;
+            rs->mask |= KADM5_POLICY;
+            continue;
+        }
+
+        /* All other arguments must be a deltat. */
+        if (krb5_string_to_deltat(arg, &delta) != 0)
+            goto error;
+
+        if (strcmp(token, "-expire") == 0) {
+            rs->princ_lifetime = delta;
+            rs->mask |= KADM5_PRINC_EXPIRE_TIME;
+        } else if (strcmp(token, "-pwexpire") == 0) {
+            rs->pw_lifetime = delta;
+            rs->mask |= KADM5_PW_EXPIRATION;
+        } else if (strcmp(token, "-maxlife") == 0) {
+            rs->max_life = delta;
+            rs->mask |= KADM5_MAX_LIFE;
+        } else if (strcmp(token, "-maxrenewlife") == 0) {
+            rs->max_renewable_life = delta;
+            rs->mask |= KADM5_MAX_RLIFE;
         } else {
-            memset(*rpp, 0, sizeof(**rpp));
-            (*rpp)->forbid_attrs = ~(krb5_flags)0;
-            for (tp = strtok_r(sp, delims, &save); tp;
-                 tp = strtok_r(NULL, delims, &save)) {
-                if (!krb5_flagspec_to_mask(tp, &(*rpp)->require_attrs,
-                                           &(*rpp)->forbid_attrs)) {
-                    (*rpp)->mask |= KADM5_ATTRIBUTES;
-                } else if (!strcmp(tp, "-clearpolicy")) {
-                    (*rpp)->mask |= KADM5_POLICY_CLR;
-                } else {
-                    /* everything else needs an argument ... */
-                    if (!(ap = strtok_r(NULL, delims, &save))) {
-                        code = EINVAL;
-                        break;
-                    }
-                    if (!strcmp(tp, "-policy")) {
-                        if (!((*rpp)->policy = strdup(ap))) {
-                            code = ENOMEM;
-                            break;
-                        }
-                        (*rpp)->mask |= KADM5_POLICY;
-                    } else {
-                        /* all other arguments must be a deltat ... */
-                        if (krb5_string_to_deltat(ap, &dt)) {
-                            code = EINVAL;
-                            break;
-                        }
-                        if (!strcmp(tp, "-expire")) {
-                            (*rpp)->princ_lifetime = dt;
-                            (*rpp)->mask |= KADM5_PRINC_EXPIRE_TIME;
-                        } else if (!strcmp(tp, "-pwexpire")) {
-                            (*rpp)->pw_lifetime = dt;
-                            (*rpp)->mask |= KADM5_PW_EXPIRATION;
-                        } else if (!strcmp(tp, "-maxlife")) {
-                            (*rpp)->max_life = dt;
-                            (*rpp)->mask |= KADM5_MAX_LIFE;
-                        } else if (!strcmp(tp, "-maxrenewlife")) {
-                            (*rpp)->max_renewable_life = dt;
-                            (*rpp)->mask |= KADM5_MAX_RLIFE;
-                        } else {
-                            code = EINVAL;
-                            break;
-                        }
-                    }
-                }
-            }
-            if (code) {
-                krb5_klog_syslog(LOG_ERR, _("%s: invalid restrictions: %s"),
-                                 acl_acl_file, s);
+            goto error;
+        }
+    }
+
+    free(copy);
+    return rs;
+
+error:
+    krb5_klog_syslog(LOG_ERR, _("%s: invalid restrictions: %s"), fname, str);
+    free(copy);
+    free(rs->policy);
+    free(rs);
+    return NULL;
+}
+
+static void
+free_acl_entry(struct acl_entry *entry)
+{
+    free(entry->client_string);
+    krb5_free_principal(NULL, entry->client);
+    free(entry->target_string);
+    krb5_free_principal(NULL, entry->target);
+    free(entry->rs_string);
+    if (entry->rs != NULL) {
+        free(entry->rs->policy);
+        free(entry->rs);
+    }
+    free(entry);
+}
+
+/* Parse the four fields of an ACL entry and return a structure representing
+ * it.  Log a message and return NULL on error. */
+static struct acl_entry *
+parse_entry(const char *client, const char *ops, const char *target,
+            const char *rs, const char *line, const char *fname)
+{
+    struct acl_entry *entry;
+    const char *op;
+    char rop;
+    int t;
+
+    entry = calloc(1, sizeof(*entry));
+    if (entry == NULL)
+        return NULL;
+
+    for (op = ops; *op; op++) {
+        rop = isupper((unsigned char)*op) ? tolower((unsigned char)*op) : *op;
+        for (t = 0; acl_op_table[t].op; t++) {
+            if (rop == acl_op_table[t].op) {
+                if (rop == *op)
+                    entry->op_allowed |= acl_op_table[t].mask;
+                else
+                    entry->op_allowed &= ~acl_op_table[t].mask;
+                break;
             }
         }
+        if (!acl_op_table[t].op) {
+            krb5_klog_syslog(LOG_ERR,
+                             _("Unrecognized ACL operation '%c' in %s"),
+                             *op, line);
+            goto error;
+        }
+    }
+
+    entry->client_string = strdup(client);
+    if (entry->client_string == NULL)
+        goto error;
+    if (target != NULL) {
+        entry->target_string = strdup(target);
+        if (entry->target_string == NULL)
+            goto error;
     }
-    if (sp)
-        free(sp);
-    if (*rpp && code) {
-        if ((*rpp)->policy)
-            free((*rpp)->policy);
-        free(*rpp);
-        *rpp = (restriction_t *) NULL;
+    if (rs != NULL) {
+        entry->rs_string = strdup(rs);
+        if (entry->rs_string == NULL)
+            goto error;
     }
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("X kadm5int_acl_parse_restrictions() = %d, mask=0x%08x\n",
-            code, (*rpp) ? (*rpp)->mask : 0));
-    return code;
+
+    return entry;
+
+error:
+    free_acl_entry(entry);
+    return NULL;
 }
 
-/*
- * kadm5int_acl_impose_restrictions()   - impose restrictions, modifying *recp, *maskp
- *
- * Returns: 0 on success;
- *          malloc or timeofday errors
- */
+/* Parse the contents of an ACL line. */
+static struct acl_entry *
+parse_line(const char *line, const char *fname)
+{
+    struct acl_entry *entry = NULL;
+    char *copy;
+    char *client, *client_end, *ops, *ops_end, *target, *target_end, *rs, *end;
+    const char *ws = "\t\n\f\v\r ,";
+
+    /*
+     * Format:
+     *  entry ::= [<whitespace>] <principal> <whitespace> <opstring>
+     *            [<whitespace> <target> [<whitespace> <restrictions>
+     *                                    [<whitespace>]]]
+     */
+
+    /* Make a copy and remove any trailing whitespace. */
+    copy = strdup(line);
+    if (copy == NULL)
+        return NULL;
+    end = copy + strlen(copy);
+    while (end > copy && isspace(end[-1]))
+        *--end = '\0';
+
+    /* Find the beginning and end of each field.  The end of restrictions is
+     * the end of copy. */
+    client = copy + strspn(copy, ws);
+    client_end = client + strcspn(client, ws);
+    ops = client_end + strspn(client_end, ws);
+    ops_end = ops + strcspn(ops, ws);
+    target = ops_end + strspn(ops_end, ws);
+    target_end = target + strcspn(target, ws);
+    rs = target_end + strspn(target_end, ws);
+
+    /* Terminate the first three fields. */
+    *client_end = *ops_end = *target_end = '\0';
+
+    /* The last two fields are optional; represent them as NULL if not present.
+     * The first two fields are required. */
+    if (*target == '\0')
+        target = NULL;
+    if (*rs == '\0')
+        rs = NULL;
+    if (*client != '\0' && *ops != '\0')
+        entry = parse_entry(client, ops, target, rs, line, fname);
+    free(copy);
+    return entry;
+}
+
+/* Impose restrictions, modifying *rec and *mask. */
 krb5_error_code
-kadm5int_acl_impose_restrictions(kcontext, recp, maskp, rp)
-    krb5_context               kcontext;
-    kadm5_principal_ent_rec    *recp;
-    long                       *maskp;
-    restriction_t              *rp;
+acl_impose_restrictions(krb5_context context, kadm5_principal_ent_rec *rec,
+                        long *mask, struct kadm5_auth_restrictions *rs)
 {
-    krb5_error_code     code;
-    krb5_timestamp      now;
+    krb5_error_code ret;
+    krb5_timestamp now;
 
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("* kadm5int_acl_impose_restrictions(..., *maskp=0x%08x, rp=0x%08x)\n",
-            *maskp, (long)rp));
-    if (!rp)
+    if (rs == NULL)
         return 0;
-    if (rp->mask & (KADM5_PRINC_EXPIRE_TIME|KADM5_PW_EXPIRATION))
-        if ((code = krb5_timeofday(kcontext, &now)))
-            return code;
-
-    if (rp->mask & KADM5_ATTRIBUTES) {
-        recp->attributes |= rp->require_attrs;
-        recp->attributes &= rp->forbid_attrs;
-        *maskp |= KADM5_ATTRIBUTES;
+    if (rs->mask & (KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION)) {
+        ret = krb5_timeofday(context, &now);
+        if (ret)
+            return ret;
+    }
+
+    if (rs->mask & KADM5_ATTRIBUTES) {
+        rec->attributes |= rs->require_attrs;
+        rec->attributes &= rs->forbid_attrs;
+        *mask |= KADM5_ATTRIBUTES;
     }
-    if (rp->mask & KADM5_POLICY_CLR) {
-        *maskp &= ~KADM5_POLICY;
-        *maskp |= KADM5_POLICY_CLR;
-    } else if (rp->mask & KADM5_POLICY) {
-        if (recp->policy && strcmp(recp->policy, rp->policy)) {
-            free(recp->policy);
-            recp->policy = (char *) NULL;
+    if (rs->mask & KADM5_POLICY_CLR) {
+        *mask &= ~KADM5_POLICY;
+        *mask |= KADM5_POLICY_CLR;
+    } else if (rs->mask & KADM5_POLICY) {
+        if (rec->policy != NULL && strcmp(rec->policy, rs->policy) != 0) {
+            free(rec->policy);
+            rec->policy = NULL;
         }
-        if (!recp->policy) {
-            recp->policy = strdup(rp->policy);  /* XDR will free it */
-            if (!recp->policy)
+        if (rec->policy == NULL) {
+            rec->policy = strdup(rs->policy);  /* XDR will free it */
+            if (!rec->policy)
                 return ENOMEM;
         }
-        *maskp |= KADM5_POLICY;
+        *mask |= KADM5_POLICY;
     }
-    if (rp->mask & KADM5_PRINC_EXPIRE_TIME) {
-        if (!(*maskp & KADM5_PRINC_EXPIRE_TIME)
-            || ts_after(recp->princ_expire_time,
-                        ts_incr(now, rp->princ_lifetime)))
-            recp->princ_expire_time = now + rp->princ_lifetime;
-        *maskp |= KADM5_PRINC_EXPIRE_TIME;
+    if (rs->mask & KADM5_PRINC_EXPIRE_TIME) {
+        if (!(*mask & KADM5_PRINC_EXPIRE_TIME) ||
+            ts_after(rec->princ_expire_time, ts_incr(now, rs->princ_lifetime)))
+            rec->princ_expire_time = now + rs->princ_lifetime;
+        *mask |= KADM5_PRINC_EXPIRE_TIME;
     }
-    if (rp->mask & KADM5_PW_EXPIRATION) {
-        if (!(*maskp & KADM5_PW_EXPIRATION)
-            || ts_after(recp->pw_expiration, ts_incr(now, rp->pw_lifetime)))
-            recp->pw_expiration = now + rp->pw_lifetime;
-        *maskp |= KADM5_PW_EXPIRATION;
+    if (rs->mask & KADM5_PW_EXPIRATION) {
+        if (!(*mask & KADM5_PW_EXPIRATION) ||
+            ts_after(rec->pw_expiration, ts_incr(now, rs->pw_lifetime)))
+            rec->pw_expiration = now + rs->pw_lifetime;
+        *mask |= KADM5_PW_EXPIRATION;
     }
-    if (rp->mask & KADM5_MAX_LIFE) {
-        if (!(*maskp & KADM5_MAX_LIFE)
-            || (recp->max_life > rp->max_life))
-            recp->max_life = rp->max_life;
-        *maskp |= KADM5_MAX_LIFE;
+    if (rs->mask & KADM5_MAX_LIFE) {
+        if (!(*mask & KADM5_MAX_LIFE) || rec->max_life > rs->max_life)
+            rec->max_life = rs->max_life;
+        *mask |= KADM5_MAX_LIFE;
     }
-    if (rp->mask & KADM5_MAX_RLIFE) {
-        if (!(*maskp & KADM5_MAX_RLIFE)
-            || (recp->max_renewable_life > rp->max_renewable_life))
-            recp->max_renewable_life = rp->max_renewable_life;
-        *maskp |= KADM5_MAX_RLIFE;
+    if (rs->mask & KADM5_MAX_RLIFE) {
+        if (!(*mask & KADM5_MAX_RLIFE) ||
+            rec->max_renewable_life > rs->max_renewable_life)
+            rec->max_renewable_life = rs->max_renewable_life;
+        *mask |= KADM5_MAX_RLIFE;
     }
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("X kadm5int_acl_impose_restrictions() = 0, *maskp=0x%08x\n", *maskp));
     return 0;
 }
 
-/*
- * kadm5int_acl_free_entries() - Free all ACL entries.
- */
+/* Free all ACL entries. */
 static void
-kadm5int_acl_free_entries()
+free_acl_entries(struct acl_state *state)
 {
-    aent_t      *ap;
-    aent_t      *np;
-
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_free_entries()\n"));
-    for (ap=acl_list_head; ap; ap = np) {
-        if (ap->ae_name)
-            free(ap->ae_name);
-        if (ap->ae_principal)
-            krb5_free_principal((krb5_context) NULL, ap->ae_principal);
-        if (ap->ae_target)
-            free(ap->ae_target);
-        if (ap->ae_target_princ)
-            krb5_free_principal((krb5_context) NULL, ap->ae_target_princ);
-        if (ap->ae_restriction_string)
-            free(ap->ae_restriction_string);
-        if (ap->ae_restrictions) {
-            if (ap->ae_restrictions->policy)
-                free(ap->ae_restrictions->policy);
-            free(ap->ae_restrictions);
-        }
-        np = ap->ae_next;
-        free(ap);
+    struct acl_entry *entry, *next;
+
+    for (entry = state->list; entry != NULL; entry = next) {
+        next = entry->next;
+        free_acl_entry(entry);
     }
-    acl_list_head = acl_list_tail = (aent_t *) NULL;
-    acl_inited = 0;
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_free_entries()\n"));
+    state->list = NULL;
 }
 
-/*
- * kadm5int_acl_load_acl_file() - Open and parse the ACL file.
- */
-static int
-kadm5int_acl_load_acl_file()
+/* Open and parse the ACL file. */
+static void
+load_acl_file(const char *fname, struct acl_state *state)
 {
-    FILE        *afp;
-    char        *alinep;
-    aent_t      **aentpp;
-    int         alineno;
-    int         retval = 1;
-
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_load_acl_file()\n"));
-    /* Open the ACL file for read */
-    afp = fopen(acl_acl_file, "r");
-    if (afp) {
-        set_cloexec_file(afp);
-        alineno = 1;
-        aentpp = &acl_list_head;
-
-        /* Get a non-comment line */
-        while ((alinep = kadm5int_acl_get_line(afp, &alineno))) {
-            /* Parse it */
-            *aentpp = kadm5int_acl_parse_line(alinep);
-            /* If syntax error, then fall out */
-            if (!*aentpp) {
-                krb5_klog_syslog(LOG_ERR, _(acl_syn_err_msg),
-                                 acl_acl_file, alineno, alinep);
-                retval = 0;
-                break;
-            }
-            acl_list_tail = *aentpp;
-            aentpp = &(*aentpp)->ae_next;
-        }
-
-        fclose(afp);
-
-        if (acl_catchall_entry) {
-            *aentpp = kadm5int_acl_parse_line(acl_catchall_entry);
-            if (*aentpp) {
-                acl_list_tail = *aentpp;
-            }
-            else {
-                retval = 0;
-                DPRINT(DEBUG_OPERATION, acl_debug_level,
-                       ("> catchall acl entry (%s) load failed\n",
-                        acl_catchall_entry));
-            }
-        }
+    FILE *fp;
+    char *line;
+    struct acl_entry **entry_slot;
+    int lineno, incr;
+
+    state->list = NULL;
+
+    /* Open the ACL file for reading. */
+    fp = fopen(fname, "r");
+    if (fp == NULL) {
+        krb5_klog_syslog(LOG_ERR, _("%s while opening ACL file %s"),
+                         error_message(errno), fname);
+        return;
     }
-    else {
-        krb5_klog_syslog(LOG_ERR, _(acl_cantopen_msg),
-                         error_message(errno), acl_acl_file);
-        if (acl_catchall_entry &&
-            (acl_list_head = kadm5int_acl_parse_line(acl_catchall_entry))) {
-            acl_list_tail = acl_list_head;
-        }
-        else {
-            retval = 0;
-            DPRINT(DEBUG_OPERATION, acl_debug_level,
-                   ("> catchall acl entry (%s) load failed\n",
-                    acl_catchall_entry));
+
+    set_cloexec_file(fp);
+    lineno = 1;
+    incr = 0;
+    entry_slot = &state->list;
+
+    /* Get a non-comment line. */
+    while ((line = get_line(fp, fname, &lineno, &incr)) != NULL) {
+        /* Parse it.  Fail out on syntax error. */
+        *entry_slot = parse_line(line, fname);
+        if (*entry_slot == NULL) {
+            krb5_klog_syslog(LOG_ERR,
+                             _("%s: syntax error at line %d <%.10s...>"),
+                             fname, lineno, line);
+            free_acl_entries(state);
+            free(line);
+            fclose(fp);
+            return;
         }
+        entry_slot = &(*entry_slot)->next;
+        free(line);
     }
 
-    if (!retval) {
-        kadm5int_acl_free_entries();
-    }
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("X kadm5int_acl_load_acl_file() = %d\n", retval));
-    return(retval);
+    fclose(fp);
+    state->fname = fname;
 }
 
 /*
- * kadm5int_acl_match_data()    - See if two data entries match.
- *
- * Wildcarding is only supported for a whole component.
+ * See if two data entries match.  If e1 is a wildcard (matching a whole
+ * component only) and targetflag is false, save an alias to e2 into
+ * ws->backref.  If e1 is a back-reference and targetflag is true, compare the
+ * appropriate entry in ws->backref to e2.  If ws is NULL, do not store or
+ * match back-references.
  */
 static krb5_boolean
-kadm5int_acl_match_data(const krb5_data *e1, const krb5_data *e2,
-                        int targetflag, wildstate_t *ws)
+match_data(const krb5_data *e1, const krb5_data *e2, krb5_boolean targetflag,
+           struct wildstate *ws)
 {
-    krb5_boolean        retval;
-
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("* acl_match_entry(%s, %s)\n", e1->data, e2->data));
-    retval = 0;
-    if (!strncmp(e1->data, "*", e1->length)) {
-        retval = 1;
-        if (ws && !targetflag) {
-            if (ws->nwild >= 9) {
-                DPRINT(DEBUG_ACL, acl_debug_level,
-                       ("Too many wildcards in ACL entry.\n"));
-            }
-            else
+    int n;
+
+    if (data_eq_string(*e1, "*")) {
+        if (ws != NULL && !targetflag) {
+            if (ws->nwild < 9)
                 ws->backref[ws->nwild++] = e2;
         }
+        return TRUE;
     }
-    else if (ws && targetflag && (e1->length == 2) && (e1->data[0] == '*') &&
-             (e1->data[1] >= '1') && (e1->data[1] <= '9')) {
-        int     n = e1->data[1] - '1';
-        if (n >= ws->nwild) {
-            DPRINT(DEBUG_ACL, acl_debug_level,
-                   ("Too many backrefs in ACL entry.\n"));
-        }
-        else if ((ws->backref[n]->length == e2->length) &&
-                 (!strncmp(ws->backref[n]->data, e2->data, e2->length)))
-            retval = 1;
 
+    if (ws != NULL && targetflag && e1->length == 2 && e1->data[0] == '*' &&
+        e1->data[1] >= '1' && e1->data[1] <= '9') {
+        n = e1->data[1] - '1';
+        if (n >= ws->nwild)
+            return FALSE;
+        return data_eq(*e2, *ws->backref[n]);
+    } else {
+        return data_eq(*e2, *e1);
     }
-    else {
-        if ((e1->length == e2->length) &&
-            (!strncmp(e1->data, e2->data, e1->length)))
-            retval = 1;
+}
+
+/* Return true if p1 matches p2.  p1 may contain wildcards if targetflag is
+ * false, or backreferences if it is true. */
+static krb5_boolean
+match_princ(krb5_const_principal p1, krb5_const_principal p2,
+            krb5_boolean targetflag, struct wildstate *ws)
+{
+    int i;
+
+    /* The principals must be of the same length. */
+    if (p1->length != p2->length)
+        return FALSE;
+
+    /* The realm must match, and does not interact with wildcard state. */
+    if (!match_data(&p1->realm, &p2->realm, targetflag, NULL))
+        return FALSE;
+
+    /* All components of the principals must match. */
+    for (i = 0; i < p1->length; i++) {
+        if (!match_data(&p1->data[i], &p2->data[i], targetflag, ws))
+            return FALSE;
     }
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_match_entry()=%d\n",retval));
-    return(retval);
+
+    return TRUE;
 }
 
-/*
- * kadm5int_acl_find_entry()    - Find a matching entry.
- */
-static aent_t *
-kadm5int_acl_find_entry(krb5_context kcontext, krb5_const_principal principal,
-                        krb5_const_principal dest_princ)
+/* Find an ACL entry matching principal and target_principal.  Return NULL if
+ * none is found. */
+static struct acl_entry *
+find_entry(krb5_context context, struct acl_state *state,
+           krb5_const_principal client, krb5_const_principal target)
 {
-    aent_t              *entry;
-    krb5_error_code     kret;
-    int                 i;
-    int                 matchgood;
-    wildstate_t         state;
-
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_find_entry()\n"));
-    for (entry=acl_list_head; entry; entry = entry->ae_next) {
-        memset(&state, 0, sizeof(state));
-        if (entry->ae_name_bad)
+    struct acl_entry *entry;
+    krb5_error_code ret;
+    struct wildstate ws;
+
+    for (entry = state->list; entry != NULL; entry = entry->next) {
+        memset(&ws, 0, sizeof(ws));
+        if (entry->client_bad || entry->target_bad || entry->rs_bad)
             continue;
-        if (!strcmp(entry->ae_name, "*")) {
-            DPRINT(DEBUG_ACL, acl_debug_level, ("A wildcard ACL match\n"));
-            matchgood = 1;
-        }
-        else {
-            if (!entry->ae_principal && !entry->ae_name_bad) {
-                kret = krb5_parse_name(kcontext,
-                                       entry->ae_name,
-                                       &entry->ae_principal);
-                if (kret)
-                    entry->ae_name_bad = 1;
+
+        /* The client principal must match or be "*" in the entry. */
+        if (strcmp(entry->client_string, "*") != 0) {
+            if (entry->client == NULL) {
+                ret = krb5_parse_name(context, entry->client_string,
+                                      &entry->client);
+                if (ret) {
+                    entry->client_bad = TRUE;
+                    continue;
+                }
             }
-            if (entry->ae_name_bad) {
-                DPRINT(DEBUG_ACL, acl_debug_level,
-                       ("Bad ACL entry %s\n", entry->ae_name));
+            if (!match_princ(entry->client, client, FALSE, &ws))
                 continue;
-            }
-            matchgood = 0;
-            if (kadm5int_acl_match_data(&entry->ae_principal->realm,
-                                        &principal->realm, 0, (wildstate_t *)0) &&
-                (entry->ae_principal->length == principal->length)) {
-                matchgood = 1;
-                for (i=0; i<principal->length; i++) {
-                    if (!kadm5int_acl_match_data(&entry->ae_principal->data[i],
-                                                 &principal->data[i], 0, &state)) {
-                        matchgood = 0;
-                        break;
-                    }
+        }
+
+        /* The target principal must match if one is specified. */
+        if (entry->target_string != NULL &&
+            strcmp(entry->target_string, "*") != 0) {
+            if (entry->target == NULL) {
+                ret = krb5_parse_name(context, entry->target_string,
+                                      &entry->target);
+                if (ret) {
+                    entry->target_bad = TRUE;
+                    continue;
                 }
             }
+            if (target == NULL)
+                continue;
+            if (!match_princ(entry->target, target, TRUE, &ws))
+                continue;
         }
-        if (!matchgood)
-            continue;
 
-        /* We've matched the principal.  If we have a target, then try it */
-        if (entry->ae_target && strcmp(entry->ae_target, "*")) {
-            if (!entry->ae_target_princ && !entry->ae_target_bad) {
-                kret = krb5_parse_name(kcontext, entry->ae_target,
-                                       &entry->ae_target_princ);
-                if (kret)
-                    entry->ae_target_bad = 1;
-            }
-            if (entry->ae_target_bad) {
-                DPRINT(DEBUG_ACL, acl_debug_level,
-                       ("Bad target in ACL entry for %s\n", entry->ae_name));
-                entry->ae_name_bad = 1;
+        if (entry->rs_string != NULL && entry->rs == NULL) {
+            entry->rs = parse_restrictions(entry->rs_string, aclstate.fname);
+            if (entry->rs == NULL) {
+                entry->rs_bad = TRUE;
                 continue;
             }
-            if (!dest_princ)
-                matchgood = 0;
-            else if (entry->ae_target_princ && dest_princ) {
-                if (kadm5int_acl_match_data(&entry->ae_target_princ->realm,
-                                            &dest_princ->realm, 1, (wildstate_t *)0) &&
-                    (entry->ae_target_princ->length == dest_princ->length)) {
-                    for (i=0; i<dest_princ->length; i++) {
-                        if (!kadm5int_acl_match_data(&entry->ae_target_princ->data[i],
-                                                     &dest_princ->data[i], 1, &state)) {
-                            matchgood = 0;
-                            break;
-                        }
-                    }
-                }
-                else
-                    matchgood = 0;
-            }
         }
-        if (!matchgood)
-            continue;
 
-        if (entry->ae_restriction_string
-            && !entry->ae_restriction_bad
-            && !entry->ae_restrictions
-            && kadm5int_acl_parse_restrictions(entry->ae_restriction_string,
-                                               &entry->ae_restrictions)) {
-            DPRINT(DEBUG_ACL, acl_debug_level,
-                   ("Bad restrictions in ACL entry for %s\n", entry->ae_name));
-            entry->ae_restriction_bad = 1;
-        }
-        if (entry->ae_restriction_bad) {
-            entry->ae_name_bad = 1;
-            continue;
-        }
-        break;
+        return entry;
     }
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_find_entry()=%x\n",entry));
-    return(entry);
+
+    return NULL;
 }
 
-/*
- * kadm5int_acl_init()  - Initialize ACL context.
- */
+/* Initialize the ACL context. */
 krb5_error_code
-kadm5int_acl_init(kcontext, debug_level, acl_file)
-    krb5_context        kcontext;
-    int                 debug_level;
-    char                *acl_file;
+acl_init(krb5_context context, const char *acl_file)
 {
-    krb5_error_code     kret;
-
-    kret = 0;
-    acl_debug_level = debug_level;
-    DPRINT(DEBUG_CALLS, acl_debug_level,
-           ("* kadm5int_acl_init(afile=%s)\n",
-            ((acl_file) ? acl_file : "(null)")));
-    acl_acl_file = (acl_file) ? acl_file : (char *) KRB5_DEFAULT_ADMIN_ACL;
-    acl_inited = kadm5int_acl_load_acl_file();
-
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_init() = %d\n", kret));
-    return(kret);
+    load_acl_file(acl_file, &aclstate);
+    return 0;
 }
 
-/*
- * kadm5int_acl_finish  - Terminate ACL context.
- */
+/* Terminate the ACL context. */
 void
-kadm5int_acl_finish(kcontext, debug_level)
-    krb5_context        kcontext;
-    int                 debug_level;
+acl_finish(krb5_context context)
 {
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_finish()\n"));
-    kadm5int_acl_free_entries();
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_finish()\n"));
+    free_acl_entries(&aclstate);
 }
 
-/*
- * kadm5int_acl_check_krb()     - Is this operation permitted for this principal?
- */
+/* Return true if op is permitted for this principal.  Set *rs_out (if not
+ * NULL) according to any restrictions in the ACL entry. */
 krb5_boolean
-kadm5int_acl_check_krb(kcontext, caller_princ, opmask, principal, restrictions)
-    krb5_context         kcontext;
-    krb5_const_principal caller_princ;
-    krb5_int32           opmask;
-    krb5_const_principal principal;
-    restriction_t        **restrictions;
+acl_check(krb5_context context, krb5_const_principal client, uint32_t op,
+          krb5_const_principal target, struct kadm5_auth_restrictions **rs_out)
 {
-    krb5_boolean        retval;
-    aent_t              *aentry;
-
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_op_permitted()\n"));
-
-    retval = FALSE;
-
-    aentry = kadm5int_acl_find_entry(kcontext, caller_princ, principal);
-    if (aentry) {
-        if ((aentry->ae_op_allowed & opmask) == opmask) {
-            retval = TRUE;
-            if (restrictions) {
-                *restrictions =
-                    (aentry->ae_restrictions && aentry->ae_restrictions->mask)
-                    ? aentry->ae_restrictions
-                    : (restriction_t *) NULL;
-            }
-        }
-    }
+    struct acl_entry *entry;
 
-    DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_op_permitted()=%d\n",
-                                          retval));
-    return retval;
-}
+    if (rs_out != NULL)
+        *rs_out = NULL;
 
-/*
- * kadm5int_acl_check() - Is this operation permitted for this principal?
- *                      this code used not to be based on gssapi.  In order
- *                      to minimize porting hassles, I've put all the
- *                      gssapi hair in this function.  This might not be
- *                      the best medium-term solution.  (The best long-term
- *                      solution is, of course, a real authorization service.)
- */
-krb5_boolean
-kadm5int_acl_check(kcontext, caller, opmask, principal, restrictions)
-    krb5_context        kcontext;
-    gss_name_t          caller;
-    krb5_int32          opmask;
-    krb5_principal      principal;
-    restriction_t       **restrictions;
-{
-    krb5_boolean        retval;
-    gss_buffer_desc     caller_buf;
-    gss_OID             caller_oid;
-    OM_uint32           emin;
-    krb5_error_code     code;
-    krb5_principal      caller_princ;
-
-    if (GSS_ERROR(gss_display_name(&emin, caller, &caller_buf, &caller_oid)))
+    entry = find_entry(context, &aclstate, client, target);
+    if (entry == NULL)
         return FALSE;
-
-    code = krb5_parse_name(kcontext, (char *) caller_buf.value,
-                           &caller_princ);
-
-    gss_release_buffer(&emin, &caller_buf);
-
-    if (code != 0)
+    if (!(entry->op_allowed & op))
         return FALSE;
 
-    retval = kadm5int_acl_check_krb(kcontext, caller_princ,
-                                    opmask, principal, restrictions);
-
-    krb5_free_principal(kcontext, caller_princ);
+    if (rs_out != NULL && entry->rs != NULL && entry->rs->mask)
+        *rs_out = entry->rs;
 
-    return retval;
+    return TRUE;
 }
diff --git a/src/kadmin/server/auth_acl.h b/src/kadmin/server/auth_acl.h
index c1a45db..55a8662 100644
--- a/src/kadmin/server/auth_acl.h
+++ b/src/kadmin/server/auth_acl.h
@@ -28,24 +28,6 @@
 #define SERVER_ACL_H__
 
 /*
- * Debug definitions.
- */
-#define DEBUG_SPROC     1
-#define DEBUG_OPERATION 2
-#define DEBUG_HOST      4
-#define DEBUG_REALM     8
-#define DEBUG_REQUESTS  16
-#define DEBUG_ACL       32
-#define DEBUG_PROTO     64
-#define DEBUG_CALLS     128
-#define DEBUG_NOSLAVES  256
-#ifdef  DEBUG
-#define DPRINT(l1, cl, al)      if ((cl & l1) != 0) printf al
-#else   /* DEBUG */
-#define DPRINT(l1, cl, al)
-#endif  /* DEBUG */
-
-/*
  * Access control bits.
  */
 #define ACL_ADD                 1
@@ -58,7 +40,6 @@
 #define ACL_LIST                128
 #define ACL_SETKEY              256
 #define ACL_IPROP               512
-#define ACL_RENAME              (ACL_ADD+ACL_DELETE)
 
 #define ACL_ALL_MASK            (ACL_ADD        |       \
                                  ACL_DELETE     |       \
@@ -69,32 +50,25 @@
                                  ACL_IPROP      |       \
                                  ACL_SETKEY)
 
-typedef struct _restriction {
-    long                mask;
-    krb5_flags          require_attrs;
-    krb5_flags          forbid_attrs;
-    krb5_deltat         princ_lifetime;
-    krb5_deltat         pw_lifetime;
-    krb5_deltat         max_life;
-    krb5_deltat         max_renewable_life;
-    long                aux_attributes;
-    char                *policy;
-} restriction_t;
+struct kadm5_auth_restrictions {
+    long mask;
+    krb5_flags require_attrs;
+    krb5_flags forbid_attrs;
+    krb5_deltat princ_lifetime;
+    krb5_deltat pw_lifetime;
+    krb5_deltat max_life;
+    krb5_deltat max_renewable_life;
+    char *policy;
+};
+
+krb5_error_code acl_init(krb5_context context, const char *acl_file);
+void acl_finish(krb5_context);
+krb5_boolean acl_check(krb5_context context, krb5_const_principal client,
+                       uint32_t op, krb5_const_principal target,
+                       struct kadm5_auth_restrictions **rs_out);
+krb5_error_code acl_impose_restrictions(krb5_context context,
+                                        kadm5_principal_ent_rec *rec,
+                                        long *mask,
+                                        struct kadm5_auth_restrictions *rs);
 
-krb5_error_code kadm5int_acl_init(krb5_context, int, char *);
-void kadm5int_acl_finish(krb5_context, int);
-krb5_boolean kadm5int_acl_check(krb5_context,
-                                gss_name_t,
-                                krb5_int32,
-                                krb5_principal,
-                                restriction_t **);
-krb5_boolean kadm5int_acl_check_krb(krb5_context,
-                                    krb5_const_principal,
-                                    krb5_int32,
-                                    krb5_const_principal,
-                                    restriction_t **);
-krb5_error_code kadm5int_acl_impose_restrictions(krb5_context,
-                                                 kadm5_principal_ent_rec *,
-                                                 long *,
-                                                 restriction_t *);
 #endif  /* SERVER_ACL_H__ */
diff --git a/src/kadmin/server/deps b/src/kadmin/server/deps
index fce7ed3..e7cd3e6 100644
--- a/src/kadmin/server/deps
+++ b/src/kadmin/server/deps
@@ -2,25 +2,24 @@
 # Generated makefile dependencies follow.
 #
 $(OUTPRE)auth_acl.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
-  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \
-  $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
-  $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
-  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \
-  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
-  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \
-  $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \
-  $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \
-  $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \
-  $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \
-  $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \
-  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
-  $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
-  $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
-  $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
-  $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \
-  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
-  $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
-  $(top_srcdir)/include/socket-utils.h auth_acl.c auth_acl.h
+  $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+  $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+  $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \
+  $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \
+  $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \
+  $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \
+  $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \
+  $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \
+  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+  $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
+  $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+  auth_acl.c auth_acl.h
 $(OUTPRE)kadm_rpc_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
   $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \
   $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \
diff --git a/src/kadmin/server/ipropd_svc.c b/src/kadmin/server/ipropd_svc.c
index 503b797..c552ed0 100644
--- a/src/kadmin/server/ipropd_svc.c
+++ b/src/kadmin/server/ipropd_svc.c
@@ -129,6 +129,19 @@ buf_to_string(gss_buffer_desc *b)
     return s;
 }
 
+static krb5_boolean
+iprop_acl_check(krb5_context context, const char *client_name)
+{
+    krb5_principal client_princ;
+    krb5_boolean result;
+
+    if (krb5_parse_name(context, client_name, &client_princ) != 0)
+	return FALSE;
+    result = acl_check(context, client_princ, ACL_IPROP, NULL, NULL);
+    krb5_free_principal(context, client_princ);
+    return result;
+}
+
 kdb_incr_result_t *
 iprop_get_updates_1_svc(kdb_last_t *arg, struct svc_req *rqstp)
 {
@@ -174,11 +187,7 @@ iprop_get_updates_1_svc(kdb_last_t *arg, struct svc_req *rqstp)
     DPRINT("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n", whoami, client_name,
 	   service_name);
 
-    if (!kadm5int_acl_check(handle->context,
-			    rqst2name(rqstp),
-			    ACL_IPROP,
-			    NULL,
-			    NULL)) {
+    if (!iprop_acl_check(handle->context, client_name)) {
 	ret.ret = UPDATE_PERM_DENIED;
 
 	DPRINT("%s: PERMISSION DENIED: clprinc=`%s'\n\tsvcprinc=`%s'\n",
@@ -301,11 +310,7 @@ ipropx_resync(uint32_t vers, struct svc_req *rqstp)
     DPRINT("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
 	    whoami, client_name, service_name);
 
-    if (!kadm5int_acl_check(handle->context,
-			    rqst2name(rqstp),
-			    ACL_IPROP,
-			    NULL,
-			    NULL)) {
+    if (!iprop_acl_check(handle->context, client_name)) {
 	ret.ret = UPDATE_PERM_DENIED;
 
 	DPRINT("%s: Permission denied\n", whoami);
diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
index 685a0bb..1975af0 100644
--- a/src/kadmin/server/misc.c
+++ b/src/kadmin/server/misc.c
@@ -133,8 +133,7 @@ schpw_util_wrapper(void *server_handle,
         access_granted = FALSE;
 
     if (!access_granted &&
-        kadm5int_acl_check_krb(handle->context, client,
-                               ACL_CHANGEPW, target, NULL)) {
+        acl_check(handle->context, client, ACL_CHANGEPW, target, NULL)) {
         /*
          * Otherwise, principals with appropriate privileges can change
          * any password
diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c
index b9876b9..498c7cd 100644
--- a/src/kadmin/server/ovsec_kadmd.c
+++ b/src/kadmin/server/ovsec_kadmd.c
@@ -505,7 +505,7 @@ main(int argc, char *argv[])
     if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE)
         fail_to_start(0, _("Cannot initialize GSSAPI service name"));
 
-    ret = kadm5int_acl_init(context, 0, params.acl_file);
+    ret = acl_init(context, params.acl_file);
     if (ret)
         fail_to_start(ret, _("initializing ACL file"));
 
@@ -550,7 +550,7 @@ main(int argc, char *argv[])
     svcauth_gssapi_unset_names();
     kadm5_destroy(global_server_handle);
     loop_free(vctx);
-    kadm5int_acl_finish(context, 0);
+    acl_finish(context);
     (void)gss_release_name(&minor_status, &gss_changepw_name);
     (void)gss_release_name(&minor_status, &gss_oldchangepw_name);
     for (i = 0; i < 4; i++)
diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c
index be50efc..84b877a 100644
--- a/src/kadmin/server/server_stubs.c
+++ b/src/kadmin/server/server_stubs.c
@@ -320,6 +320,15 @@ stub_cleanup(kadm5_server_handle_t handle, char *princ_str,
     gss_release_buffer(&minor_stat, service_name);
 }
 
+static krb5_boolean
+stub_acl_check(kadm5_server_handle_t handle, uint32_t op,
+               krb5_const_principal target,
+               struct kadm5_auth_restrictions **rs_out)
+{
+    return acl_check(handle->context, handle->current_caller, op, target,
+                     rs_out);
+}
+
 static int
 log_unauth(
     char *op,
@@ -387,7 +396,7 @@ create_principal_2_svc(cprinc_arg *arg, generic_ret *ret,
     gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
     kadm5_server_handle_t       handle;
-    restriction_t               *rp;
+    struct kadm5_auth_restrictions *rp;
     const char                  *errmsg = NULL;
 
     ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
@@ -396,11 +405,9 @@ create_principal_2_svc(cprinc_arg *arg, generic_ret *ret,
     if (ret->code)
         goto exit_func;
 
-    if (CHANGEPW_SERVICE(rqstp)
-        || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_ADD,
-                               arg->rec.principal, &rp)
-        || kadm5int_acl_impose_restrictions(handle->context,
-                                            &arg->rec, &arg->mask, rp)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_ADD, arg->rec.principal, &rp) ||
+        acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) {
         ret->code = KADM5_AUTH_ADD;
         log_unauth("kadm5_create_principal", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -431,7 +438,7 @@ create_principal3_2_svc(cprinc3_arg *arg, generic_ret *ret,
     gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
     kadm5_server_handle_t       handle;
-    restriction_t               *rp;
+    struct kadm5_auth_restrictions *rp;
     const char                  *errmsg = NULL;
 
     ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
@@ -440,11 +447,9 @@ create_principal3_2_svc(cprinc3_arg *arg, generic_ret *ret,
     if (ret->code)
         goto exit_func;
 
-    if (CHANGEPW_SERVICE(rqstp)
-        || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_ADD,
-                               arg->rec.principal, &rp)
-        || kadm5int_acl_impose_restrictions(handle->context,
-                                            &arg->rec, &arg->mask, rp)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_ADD, arg->rec.principal, &rp) ||
+        acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) {
         ret->code = KADM5_AUTH_ADD;
         log_unauth("kadm5_create_principal", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -498,9 +503,8 @@ delete_principal_2_svc(dprinc_arg *arg, generic_ret *ret,
     if (ret->code)
         goto exit_func;
 
-    if (CHANGEPW_SERVICE(rqstp)
-        || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_DELETE,
-                               arg->princ, NULL)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_DELETE, arg->princ, NULL)) {
         ret->code = KADM5_AUTH_DELETE;
         log_unauth("kadm5_delete_principal", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -540,7 +544,7 @@ modify_principal_2_svc(mprinc_arg *arg, generic_ret *ret,
     gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
     kadm5_server_handle_t           handle;
-    restriction_t                   *rp;
+    struct kadm5_auth_restrictions *rp;
     const char                      *errmsg = NULL;
 
     ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
@@ -549,11 +553,9 @@ modify_principal_2_svc(mprinc_arg *arg, generic_ret *ret,
     if (ret->code)
         goto exit_func;
 
-    if (CHANGEPW_SERVICE(rqstp)
-        || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_MODIFY,
-                               arg->rec.principal, &rp)
-        || kadm5int_acl_impose_restrictions(handle->context,
-                                            &arg->rec, &arg->mask, rp)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_MODIFY, arg->rec.principal, &rp) ||
+        acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) {
         ret->code = KADM5_AUTH_MODIFY;
         log_unauth("kadm5_modify_principal", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -592,7 +594,7 @@ rename_principal_2_svc(rprinc_arg *arg, generic_ret *ret,
     gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
     kadm5_server_handle_t       handle;
-    restriction_t               *rp;
+    struct kadm5_auth_restrictions *rp;
     const char                  *errmsg = NULL;
     size_t                      tlen1, tlen2, clen, slen;
     char                        *tdots1, *tdots2, *cdots, *sdots;
@@ -619,12 +621,10 @@ rename_principal_2_svc(rprinc_arg *arg, generic_ret *ret,
 
     ret->code = KADM5_OK;
     if (! CHANGEPW_SERVICE(rqstp)) {
-        if (!kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                                ACL_DELETE, arg->src, NULL))
+        if (!stub_acl_check(handle, ACL_DELETE, arg->src, NULL))
             ret->code = KADM5_AUTH_DELETE;
         /* any restrictions at all on the ADD kills the RENAME */
-        if (!kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                                ACL_ADD, arg->dest, &rp) || rp) {
+        if (!stub_acl_check(handle, ACL_ADD, arg->dest, &rp) || rp != NULL) {
             if (ret->code == KADM5_AUTH_DELETE)
                 ret->code = KADM5_AUTH_INSUFFICIENT;
             else
@@ -697,11 +697,8 @@ get_principal_2_svc(gprinc_arg *arg, gprinc_ret *ret, struct svc_req *rqstp)
     funcname = "kadm5_get_principal";
 
     if (! cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) &&
-        (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
-                                                        rqst2name(rqstp),
-                                                        ACL_INQUIRE,
-                                                        arg->princ,
-                                                        NULL))) {
+        (CHANGEPW_SERVICE(rqstp) ||
+         !stub_acl_check(handle, ACL_INQUIRE, arg->princ, NULL))) {
         ret->code = KADM5_AUTH_GET;
         log_unauth(funcname, prime_arg,
                    &client_name, &service_name, rqstp);
@@ -743,11 +740,8 @@ get_princs_2_svc(gprincs_arg *arg, gprincs_ret *ret, struct svc_req *rqstp)
     if (prime_arg == NULL)
         prime_arg = "*";
 
-    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
-                                                       rqst2name(rqstp),
-                                                       ACL_LIST,
-                                                       NULL,
-                                                       NULL)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_LIST, NULL, NULL)) {
         ret->code = KADM5_AUTH_LIST;
         log_unauth("kadm5_get_principals", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -797,8 +791,7 @@ chpass_principal_2_svc(chpass_arg *arg, generic_ret *ret,
         ret->code = chpass_principal_wrapper_3(handle, arg->princ, FALSE, 0,
                                                NULL, arg->pass);
     } else if (!(CHANGEPW_SERVICE(rqstp)) &&
-               kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                                  ACL_CHANGEPW, arg->princ, NULL)) {
+               stub_acl_check(handle, ACL_CHANGEPW, arg->princ, NULL)) {
         ret->code = kadm5_chpass_principal(handle, arg->princ, arg->pass);
     } else {
         log_unauth("kadm5_chpass_principal", prime_arg,
@@ -850,8 +843,7 @@ chpass_principal3_2_svc(chpass3_arg *arg, generic_ret *ret,
                                                arg->keepold, arg->n_ks_tuple,
                                                arg->ks_tuple, arg->pass);
     } else if (!(CHANGEPW_SERVICE(rqstp)) &&
-               kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                                  ACL_CHANGEPW, arg->princ, NULL)) {
+               stub_acl_check(handle, ACL_CHANGEPW, arg->princ, NULL)) {
         ret->code = kadm5_chpass_principal_3(handle, arg->princ, arg->keepold,
                                              arg->n_ks_tuple, arg->ks_tuple,
                                              arg->pass);
@@ -901,8 +893,7 @@ setv4key_principal_2_svc(setv4key_arg *arg, generic_ret *ret,
             ret->code = KADM5_AUTH_SETKEY;
         }
     } else if (!(CHANGEPW_SERVICE(rqstp)) &&
-        kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                           ACL_SETKEY, arg->princ, NULL)) {
+               stub_acl_check(handle, ACL_SETKEY, arg->princ, NULL)) {
         ret->code = kadm5_setv4key_principal(handle, arg->princ,
                                              arg->keyblock);
     } else {
@@ -952,8 +943,7 @@ setkey_principal_2_svc(setkey_arg *arg, generic_ret *ret,
             ret->code = KADM5_AUTH_SETKEY;
         }
     } else if (!(CHANGEPW_SERVICE(rqstp)) &&
-        kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                           ACL_SETKEY, arg->princ, NULL)) {
+               stub_acl_check(handle, ACL_SETKEY, arg->princ, NULL)) {
         ret->code = kadm5_setkey_principal(handle, arg->princ, arg->keyblocks,
                                            arg->n_keys);
     } else {
@@ -1002,8 +992,7 @@ setkey_principal3_2_svc(setkey3_arg *arg, generic_ret *ret,
             ret->code = KADM5_AUTH_SETKEY;
         }
     } else if (!(CHANGEPW_SERVICE(rqstp)) &&
-        kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                           ACL_SETKEY, arg->princ, NULL)) {
+               stub_acl_check(handle, ACL_SETKEY, arg->princ, NULL)) {
         ret->code = kadm5_setkey_principal_3(handle, arg->princ, arg->keepold,
                                              arg->n_ks_tuple, arg->ks_tuple,
                                              arg->keyblocks, arg->n_keys);
@@ -1053,8 +1042,7 @@ setkey_principal4_2_svc(setkey4_arg *arg, generic_ret *ret,
             ret->code = KADM5_AUTH_SETKEY;
         }
     } else if (!(CHANGEPW_SERVICE(rqstp)) &&
-        kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                           ACL_SETKEY, arg->princ, NULL)) {
+               stub_acl_check(handle, ACL_SETKEY, arg->princ, NULL)) {
         ret->code = kadm5_setkey_principal_4(handle, arg->princ, arg->keepold,
                                              arg->key_data, arg->n_key_data);
     } else {
@@ -1123,8 +1111,7 @@ chrand_principal_2_svc(chrand_arg *arg, chrand_ret *ret, struct svc_req *rqstp)
         ret->code = randkey_principal_wrapper_3(handle, arg->princ, FALSE, 0,
                                                 NULL, &k, &nkeys);
     } else if (!(CHANGEPW_SERVICE(rqstp)) &&
-               kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                                  ACL_CHANGEPW, arg->princ, NULL)) {
+               stub_acl_check(handle, ACL_CHANGEPW, arg->princ, NULL)) {
         ret->code = kadm5_randkey_principal(handle, arg->princ, &k, &nkeys);
     } else {
         log_unauth(funcname, prime_arg,
@@ -1181,8 +1168,7 @@ chrand_principal3_2_svc(chrand3_arg *arg, chrand_ret *ret,
                                                 arg->keepold, arg->n_ks_tuple,
                                                 arg->ks_tuple, &k, &nkeys);
     } else if (!(CHANGEPW_SERVICE(rqstp)) &&
-               kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                                  ACL_CHANGEPW, arg->princ, NULL)) {
+               stub_acl_check(handle, ACL_CHANGEPW, arg->princ, NULL)) {
         ret->code = kadm5_randkey_principal_3(handle, arg->princ, arg->keepold,
                                               arg->n_ks_tuple, arg->ks_tuple,
                                               &k, &nkeys);
@@ -1233,9 +1219,8 @@ create_policy_2_svc(cpol_arg *arg, generic_ret *ret, struct svc_req *rqstp)
 
     prime_arg = arg->rec.policy;
 
-    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
-                                                       rqst2name(rqstp),
-                                                       ACL_ADD, NULL, NULL)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_ADD, NULL, NULL)) {
         ret->code = KADM5_AUTH_ADD;
         log_unauth("kadm5_create_policy", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -1275,9 +1260,8 @@ delete_policy_2_svc(dpol_arg *arg, generic_ret *ret, struct svc_req *rqstp)
 
     prime_arg = arg->name;
 
-    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
-                                                       rqst2name(rqstp),
-                                                       ACL_DELETE, NULL, NULL)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_DELETE, NULL, NULL)) {
         log_unauth("kadm5_delete_policy", prime_arg,
                    &client_name, &service_name, rqstp);
         ret->code = KADM5_AUTH_DELETE;
@@ -1316,9 +1300,8 @@ modify_policy_2_svc(mpol_arg *arg, generic_ret *ret, struct svc_req *rqstp)
 
     prime_arg = arg->rec.policy;
 
-    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
-                                                       rqst2name(rqstp),
-                                                       ACL_MODIFY, NULL, NULL)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_MODIFY, NULL, NULL)) {
         log_unauth("kadm5_modify_policy", prime_arg,
                    &client_name, &service_name, rqstp);
         ret->code = KADM5_AUTH_MODIFY;
@@ -1362,11 +1345,10 @@ get_policy_2_svc(gpol_arg *arg, gpol_ret *ret, struct svc_req *rqstp)
     prime_arg = arg->name;
 
     ret->code = KADM5_AUTH_GET;
-    if (!CHANGEPW_SERVICE(rqstp) && kadm5int_acl_check(handle->context,
-                                                       rqst2name(rqstp),
-                                                       ACL_INQUIRE, NULL, NULL))
+    if (!CHANGEPW_SERVICE(rqstp) &&
+        stub_acl_check(handle, ACL_INQUIRE, NULL, NULL)) {
         ret->code = KADM5_OK;
-    else {
+    } else {
         ret->code = kadm5_get_principal(handle->lhandle,
                                         handle->current_caller, &caller_ent,
                                         KADM5_PRINCIPAL_NORMAL_MASK);
@@ -1424,9 +1406,8 @@ get_pols_2_svc(gpols_arg *arg, gpols_ret *ret, struct svc_req *rqstp)
     if (prime_arg == NULL)
         prime_arg = "*";
 
-    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
-                                                       rqst2name(rqstp),
-                                                       ACL_LIST, NULL, NULL)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_LIST, NULL, NULL)) {
         ret->code = KADM5_AUTH_LIST;
         log_unauth("kadm5_get_policies", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -1495,9 +1476,8 @@ purgekeys_2_svc(purgekeys_arg *arg, generic_ret *ret, struct svc_req *rqstp)
     funcname = "kadm5_purgekeys";
 
     if (!cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) &&
-        (CHANGEPW_SERVICE(rqstp)
-         || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_MODIFY,
-                                arg->princ, NULL))) {
+        (CHANGEPW_SERVICE(rqstp) ||
+         !stub_acl_check(handle, ACL_MODIFY, arg->princ, NULL))) {
         ret->code = KADM5_AUTH_MODIFY;
         log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp);
     } else {
@@ -1533,11 +1513,8 @@ get_strings_2_svc(gstrings_arg *arg, gstrings_ret *ret, struct svc_req *rqstp)
         goto exit_func;
 
     if (! cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) &&
-        (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
-                                                        rqst2name(rqstp),
-                                                        ACL_INQUIRE,
-                                                        arg->princ,
-                                                        NULL))) {
+        (CHANGEPW_SERVICE(rqstp) ||
+         !stub_acl_check(handle, ACL_INQUIRE, arg->princ, NULL))) {
         ret->code = KADM5_AUTH_GET;
         log_unauth("kadm5_get_strings", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -1574,9 +1551,8 @@ set_string_2_svc(sstring_arg *arg, generic_ret *ret, struct svc_req *rqstp)
     if (ret->code)
         goto exit_func;
 
-    if (CHANGEPW_SERVICE(rqstp)
-        || !kadm5int_acl_check(handle->context, rqst2name(rqstp), ACL_MODIFY,
-                               arg->princ, NULL)) {
+    if (CHANGEPW_SERVICE(rqstp) ||
+        !stub_acl_check(handle, ACL_MODIFY, arg->princ, NULL)) {
         ret->code = KADM5_AUTH_MODIFY;
         log_unauth("kadm5_mod_strings", prime_arg,
                    &client_name, &service_name, rqstp);
@@ -1665,8 +1641,7 @@ get_principal_keys_2_svc(getpkeys_arg *arg, getpkeys_ret *ret,
         goto exit_func;
 
     if (!(CHANGEPW_SERVICE(rqstp)) &&
-        kadm5int_acl_check(handle->context, rqst2name(rqstp),
-                           ACL_EXTRACT, arg->princ, NULL)) {
+        stub_acl_check(handle, ACL_EXTRACT, arg->princ, NULL)) {
         ret->code = kadm5_get_principal_keys(handle, arg->princ, arg->kvno,
                                              &ret->key_data, &ret->n_key_data);
     } else {


More information about the cvs-krb5 mailing list