any principal that it creates or modifies will not be able to get
postdateable tickets or tickets with a life of longer than 9 hours.
+MODULE BEHAVIOR
+---------------
+
+The ACL file can coexist with other authorization modules in release
+1.16 and later, as configured in the :ref:`kadm5_auth` section of
+:ref:`krb5.conf(5)`. The ACL file will positively authorize
+operations according to the rules above, but will never
+authoritatively deny an operation, so other modules can authorize
+operations in addition to those authorized by the ACL file.
+
+To operate without an ACL file, set the *acl_file* variable in
+:ref:`kdc.conf(5)` to the empty string with ``acl_file = ""``.
+
SEE ALSO
--------
**acl_file**
(String.) Location of the access control list file that
:ref:`kadmind(8)` uses to determine which principals are allowed
- which permissions on the Kerberos database. The default value is
- |kdcdir|\ ``/kadm5.acl``. For more information on Kerberos ACL
- file see :ref:`kadm5.acl(5)`.
+ which permissions on the Kerberos database. To operate without an
+ ACL file, set this relation to the empty string with ``acl_file =
+ ""``. The default value is |kdcdir|\ ``/kadm5.acl``. For more
+ information on Kerberos ACL file see :ref:`kadm5.acl(5)`.
**database_module**
(String.) This relation indicates the name of the configuration
with another database such as Active Directory. No plugins are built
in for this interface.
+.. _kadm5_auth:
+
+kadm5_auth interface
+====================
+
+The kadm5_auth section (introduced in release 1.16) controls modules
+for the kadmin authorization interface, which determines whether a
+client principal is allowed to perform a kadmin operation. The
+following built-in modules exist for this interface:
+
+**acl**
+ This module reads the :ref:`kadm5.acl(5)` file, and authorizes
+ operations which are allowed according to the rules in the file.
+
+**self**
+ This module authorizes self-service operations including password
+ changes, creation of new random keys, fetching the client's
+ principal record or string attributes, and fetching the policy
+ record associated with the client principal.
+
.. _clpreauth:
.. _kdcpreauth:
-I$(BUILDTOP)/lib/gssapi/krb5 -I$(top_srcdir)/lib/kadm5/srv
PROG = kadmind
-OBJS = auth.o auth_acl.o kadm_rpc_svc.o server_stubs.o ovsec_kadmd.o schpw.o \
- misc.o ipropd_svc.o
-SRCS = auth.o auth_acl.c kadm_rpc_svc.c server_stubs.c ovsec_kadmd.c schpw.c \
- misc.c ipropd_svc.c
+OBJS = auth.o auth_acl.o auth_self.o kadm_rpc_svc.o server_stubs.o \
+ ovsec_kadmd.o schpw.o misc.o ipropd_svc.o
+SRCS = auth.o auth_acl.c auth_self.c kadm_rpc_svc.c server_stubs.c \
+ ovsec_kadmd.c schpw.c misc.c ipropd_svc.c
all: $(PROG)
krb5_plugin_initvt_fn *modules = NULL, *mod;
size_t count;
auth_handle h = NULL;
+ const int intf = PLUGIN_INTERFACE_KADM5_AUTH;
+ ret = k5_plugin_register(context, intf, "acl", kadm5_auth_acl_initvt);
+ if (ret)
+ goto cleanup;
+ ret = k5_plugin_register(context, intf, "self", kadm5_auth_self_initvt);
+ if (ret)
+ goto cleanup;
ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KADM5_AUTH, &modules);
if (ret)
goto cleanup;
/* Notify modules that the most recent authorized operation has ended. */
void auth_end(krb5_context context);
+/* initvt declarations for built-in modules */
+
+krb5_error_code kadm5_auth_acl_initvt(krb5_context context, int maj_ver,
+ int min_ver, krb5_plugin_vtable vtable);
+krb5_error_code kadm5_auth_self_initvt(krb5_context context, int maj_ver,
+ int min_ver, krb5_plugin_vtable vtable);
+
#endif /* AUTH_H */
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* kadmin/server/auth_acl.c */
+/* kadmin/server/auth_acl.c - ACL kadm5_auth module */
/*
* Copyright 1995-2004, 2007, 2008, 2017 by the Massachusetts Institute of
* Technology. All Rights Reserved.
#include "k5-int.h"
#include <syslog.h>
#include <kadm5/admin.h>
+#include <krb5/kadm5_auth_plugin.h>
#include "adm_proto.h"
-#include "auth_acl.h"
#include <ctype.h>
+#include "auth.h"
+
+/*
+ * Access control bits.
+ */
+#define ACL_ADD 1
+#define ACL_DELETE 2
+#define ACL_MODIFY 4
+#define ACL_CHANGEPW 8
+/* #define ACL_CHANGE_OWN_PW 16 */
+#define ACL_INQUIRE 32
+#define ACL_EXTRACT 64
+#define ACL_LIST 128
+#define ACL_SETKEY 256
+#define ACL_IPROP 512
+
+#define ACL_ALL_MASK (ACL_ADD | \
+ ACL_DELETE | \
+ ACL_MODIFY | \
+ ACL_CHANGEPW | \
+ ACL_INQUIRE | \
+ ACL_LIST | \
+ ACL_IPROP | \
+ ACL_SETKEY)
struct acl_op_table {
char op;
struct acl_entry *list;
};
-static struct acl_state aclstate;
-
/*
* 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
return entry;
}
-/* Impose restrictions, modifying *rec and *mask. */
-krb5_error_code
-acl_impose_restrictions(krb5_context context, kadm5_principal_ent_rec *rec,
- long *mask, struct kadm5_auth_restrictions *rs)
-{
- krb5_error_code ret;
- krb5_timestamp now;
-
- if (rs == NULL)
- return 0;
- 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 (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 (rec->policy == NULL) {
- rec->policy = strdup(rs->policy); /* XDR will free it */
- if (!rec->policy)
- return ENOMEM;
- }
- *mask |= KADM5_POLICY;
- }
- 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 (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 (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 (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;
- }
- return 0;
-}
-
/* Free all ACL entries. */
static void
free_acl_entries(struct acl_state *state)
}
/* Open and parse the ACL file. */
-static void
+static krb5_error_code
load_acl_file(krb5_context context, const char *fname, struct acl_state *state)
{
+ krb5_error_code ret;
FILE *fp;
char *line;
struct acl_entry **entry_slot;
if (fp == NULL) {
krb5_klog_syslog(LOG_ERR, _("%s while opening ACL file %s"),
error_message(errno), fname);
- return;
+ ret = errno;
+ k5_setmsg(context, errno, _("Cannot open %s: %s"), fname,
+ error_message(ret));
+ return ret;
}
set_cloexec_file(fp);
free_acl_entries(state);
free(line);
fclose(fp);
- return;
+ k5_setmsg(context, EINVAL,
+ _("%s: syntax error at line %d <%.10s...>"),
+ fname, lineno, line);
+ return EINVAL;
}
entry_slot = &(*entry_slot)->next;
free(line);
}
fclose(fp);
+ return 0;
}
/*
return NULL;
}
-/* Initialize the ACL context. */
-krb5_error_code
-acl_init(krb5_context context, const char *acl_file)
-{
- load_acl_file(context, acl_file, &aclstate);
- return 0;
-}
-
-/* Terminate the ACL context. */
-void
-acl_finish(krb5_context context)
-{
- free_acl_entries(&aclstate);
-}
-
/* 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
-acl_check(krb5_context context, krb5_const_principal client, uint32_t op,
+static krb5_error_code
+acl_check(kadm5_auth_moddata data, uint32_t op, krb5_const_principal client,
krb5_const_principal target, struct kadm5_auth_restrictions **rs_out)
{
struct acl_entry *entry;
if (rs_out != NULL)
*rs_out = NULL;
- entry = find_entry(&aclstate, client, target);
+ entry = find_entry((struct acl_state *)data, client, target);
if (entry == NULL)
- return FALSE;
+ return KRB5_PLUGIN_NO_HANDLE;
if (!(entry->op_allowed & op))
- return FALSE;
+ return KRB5_PLUGIN_NO_HANDLE;
if (rs_out != NULL && entry->rs != NULL && entry->rs->mask)
*rs_out = entry->rs;
- return TRUE;
+ return 0;
+}
+
+static krb5_error_code
+acl_init(krb5_context context, const char *acl_file,
+ kadm5_auth_moddata *data_out)
+{
+ krb5_error_code ret;
+ struct acl_state *state;
+
+ *data_out = NULL;
+ if (acl_file == NULL)
+ return KRB5_PLUGIN_NO_HANDLE;
+ state = malloc(sizeof(*state));
+ state->list = NULL;
+ ret = load_acl_file(context, acl_file, state);
+ if (ret) {
+ free(state);
+ return ret;
+ }
+ *data_out = (kadm5_auth_moddata)state;
+ return 0;
+}
+
+static void
+acl_fini(krb5_context context, kadm5_auth_moddata data)
+{
+ if (data == NULL)
+ return;
+ free_acl_entries((struct acl_state *)data);
+ free(data);
+}
+
+static krb5_error_code
+acl_addprinc(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target,
+ const struct _kadm5_principal_ent_t *ent, long mask,
+ struct kadm5_auth_restrictions **rs_out)
+{
+ return acl_check(data, ACL_ADD, client, target, rs_out);
+}
+
+static krb5_error_code
+acl_modprinc(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target,
+ const struct _kadm5_principal_ent_t *ent, long mask,
+ struct kadm5_auth_restrictions **rs_out)
+{
+ return acl_check(data, ACL_MODIFY, client, target, rs_out);
+}
+
+static krb5_error_code
+acl_setstr(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target,
+ const char *key, const char *value)
+{
+ return acl_check(data, ACL_MODIFY, client, target, NULL);
+}
+
+static krb5_error_code
+acl_cpw(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ return acl_check(data, ACL_CHANGEPW, client, target, NULL);
+}
+
+static krb5_error_code
+acl_chrand(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ return acl_check(data, ACL_CHANGEPW, client, target, NULL);
+}
+
+static krb5_error_code
+acl_setkey(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ return acl_check(data, ACL_SETKEY, client, target, NULL);
+}
+
+static krb5_error_code
+acl_purgekeys(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ return acl_check(data, ACL_MODIFY, client, target, NULL);
+}
+
+static krb5_error_code
+acl_delprinc(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ return acl_check(data, ACL_DELETE, client, target, NULL);
+}
+
+static krb5_error_code
+acl_renprinc(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal src,
+ krb5_const_principal dest)
+{
+ struct kadm5_auth_restrictions *rs;
+
+ if (acl_check(data, ACL_DELETE, client, src, NULL) == 0 &&
+ acl_check(data, ACL_ADD, client, dest, &rs) == 0 && rs == NULL)
+ return 0;
+ return KRB5_PLUGIN_NO_HANDLE;
+}
+
+static krb5_error_code
+acl_getprinc(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ return acl_check(data, ACL_INQUIRE, client, target, NULL);
+}
+
+static krb5_error_code
+acl_getstrs(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ return acl_check(data, ACL_INQUIRE, client, target, NULL);
+}
+
+static krb5_error_code
+acl_extract(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ return acl_check(data, ACL_EXTRACT, client, target, NULL);
+}
+
+static krb5_error_code
+acl_listprincs(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client)
+{
+ return acl_check(data, ACL_LIST, client, NULL, NULL);
+}
+
+static krb5_error_code
+acl_addpol(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, const char *policy,
+ const struct _kadm5_policy_ent_t *ent, long mask)
+{
+ return acl_check(data, ACL_ADD, client, NULL, NULL);
+}
+
+static krb5_error_code
+acl_modpol(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, const char *policy,
+ const struct _kadm5_policy_ent_t *ent, long mask)
+{
+ return acl_check(data, ACL_MODIFY, client, NULL, NULL);
+}
+
+static krb5_error_code
+acl_delpol(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, const char *policy)
+{
+ return acl_check(data, ACL_DELETE, client, NULL, NULL);
+}
+
+static krb5_error_code
+acl_getpol(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, const char *policy,
+ const char *client_policy)
+{
+ return acl_check(data, ACL_INQUIRE, client, NULL, NULL);
+}
+
+static krb5_error_code
+acl_listpols(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client)
+{
+ return acl_check(data, ACL_LIST, client, NULL, NULL);
+}
+
+static krb5_error_code
+acl_iprop(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client)
+{
+ return acl_check(data, ACL_IPROP, client, NULL, NULL);
+}
+
+krb5_error_code
+kadm5_auth_acl_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable)
+{
+ kadm5_auth_vtable vt;
+
+ if (maj_ver != 1)
+ return KRB5_PLUGIN_VER_NOTSUPP;
+ vt = (kadm5_auth_vtable)vtable;
+ vt->name = "acl";
+ vt->init = acl_init;
+ vt->fini = acl_fini;
+ vt->addprinc = acl_addprinc;
+ vt->modprinc = acl_modprinc;
+ vt->setstr = acl_setstr;
+ vt->cpw = acl_cpw;
+ vt->chrand = acl_chrand;
+ vt->setkey = acl_setkey;
+ vt->purgekeys = acl_purgekeys;
+ vt->delprinc = acl_delprinc;
+ vt->renprinc = acl_renprinc;
+ vt->getprinc = acl_getprinc;
+ vt->getstrs = acl_getstrs;
+ vt->extract = acl_extract;
+ vt->listprincs = acl_listprincs;
+ vt->addpol = acl_addpol;
+ vt->modpol = acl_modpol;
+ vt->delpol = acl_delpol;
+ vt->getpol = acl_getpol;
+ vt->listpols = acl_listpols;
+ vt->iprop = acl_iprop;
+ return 0;
}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* kadmin/server/auth_acl.h */
-/*
- * Copyright 1995-2004, 2007, 2008 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.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- */
-
-#ifndef SERVER_ACL_H__
-#define SERVER_ACL_H__
-
-/*
- * Access control bits.
- */
-#define ACL_ADD 1
-#define ACL_DELETE 2
-#define ACL_MODIFY 4
-#define ACL_CHANGEPW 8
-/* #define ACL_CHANGE_OWN_PW 16 */
-#define ACL_INQUIRE 32
-#define ACL_EXTRACT 64
-#define ACL_LIST 128
-#define ACL_SETKEY 256
-#define ACL_IPROP 512
-
-#define ACL_ALL_MASK (ACL_ADD | \
- ACL_DELETE | \
- ACL_MODIFY | \
- ACL_CHANGEPW | \
- ACL_INQUIRE | \
- ACL_LIST | \
- ACL_IPROP | \
- ACL_SETKEY)
-
-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);
-
-#endif /* SERVER_ACL_H__ */
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* kadmin/server/auth_self.c - self-service kadm5_auth module */
+/*
+ * Copyright (C) 2017 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "k5-int.h"
+#include <kadm5/admin.h>
+#include <krb5/kadm5_auth_plugin.h>
+#include "auth.h"
+
+/* Authorize a principal to operate on itself. Applies to cpw, chrand,
+ * purgekeys, getprinc, and getstrs. */
+static krb5_error_code
+self_compare(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, krb5_const_principal target)
+{
+ if (krb5_principal_compare(context, client, target))
+ return 0;
+ return KRB5_PLUGIN_NO_HANDLE;
+}
+
+/* Authorize a principal to get the policy record for its own policy. */
+static krb5_error_code
+self_getpol(krb5_context context, kadm5_auth_moddata data,
+ krb5_const_principal client, const char *policy,
+ const char *client_policy)
+{
+ if (client_policy != NULL && strcmp(policy, client_policy) == 0)
+ return 0;
+ return KRB5_PLUGIN_NO_HANDLE;
+}
+
+krb5_error_code
+kadm5_auth_self_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable)
+{
+ kadm5_auth_vtable vt;
+
+ if (maj_ver != 1)
+ return KRB5_PLUGIN_VER_NOTSUPP;
+ vt = (kadm5_auth_vtable)vtable;
+ vt->name = "self";
+ vt->cpw = self_compare;
+ vt->chrand = self_compare;
+ vt->purgekeys = self_compare;
+ vt->getprinc = self_compare;
+ vt->getstrs = self_compare;
+ vt->getpol = self_getpol;
+ return 0;
+}
$(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
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kadm5_auth_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h auth.h auth_acl.c
+$(OUTPRE)auth_self.$(OBJEXT): $(BUILDTOP)/include/autoconf.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/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/kadm5_auth_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h auth.h auth_self.c
$(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 \
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/plugin.h \
$(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h auth_acl.h misc.h \
+ $(top_srcdir)/include/socket-utils.h auth.h misc.h \
server_stubs.c
$(OUTPRE)ovsec_kadmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \
$(top_srcdir)/lib/gssapi/generic/gssapiP_generic.h \
$(top_srcdir)/lib/gssapi/generic/gssapi_ext.h $(top_srcdir)/lib/gssapi/generic/gssapi_generic.h \
$(top_srcdir)/lib/gssapi/krb5/gssapiP_krb5.h $(top_srcdir)/lib/gssapi/krb5/gssapi_krb5.h \
- auth_acl.h misc.h ovsec_kadmd.c
+ auth.h misc.h ovsec_kadmd.c
$(OUTPRE)schpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
$(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.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/net-server.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h auth_acl.h misc.c \
+ $(top_srcdir)/include/socket-utils.h auth.h misc.c \
misc.h
$(OUTPRE)ipropd_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \
$(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \
- $(top_srcdir)/lib/gssapi/krb5/gssapi_krb5.h auth_acl.h \
+ $(top_srcdir)/lib/gssapi/krb5/gssapi_krb5.h auth.h \
ipropd_svc.c misc.h
#include <arpa/inet.h>
#include <netdb.h>
#include <kdb_log.h>
-#include "auth_acl.h"
+#include "auth.h"
#include "misc.h"
#include "osconf.h"
if (krb5_parse_name(context, client_name, &client_princ) != 0)
return FALSE;
- result = acl_check(context, client_princ, ACL_IPROP, NULL, NULL);
+ result = auth(context, OP_IPROP, client_princ,
+ NULL, NULL, NULL, NULL, NULL, 0);
krb5_free_principal(context, client_princ);
return result;
}
#include <kdb.h>
#include <kadm5/server_internal.h>
#include "misc.h"
-#include "auth_acl.h"
+#include "auth.h"
#include "net-server.h"
-
-/*
- * Function: chpass_principal_wrapper_3
- *
- * Purpose: wrapper to kadm5_chpass_principal that checks to see if
- * pw_min_life has been reached. if not it returns an error.
- * otherwise it calls kadm5_chpass_principal
- *
- * Arguments:
- * principal (input) krb5_principals whose password we are
- * changing
- * keepold (input) whether to preserve old keys
- * n_ks_tuple (input) the number of key-salt tuples in ks_tuple
- * ks_tuple (input) array of tuples indicating the caller's
- * requested enctypes/salttypes
- * password (input) password we are going to change to.
- * <return value> 0 on success error code on failure.
- *
- * Requires:
- * kadm5_init to have been run.
- *
- * Effects:
- * calls kadm5_chpass_principal which changes the kdb and the
- * the admin db.
- *
- */
-kadm5_ret_t
-chpass_principal_wrapper_3(void *server_handle,
- krb5_principal principal,
- krb5_boolean keepold,
- int n_ks_tuple,
- krb5_key_salt_tuple *ks_tuple,
- char *password)
-{
- kadm5_ret_t ret;
-
- ret = check_min_life(server_handle, principal, NULL, 0);
- if (ret)
- return ret;
-
- return kadm5_chpass_principal_3(server_handle, principal,
- keepold, n_ks_tuple, ks_tuple,
- password);
-}
-
-
-/*
- * Function: randkey_principal_wrapper_3
- *
- * Purpose: wrapper to kadm5_randkey_principal which checks the
- * password's min. life.
- *
- * Arguments:
- * principal (input) krb5_principal whose password we are
- * changing
- * keepold (input) whether to preserve old keys
- * n_ks_tuple (input) the number of key-salt tuples in ks_tuple
- * ks_tuple (input) array of tuples indicating the caller's
- * requested enctypes/salttypes
- * key (output) new random key
- * <return value> 0, error code on error.
- *
- * Requires:
- * kadm5_init needs to be run
- *
- * Effects:
- * calls kadm5_randkey_principal
- *
- */
-kadm5_ret_t
-randkey_principal_wrapper_3(void *server_handle,
- krb5_principal principal,
- krb5_boolean keepold,
- int n_ks_tuple,
- krb5_key_salt_tuple *ks_tuple,
- krb5_keyblock **keys, int *n_keys)
-{
- kadm5_ret_t ret;
-
- ret = check_min_life(server_handle, principal, NULL, 0);
- if (ret)
- return ret;
- return kadm5_randkey_principal_3(server_handle, principal,
- keepold, n_ks_tuple, ks_tuple,
- keys, n_keys);
-}
-
kadm5_ret_t
schpw_util_wrapper(void *server_handle,
krb5_principal client,
{
kadm5_ret_t ret;
kadm5_server_handle_t handle = server_handle;
- krb5_boolean access_granted;
- krb5_boolean self;
/*
* If no target is explicitly provided, then the target principal
if (target == NULL)
target = client;
- /*
- * A principal can always change its own password, as long as it
- * has an initial ticket and meets the minimum password lifetime
- * requirement.
- */
- self = krb5_principal_compare(handle->context, client, target);
- if (self) {
+ /* If the client is changing its own password, require it to use an initial
+ * ticket, and enforce the policy min_life. */
+ if (krb5_principal_compare(handle->context, client, target)) {
+ if (!initial_flag) {
+ strlcpy(msg_ret, "Ticket must be derived from a password",
+ msg_len);
+ return KADM5_AUTH_INITIAL;
+ }
+
ret = check_min_life(server_handle, target, msg_ret, msg_len);
if (ret != 0)
return ret;
-
- access_granted = initial_flag;
- } else
- access_granted = FALSE;
-
- if (!access_granted &&
- acl_check(handle->context, client, ACL_CHANGEPW, target, NULL)) {
- /*
- * Otherwise, principals with appropriate privileges can change
- * any password
- */
- access_granted = TRUE;
}
- if (access_granted) {
+ if (auth(handle->context, OP_CPW, client, target,
+ NULL, NULL, NULL, NULL, 0)) {
ret = kadm5_chpass_principal_util(server_handle,
target,
new_pw, ret_pw,
setup_gss_names(struct svc_req *, gss_buffer_desc *,
gss_buffer_desc *);
-
-kadm5_ret_t
-chpass_principal_wrapper_3(void *server_handle,
- krb5_principal principal,
- krb5_boolean keepold,
- int n_ks_tuple,
- krb5_key_salt_tuple *ks_tuple,
- char *password);
-
-kadm5_ret_t
-randkey_principal_wrapper_3(void *server_handle,
- krb5_principal principal,
- krb5_boolean keepold,
- int n_ks_tuple,
- krb5_key_salt_tuple *ks_tuple,
- krb5_keyblock **keys, int *n_keys);
-
kadm5_ret_t
schpw_util_wrapper(void *server_handle, krb5_principal client,
krb5_principal target, krb5_boolean initial_flag,
#include <kdb_log.h>
#include "misc.h"
-#include "auth_acl.h"
+#include "auth.h"
#if defined(NEED_DAEMON_PROTO)
int daemon(int, int);
verto_ctx *vctx;
const char *pid_file = NULL;
char **db_args = NULL, **tmpargs;
+ const char *acl_file;
int ret, i, db_args_size = 0, strong_random = 1, proponly = 0;
setlocale(LC_ALL, "");
if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE)
fail_to_start(0, _("Cannot initialize GSSAPI service name"));
- ret = acl_init(context, params.acl_file);
+ acl_file = (*params.acl_file != '\0') ? params.acl_file : NULL;
+ ret = auth_init(context, acl_file);
if (ret)
fail_to_start(ret, _("initializing ACL file"));
svcauth_gssapi_unset_names();
kadm5_destroy(global_server_handle);
loop_free(vctx);
- acl_finish(context);
+ auth_fini(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++)
goto chpwfail;
}
- /* for cpw, verify that this is an AS_REQ ticket */
- if (vno == 1 &&
- (ticket->enc_part2->flags & TKT_FLG_INITIAL) == 0) {
- numresult = KRB5_KPASSWD_INITIAL_FLAG_NEEDED;
- strlcpy(strresult, "Ticket must be derived from a password",
- sizeof(strresult));
- goto chpwfail;
- }
-
/* change the password */
ptr = k5memdup0(clear.data, clear.length, &ret);
case KADM5_AUTH_CHANGEPW:
numresult = KRB5_KPASSWD_ACCESSDENIED;
break;
+ case KADM5_AUTH_INITIAL:
+ numresult = KRB5_KPASSWD_INITIAL_FLAG_NEEDED;
+ break;
case KADM5_PASS_Q_TOOSHORT:
case KADM5_PASS_REUSE:
case KADM5_PASS_Q_CLASS:
#include <syslog.h>
#include <adm_proto.h> /* krb5_klog_syslog */
#include "misc.h"
-#include "auth_acl.h"
+#include "auth.h"
extern gss_name_t gss_changepw_name;
extern gss_name_t gss_oldchangepw_name;
return name;
}
-static int cmp_gss_krb5_name(kadm5_server_handle_t handle,
- gss_name_t gss_name, krb5_principal princ)
-{
- krb5_principal princ2;
- int status;
-
- if (! gss_to_krb5_name(handle, gss_name, &princ2))
- return 0;
- status = krb5_principal_compare(handle->context, princ, princ2);
- krb5_free_principal(handle->context, princ2);
- return status;
-}
-
static int gss_to_krb5_name(kadm5_server_handle_t handle,
gss_name_t gss_name, krb5_principal *princ)
{
{
OM_uint32 minor_stat;
+ auth_end(handle->context);
free_server_handle(handle);
free(princ_str);
gss_release_buffer(&minor_stat, client_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)
+stub_auth(kadm5_server_handle_t handle, int opcode, krb5_const_principal p1,
+ krb5_const_principal p2, const char *s1, const char *s2)
+{
+ return auth(handle->context, opcode, handle->current_caller, p1, p2,
+ s1, s2, NULL, 0);
+}
+
+static krb5_boolean
+stub_auth_pol(kadm5_server_handle_t handle, int opcode, const char *policy,
+ const kadm5_policy_ent_rec *polent, long mask)
+{
+ return auth(handle->context, opcode, handle->current_caller, NULL, NULL,
+ policy, NULL, polent, mask);
+}
+
+static krb5_boolean
+stub_auth_restrict(kadm5_server_handle_t handle, int opcode,
+ kadm5_principal_ent_t ent, long *mask)
+{
+ return auth_restrict(handle->context, opcode, handle->current_caller,
+ ent, mask);
+}
+
+/* Return true if the client authenticated to kadmin/changepw and princ is not
+ * the client principal. */
+static krb5_boolean
+changepw_not_self(kadm5_server_handle_t handle, struct svc_req *rqstp,
+ krb5_const_principal princ)
+{
+ return CHANGEPW_SERVICE(rqstp) &&
+ !krb5_principal_compare(handle->context, handle->current_caller,
+ princ);
+}
+
+static krb5_boolean
+ticket_is_initial(struct svc_req *rqstp)
+{
+ OM_uint32 status, minor_stat;
+ krb5_flags flags;
+
+ status = gss_krb5_get_tkt_flags(&minor_stat, rqstp->rq_svccred, &flags);
+ if (status != GSS_S_COMPLETE)
+ return 0;
+ return (flags & TKT_FLG_INITIAL) != 0;
+}
+
+/* If a key change request is for the client's own principal, verify that the
+ * client used an initial ticket and enforce the policy min_life. */
+static kadm5_ret_t
+check_self_keychange(kadm5_server_handle_t handle, struct svc_req *rqstp,
+ krb5_principal princ)
{
- return acl_check(handle->context, handle->current_caller, op, target,
- rs_out);
+ if (!krb5_principal_compare(handle->context, handle->current_caller,
+ princ))
+ return 0;
+
+ if (!ticket_is_initial(rqstp))
+ return KADM5_AUTH_INITIAL;
+
+ return check_min_life(handle, princ, NULL, 0);
}
static int
gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
kadm5_server_handle_t handle;
- struct kadm5_auth_restrictions *rp;
const char *errmsg = NULL;
ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
goto exit_func;
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_ADD, arg->rec.principal, &rp) ||
- acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) {
+ !stub_auth_restrict(handle, OP_ADDPRINC, &arg->rec, &arg->mask)) {
ret->code = KADM5_AUTH_ADD;
log_unauth("kadm5_create_principal", prime_arg,
&client_name, &service_name, rqstp);
gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
kadm5_server_handle_t handle;
- struct kadm5_auth_restrictions *rp;
const char *errmsg = NULL;
ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
goto exit_func;
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_ADD, arg->rec.principal, &rp) ||
- acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) {
+ !stub_auth_restrict(handle, OP_ADDPRINC, &arg->rec, &arg->mask)) {
ret->code = KADM5_AUTH_ADD;
log_unauth("kadm5_create_principal", prime_arg,
&client_name, &service_name, rqstp);
goto exit_func;
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_DELETE, arg->princ, NULL)) {
+ !stub_auth(handle, OP_DELPRINC, arg->princ, NULL, NULL, NULL)) {
ret->code = KADM5_AUTH_DELETE;
log_unauth("kadm5_delete_principal", prime_arg,
&client_name, &service_name, rqstp);
gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
kadm5_server_handle_t handle;
- struct kadm5_auth_restrictions *rp;
const char *errmsg = NULL;
ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
goto exit_func;
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_MODIFY, arg->rec.principal, &rp) ||
- acl_impose_restrictions(handle->context, &arg->rec, &arg->mask, rp)) {
+ !stub_auth_restrict(handle, OP_MODPRINC, &arg->rec, &arg->mask)) {
ret->code = KADM5_AUTH_MODIFY;
log_unauth("kadm5_modify_principal", prime_arg,
&client_name, &service_name, rqstp);
gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
kadm5_server_handle_t handle;
- struct kadm5_auth_restrictions *rp;
const char *errmsg = NULL;
size_t tlen1, tlen2, clen, slen;
char *tdots1, *tdots2, *cdots, *sdots;
slen = service_name.length;
trunc_name(&slen, &sdots);
- ret->code = KADM5_OK;
- if (! CHANGEPW_SERVICE(rqstp)) {
- if (!stub_acl_check(handle, ACL_DELETE, arg->src, NULL))
+ if (CHANGEPW_SERVICE(rqstp) ||
+ !stub_auth(handle, OP_RENPRINC, arg->src, arg->dest, NULL, NULL)) {
+ ret->code = KADM5_AUTH_INSUFFICIENT;
+ log_unauth("kadm5_rename_principal", prime_arg1, &client_name,
+ &service_name, rqstp);
+ } else {
+ ret->code = check_lockdown_keys(handle, arg->src);
+ if (ret->code == KADM5_PROTECT_KEYS) {
+ log_unauth("kadm5_rename_principal", prime_arg1, &client_name,
+ &service_name, rqstp);
ret->code = KADM5_AUTH_DELETE;
- /* any restrictions at all on the ADD kills the RENAME */
- if (!stub_acl_check(handle, ACL_ADD, arg->dest, &rp) || rp != NULL) {
- if (ret->code == KADM5_AUTH_DELETE)
- ret->code = KADM5_AUTH_INSUFFICIENT;
- else
- ret->code = KADM5_AUTH_ADD;
}
- if (ret->code == KADM5_OK) {
- ret->code = check_lockdown_keys(handle, arg->src);
- if (ret->code == KADM5_PROTECT_KEYS) {
- log_unauth("kadm5_rename_principal", prime_arg1, &client_name,
- &service_name, rqstp);
- ret->code = KADM5_AUTH_DELETE;
- }
- }
- } else
- ret->code = KADM5_AUTH_INSUFFICIENT;
+ }
if (ret->code != KADM5_OK) {
/* okay to cast lengths to int because trunc_name limits max value */
krb5_klog_syslog(LOG_NOTICE,
funcname = "kadm5_get_principal";
- if (! cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) &&
- (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_INQUIRE, arg->princ, NULL))) {
+ if (changepw_not_self(handle, rqstp, arg->princ) ||
+ !stub_auth(handle, OP_GETPRINC, arg->princ, NULL, NULL, NULL)) {
ret->code = KADM5_AUTH_GET;
log_unauth(funcname, prime_arg,
&client_name, &service_name, rqstp);
prime_arg = "*";
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_LIST, NULL, NULL)) {
+ !stub_auth(handle, OP_LISTPRINCS, NULL, NULL, NULL, NULL)) {
ret->code = KADM5_AUTH_LIST;
log_unauth("kadm5_get_principals", prime_arg,
&client_name, &service_name, rqstp);
&service_name, rqstp);
ret->code = KADM5_AUTH_CHANGEPW;
}
- } else if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) {
- ret->code = chpass_principal_wrapper_3(handle, arg->princ, FALSE, 0,
- NULL, arg->pass);
- } else if (!(CHANGEPW_SERVICE(rqstp)) &&
- stub_acl_check(handle, ACL_CHANGEPW, arg->princ, NULL)) {
- ret->code = kadm5_chpass_principal(handle, arg->princ, arg->pass);
- } else {
+ } else if (changepw_not_self(handle, rqstp, arg->princ) ||
+ !stub_auth(handle, OP_CPW, arg->princ, NULL, NULL, NULL)) {
+ ret->code = KADM5_AUTH_CHANGEPW;
log_unauth("kadm5_chpass_principal", prime_arg,
&client_name, &service_name, rqstp);
- ret->code = KADM5_AUTH_CHANGEPW;
+ } else {
+ ret->code = check_self_keychange(handle, rqstp, arg->princ);
+ if (!ret->code)
+ ret->code = kadm5_chpass_principal(handle, arg->princ, arg->pass);
}
if (ret->code != KADM5_AUTH_CHANGEPW) {
&service_name, rqstp);
ret->code = KADM5_AUTH_CHANGEPW;
}
- } else if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) {
- ret->code = chpass_principal_wrapper_3(handle, arg->princ,
- arg->keepold, arg->n_ks_tuple,
- arg->ks_tuple, arg->pass);
- } else if (!(CHANGEPW_SERVICE(rqstp)) &&
- 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);
- } else {
+ } else if (changepw_not_self(handle, rqstp, arg->princ) ||
+ !stub_auth(handle, OP_CPW, arg->princ, NULL, NULL, NULL)) {
+ ret->code = KADM5_AUTH_CHANGEPW;
log_unauth("kadm5_chpass_principal", prime_arg,
&client_name, &service_name, rqstp);
- ret->code = KADM5_AUTH_CHANGEPW;
+ } else {
+ ret->code = check_self_keychange(handle, rqstp, arg->princ);
+ if (!ret->code) {
+ ret->code = kadm5_chpass_principal_3(handle, arg->princ,
+ arg->keepold, arg->n_ks_tuple,
+ arg->ks_tuple, arg->pass);
+ }
}
if (ret->code != KADM5_AUTH_CHANGEPW) {
ret->code = KADM5_AUTH_SETKEY;
}
} else if (!(CHANGEPW_SERVICE(rqstp)) &&
- stub_acl_check(handle, ACL_SETKEY, arg->princ, NULL)) {
+ stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) {
ret->code = kadm5_setv4key_principal(handle, arg->princ,
arg->keyblock);
} else {
ret->code = KADM5_AUTH_SETKEY;
}
} else if (!(CHANGEPW_SERVICE(rqstp)) &&
- stub_acl_check(handle, ACL_SETKEY, arg->princ, NULL)) {
+ stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) {
ret->code = kadm5_setkey_principal(handle, arg->princ, arg->keyblocks,
arg->n_keys);
} else {
ret->code = KADM5_AUTH_SETKEY;
}
} else if (!(CHANGEPW_SERVICE(rqstp)) &&
- stub_acl_check(handle, ACL_SETKEY, arg->princ, NULL)) {
+ stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) {
ret->code = kadm5_setkey_principal_3(handle, arg->princ, arg->keepold,
arg->n_ks_tuple, arg->ks_tuple,
arg->keyblocks, arg->n_keys);
ret->code = KADM5_AUTH_SETKEY;
}
} else if (!(CHANGEPW_SERVICE(rqstp)) &&
- stub_acl_check(handle, ACL_SETKEY, arg->princ, NULL)) {
+ stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) {
ret->code = kadm5_setkey_principal_4(handle, arg->princ, arg->keepold,
arg->key_data, arg->n_key_data);
} else {
funcname = "kadm5_randkey_principal";
- if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) {
- ret->code = randkey_principal_wrapper_3(handle, arg->princ, FALSE, 0,
- NULL, &k, &nkeys);
- } else if (!(CHANGEPW_SERVICE(rqstp)) &&
- stub_acl_check(handle, ACL_CHANGEPW, arg->princ, NULL)) {
- ret->code = kadm5_randkey_principal(handle, arg->princ, &k, &nkeys);
- } else {
+ if (changepw_not_self(handle, rqstp, arg->princ) ||
+ !stub_auth(handle, OP_CHRAND, arg->princ, NULL, NULL, NULL)) {
+ ret->code = KADM5_AUTH_CHANGEPW;
log_unauth(funcname, prime_arg,
&client_name, &service_name, rqstp);
- ret->code = KADM5_AUTH_CHANGEPW;
+ } else {
+ ret->code = check_self_keychange(handle, rqstp, arg->princ);
+ if (!ret->code) {
+ ret->code = kadm5_randkey_principal(handle, arg->princ,
+ &k, &nkeys);
+ }
}
if (ret->code == KADM5_OK) {
funcname = "kadm5_randkey_principal";
- if (cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ)) {
- ret->code = randkey_principal_wrapper_3(handle, arg->princ,
- arg->keepold, arg->n_ks_tuple,
- arg->ks_tuple, &k, &nkeys);
- } else if (!(CHANGEPW_SERVICE(rqstp)) &&
- 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);
- } else {
+ if (changepw_not_self(handle, rqstp, arg->princ) ||
+ !stub_auth(handle, OP_CHRAND, arg->princ, NULL, NULL, NULL)) {
+ ret->code = KADM5_AUTH_CHANGEPW;
log_unauth(funcname, prime_arg,
&client_name, &service_name, rqstp);
- ret->code = KADM5_AUTH_CHANGEPW;
+ } else {
+ ret->code = check_self_keychange(handle, rqstp, arg->princ);
+ if (!ret->code) {
+ ret->code = kadm5_randkey_principal_3(handle, arg->princ,
+ arg->keepold,
+ arg->n_ks_tuple,
+ arg->ks_tuple, &k, &nkeys);
+ }
}
if (ret->code == KADM5_OK) {
prime_arg = arg->rec.policy;
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_ADD, NULL, NULL)) {
+ !stub_auth_pol(handle, OP_ADDPOL, arg->rec.policy,
+ &arg->rec, arg->mask)) {
ret->code = KADM5_AUTH_ADD;
log_unauth("kadm5_create_policy", prime_arg,
&client_name, &service_name, rqstp);
prime_arg = arg->name;
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_DELETE, NULL, NULL)) {
+ !stub_auth(handle, OP_DELPOL, NULL, NULL, arg->name, NULL)) {
log_unauth("kadm5_delete_policy", prime_arg,
&client_name, &service_name, rqstp);
ret->code = KADM5_AUTH_DELETE;
prime_arg = arg->rec.policy;
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_MODIFY, NULL, NULL)) {
+ !stub_auth_pol(handle, OP_MODPOL, arg->rec.policy,
+ &arg->rec, arg->mask)) {
log_unauth("kadm5_modify_policy", prime_arg,
&client_name, &service_name, rqstp);
ret->code = KADM5_AUTH_MODIFY;
kadm5_ret_t ret2;
kadm5_principal_ent_rec caller_ent;
kadm5_server_handle_t handle;
- const char *errmsg = NULL;
+ const char *errmsg = NULL, *cpolicy = NULL;
+
+ memset(&caller_ent, 0, sizeof(caller_ent));
ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle,
&ret->api_version, &client_name, &service_name,
prime_arg = arg->name;
+ /* Look up the client principal's policy value. */
+ ret2 = kadm5_get_principal(handle->lhandle, handle->current_caller,
+ &caller_ent, KADM5_PRINCIPAL_NORMAL_MASK);
+ if (ret2 == KADM5_OK && (caller_ent.aux_attributes & KADM5_POLICY))
+ cpolicy = caller_ent.policy;
+
ret->code = KADM5_AUTH_GET;
- if (!CHANGEPW_SERVICE(rqstp) &&
- stub_acl_check(handle, ACL_INQUIRE, NULL, NULL)) {
- ret->code = KADM5_OK;
+ if ((CHANGEPW_SERVICE(rqstp) &&
+ (cpolicy == NULL || strcmp(cpolicy, arg->name) != 0)) ||
+ !stub_auth(handle, OP_GETPOL, NULL, NULL, arg->name, cpolicy)) {
+ ret->code = KADM5_AUTH_GET;
+ log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp);
} else {
- ret->code = kadm5_get_principal(handle->lhandle,
- handle->current_caller, &caller_ent,
- KADM5_PRINCIPAL_NORMAL_MASK);
- if (ret->code == KADM5_OK) {
- if (caller_ent.aux_attributes & KADM5_POLICY &&
- strcmp(caller_ent.policy, arg->name) == 0) {
- ret->code = KADM5_OK;
- } else {
- ret->code = KADM5_AUTH_GET;
- }
- ret2 = kadm5_free_principal_ent(handle->lhandle,
- &caller_ent);
- ret->code = ret->code ? ret->code : ret2;
- }
- }
-
- if (ret->code == KADM5_OK) {
ret->code = kadm5_get_policy(handle, arg->name, &ret->rec);
-
if (ret->code != 0)
errmsg = krb5_get_error_message(handle->context, ret->code);
&client_name, &service_name, rqstp);
if (errmsg != NULL)
krb5_free_error_message(handle->context, errmsg);
-
- } else {
- log_unauth(funcname, prime_arg,
- &client_name, &service_name, rqstp);
}
exit_func:
+ (void)kadm5_free_principal_ent(handle->lhandle, &caller_ent);
stub_cleanup(handle, NULL, &client_name, &service_name);
return TRUE;
}
prime_arg = "*";
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_LIST, NULL, NULL)) {
+ !stub_auth(handle, OP_LISTPOLS, NULL, NULL, NULL, NULL)) {
ret->code = KADM5_AUTH_LIST;
log_unauth("kadm5_get_policies", prime_arg,
&client_name, &service_name, rqstp);
funcname = "kadm5_purgekeys";
- if (!cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) &&
- (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_MODIFY, arg->princ, NULL))) {
+ if (CHANGEPW_SERVICE(rqstp) ||
+ !stub_auth(handle, OP_PURGEKEYS, arg->princ, NULL, NULL, NULL)) {
ret->code = KADM5_AUTH_MODIFY;
log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp);
} else {
if (ret->code)
goto exit_func;
- if (! cmp_gss_krb5_name(handle, rqst2name(rqstp), arg->princ) &&
- (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_INQUIRE, arg->princ, NULL))) {
+ if (CHANGEPW_SERVICE(rqstp) ||
+ !stub_auth(handle, OP_GETSTRS, arg->princ, NULL, NULL, NULL)) {
ret->code = KADM5_AUTH_GET;
log_unauth("kadm5_get_strings", prime_arg,
&client_name, &service_name, rqstp);
goto exit_func;
if (CHANGEPW_SERVICE(rqstp) ||
- !stub_acl_check(handle, ACL_MODIFY, arg->princ, NULL)) {
+ !stub_auth(handle, OP_SETSTR, arg->princ, NULL,
+ arg->key, arg->value)) {
ret->code = KADM5_AUTH_MODIFY;
log_unauth("kadm5_mod_strings", prime_arg,
&client_name, &service_name, rqstp);
goto exit_func;
if (!(CHANGEPW_SERVICE(rqstp)) &&
- stub_acl_check(handle, ACL_EXTRACT, arg->princ, NULL)) {
+ stub_auth(handle, OP_EXTRACT, arg->princ, NULL, NULL, NULL)) {
ret->code = kadm5_get_principal_keys(handle, arg->princ, arg->kvno,
&ret->key_data, &ret->n_key_data);
} else {
error_code KADM5_SETKEY_BAD_KVNO, "Invalid multiple or duplicate kvnos in setkey operation"
error_code KADM5_AUTH_EXTRACT, "Operation requires ``extract-keys'' privilege"
error_code KADM5_PROTECT_KEYS, "Principal keys are locked down"
+error_code KADM5_AUTH_INITIAL, "Operation requires initial ticket"
end
"audit",
"tls",
"kdcauthdata",
- "certauth"
+ "certauth",
+ "kadm5_auth"
};
/* Return the context's interface structure for id, or NULL if invalid. */
kadmin_as(some_rename, ['renprinc', 'from', 'to'])
realm.run([kadminl, 'renprinc', 'to', 'from'])
kadmin_as(all_add, ['renprinc', 'from', 'to'], expected_code=1,
- expected_msg="Operation requires ``delete'' privilege")
+ expected_msg="Insufficient authorization for operation")
kadmin_as(all_delete, ['renprinc', 'from', 'to'], expected_code=1,
- expected_msg="Operation requires ``add'' privilege")
+ expected_msg="Insufficient authorization for operation")
kadmin_as(some_rename, ['renprinc', 'from', 'notto'], expected_code=1,
- expected_msg="Operation requires ``add'' privilege")
+ expected_msg="Insufficient authorization for operation")
realm.run([kadminl, 'renprinc', 'from', 'notfrom'])
kadmin_as(some_rename, ['renprinc', 'notfrom', 'to'], expected_code=1,
- expected_msg="Operation requires ``delete'' privilege")
+ expected_msg="Insufficient authorization for operation")
kadmin_as(restricted_rename, ['renprinc', 'notfrom', 'to'], expected_code=1,
- expected_msg="Operation requires ``add'' privilege")
+ expected_msg="Insufficient authorization for operation")
realm.run([kadminl, 'delprinc', 'notfrom'])
realm.addprinc('selected', 'pw')