krb5 commit: Modernize auth_acl.c

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/0def80f767b9a2cdfbc19d3a61433d1edd7a7998
commit 0def80f767b9a2cdfbc19d3a61433d1edd7a7998
Author: Greg Hudson <[email protected]>
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 {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.