Add DENY rule for krb5_kuserok() and update manpage
This commit is contained in:
@@ -263,21 +263,27 @@ wrong server name into the gss_accept_sec_context call.
|
||||
.It Li k5login_directory = Va directory
|
||||
Alternative location for user .k5login files. Tokens in the form of
|
||||
%{luser} are expanded to the name of the user whose .k5login file is
|
||||
%needed.
|
||||
needed. This option is provided for compatibility with MIT krb5
|
||||
configuration files.
|
||||
.It Li k5login_authoritative = Va boolean
|
||||
If true then if a principal is not found in k5login files then
|
||||
krb5_userok() will not fallback on principal to username mapping.
|
||||
krb5_userok() will not fallback on principal to username mapping. This
|
||||
option is provided for compatibility with MIT krb5 configuration files.
|
||||
.It Li kuserok = Va rule ...
|
||||
Specifies krb5_kuserok(3) behavior. If multiple values are given, then
|
||||
krb5_kuserok(3) will try them in order until one succeeds or all fail.
|
||||
Rules are implemented by plugins, with three built-in plugins described
|
||||
below. Default: USER-K5LOGIN SIMPLE.
|
||||
krb5_kuserok(3) will evaluate them in order until one succeeds or all
|
||||
fail. Rules are implemented by plugins, with three built-in plugins
|
||||
described below. Default: USER-K5LOGIN SIMPLE DENY.
|
||||
.It Li kuserok = Va DENY
|
||||
If set and evaluated then krb5_userok(3) will deny access to the given
|
||||
username no matter what the principal name might be.
|
||||
.It Li kuserok = Va SIMPLE
|
||||
If set then krb5_userok(3) will use principal to username mapping (see
|
||||
auth_to_local below). If the principal maps to the requested username
|
||||
then access is allowed.
|
||||
If set and evaluated then krb5_userok(3) will use principal to username
|
||||
mapping (see auth_to_local below). If the principal maps to the
|
||||
requested username then access is allowed.
|
||||
.It Li kuserok = Va SYSTEM-K5LOGIN[:directory]
|
||||
If set then krb5_userok(3) will use k5login files named after the
|
||||
If set and evaluated then krb5_userok(3) will use k5login files named
|
||||
after the
|
||||
.Va luser
|
||||
argument to krb5_kuserok(3) in the given directory or in
|
||||
/etc/k5login.d/. If a directory is given then tokens will be expanded;
|
||||
@@ -286,11 +292,13 @@ the %{luser} token will be replaced with the
|
||||
argument to krb5_kuserok(3). K5login files are text files, with each
|
||||
line containing just a principal name; principals apearing in a user's
|
||||
k5login file are permitted access to the user's account. Note: this rule
|
||||
performs no ownership nor permissions checks on k5login files.
|
||||
performs no ownership nor permissions checks on k5login files; proper
|
||||
ownership and permissions/ACLs are expected due to the system k5login
|
||||
location being a system location.
|
||||
.It Li kuserok = Va USER-K5LOGIN
|
||||
If set then krb5_userok(3) will use ~luser/.k5login and
|
||||
~luser/.k5login.d/*. User k5login files and directories must be owned
|
||||
by the user and must not have world nor group write permissions.
|
||||
If set and evaluated then krb5_userok(3) will use ~luser/.k5login and
|
||||
~luser/.k5login.d/*. User k5login files and directories must be owned by
|
||||
the user and must not have world nor group write permissions.
|
||||
.It Li aname2lname-text-db = Va filename
|
||||
The named file must be a sorted (in increasing order) text file where
|
||||
every line consists of an unparsed principal name optionally followed by
|
||||
|
@@ -70,6 +70,7 @@ static krb5_error_code plugin_reg_ret;
|
||||
static krb5plugin_kuserok_ftable kuserok_simple_plug;
|
||||
static krb5plugin_kuserok_ftable kuserok_sys_k5login_plug;
|
||||
static krb5plugin_kuserok_ftable kuserok_user_k5login_plug;
|
||||
static krb5plugin_kuserok_ftable kuserok_deny_plug;
|
||||
|
||||
static void
|
||||
reg_def_plugins_once(void *ctx)
|
||||
@@ -88,6 +89,10 @@ reg_def_plugins_once(void *ctx)
|
||||
KRB5_PLUGIN_KUSEROK, &kuserok_user_k5login_plug);
|
||||
if (!plugin_reg_ret)
|
||||
plugin_reg_ret = ret;
|
||||
ret = krb5_plugin_register(context, PLUGIN_TYPE_DATA,
|
||||
KRB5_PLUGIN_KUSEROK, &kuserok_deny_plug);
|
||||
if (!plugin_reg_ret)
|
||||
plugin_reg_ret = ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,6 +128,8 @@ check_owner(krb5_context context, krb5_boolean is_system_location,
|
||||
*/
|
||||
if (is_system_location || owner == NULL)
|
||||
return 0;
|
||||
krb5_set_error_message(context, EACCES,
|
||||
"User k5login files not supported on Windows");
|
||||
return EACCES;
|
||||
#else
|
||||
struct stat st;
|
||||
@@ -134,37 +141,67 @@ check_owner(krb5_context context, krb5_boolean is_system_location,
|
||||
#endif
|
||||
|
||||
#ifdef POSIX_GETPWNAM_R
|
||||
if (owner != NULL && getpwnam_r(owner, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0)
|
||||
if (owner != NULL && getpwnam_r(owner, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) {
|
||||
krb5_set_error_message(context, errno, "User unknown (getpwnam_r())");
|
||||
return EACCES;
|
||||
}
|
||||
#else
|
||||
pwd = getpwnam(luser);
|
||||
if (owner != NULL && pwd == NULL)
|
||||
if (owner != NULL && pwd == NULL) {
|
||||
krb5_set_error_message(context, errno, "User unknown (getpwnam())");
|
||||
return EACCES;
|
||||
}
|
||||
#endif
|
||||
if (dir) {
|
||||
if (fstat(dirfd(dir), &st) == -1)
|
||||
if (fstat(dirfd(dir), &st) == -1) {
|
||||
krb5_set_error_message(context, errno, "fstat() of k5login.d failed");
|
||||
return errno;
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
}
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
krb5_set_error_message(context, ENOTDIR, "k5login.d not a directory");
|
||||
return ENOTDIR;
|
||||
if (st.st_dev != dirlstat->st_dev || st.st_ino != dirlstat->st_ino)
|
||||
}
|
||||
if (st.st_dev != dirlstat->st_dev || st.st_ino != dirlstat->st_ino) {
|
||||
krb5_set_error_message(context, EACCES,
|
||||
"k5login.d was renamed during kuserok "
|
||||
"operation");
|
||||
return EACCES;
|
||||
if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0)
|
||||
}
|
||||
if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
|
||||
krb5_set_error_message(context, EACCES,
|
||||
"k5login.d has world and/or group write "
|
||||
"permissions");
|
||||
return EACCES; /* XXX We should have a better code */
|
||||
if (pwd != NULL && pwd->pw_uid != st.st_uid && st.st_uid != 0)
|
||||
}
|
||||
if (pwd != NULL && pwd->pw_uid != st.st_uid && st.st_uid != 0) {
|
||||
krb5_set_error_message(context, EACCES,
|
||||
"k5login.d not owned by the user or root");
|
||||
return EACCES;
|
||||
}
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
}
|
||||
if (file) {
|
||||
if (fstat(fileno(file), &st) == -1)
|
||||
if (fstat(fileno(file), &st) == -1) {
|
||||
krb5_set_error_message(context, errno, "fstat() of k5login failed");
|
||||
return errno;
|
||||
if (S_ISDIR(st.st_mode))
|
||||
}
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
krb5_set_error_message(context, EISDIR, "k5login is a directory");
|
||||
return EISDIR;
|
||||
if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0)
|
||||
}
|
||||
if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
|
||||
krb5_set_error_message(context, EISDIR,
|
||||
"k5login has world and/or group write "
|
||||
"permissions");
|
||||
return EACCES; /* XXX We should have a better code */
|
||||
}
|
||||
if (pwd == NULL || pwd->pw_uid == st.st_uid || st.st_uid == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
krb5_set_error_message(context, EACCES,
|
||||
"k5login not owned by the user or root");
|
||||
return EACCES;
|
||||
}
|
||||
|
||||
@@ -244,11 +281,15 @@ check_directory(krb5_context context,
|
||||
if (lstat(dirname, &st) < 0)
|
||||
return errno;
|
||||
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
krb5_set_error_message(context, ENOTDIR, "k5login.d not a directory");
|
||||
return ENOTDIR;
|
||||
}
|
||||
|
||||
if ((d = opendir(dirname)) == NULL)
|
||||
if ((d = opendir(dirname)) == NULL) {
|
||||
krb5_set_error_message(context, ENOTDIR, "Could not open k5login.d");
|
||||
return errno;
|
||||
}
|
||||
|
||||
ret = check_owner(context, is_system_location, d, &st, NULL, owner);
|
||||
if (ret)
|
||||
@@ -293,7 +334,7 @@ check_an2ln(krb5_context context,
|
||||
|
||||
lname = malloc(strlen(luser) + 1);
|
||||
if (lname == NULL)
|
||||
return ENOMEM;
|
||||
return krb5_enomem(context);
|
||||
ret = krb5_aname_to_localname(context, principal, strlen(luser)+1, lname);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -512,20 +553,24 @@ kuserok_user_k5login_plug_f(void *plug_ctx, krb5_context context,
|
||||
profile_dir = k5login_dir;
|
||||
if (profile_dir == NULL) {
|
||||
#ifdef POSIX_GETPWNAM_R
|
||||
if (getpwnam_r(luser, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0)
|
||||
if (getpwnam_r(luser, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) {
|
||||
krb5_set_error_message(context, errno, "User unknown (getpwnam_r())");
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
}
|
||||
#else
|
||||
pwd = getpwnam (luser);
|
||||
#endif
|
||||
if (pwd == NULL)
|
||||
if (pwd == NULL) {
|
||||
krb5_set_error_message(context, errno, "User unknown (getpwnam())");
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
}
|
||||
profile_dir = pwd->pw_dir;
|
||||
}
|
||||
|
||||
#define KLOGIN "/.k5login"
|
||||
|
||||
if (asprintf(&path, "%s/.k5login.d", profile_dir) == -1)
|
||||
return ENOMEM;
|
||||
return krb5_enomem(context);
|
||||
|
||||
ret = _krb5_expand_path_tokensv(context, path, &path_exp,
|
||||
"luser", luser, NULL);
|
||||
@@ -565,6 +610,19 @@ kuserok_user_k5login_plug_f(void *plug_ctx, krb5_context context,
|
||||
#endif
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
kuserok_deny_plug_f(void *plug_ctx, krb5_context context, const char *rule,
|
||||
unsigned int flags, const char *k5login_dir,
|
||||
const char *luser, krb5_const_principal principal,
|
||||
krb5_boolean *result)
|
||||
{
|
||||
if (strcmp(rule, "DENY") != 0)
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
|
||||
*result = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
kuser_ok_null_plugin_init(krb5_context context, void **ctx)
|
||||
{
|
||||
@@ -599,3 +657,10 @@ static krb5plugin_kuserok_ftable kuserok_user_k5login_plug = {
|
||||
kuserok_user_k5login_plug_f,
|
||||
};
|
||||
|
||||
static krb5plugin_kuserok_ftable kuserok_deny_plug = {
|
||||
KRB5_PLUGIN_KUSEROK_VERSION_0,
|
||||
kuser_ok_null_plugin_init,
|
||||
kuser_ok_null_plugin_fini,
|
||||
kuserok_deny_plug_f,
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user