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
|
.It Li k5login_directory = Va directory
|
||||||
Alternative location for user .k5login files. Tokens in the form of
|
Alternative location for user .k5login files. Tokens in the form of
|
||||||
%{luser} are expanded to the name of the user whose .k5login file is
|
%{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
|
.It Li k5login_authoritative = Va boolean
|
||||||
If true then if a principal is not found in k5login files then
|
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 ...
|
.It Li kuserok = Va rule ...
|
||||||
Specifies krb5_kuserok(3) behavior. If multiple values are given, then
|
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.
|
krb5_kuserok(3) will evaluate them in order until one succeeds or all
|
||||||
Rules are implemented by plugins, with three built-in plugins described
|
fail. Rules are implemented by plugins, with three built-in plugins
|
||||||
below. Default: USER-K5LOGIN SIMPLE.
|
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
|
.It Li kuserok = Va SIMPLE
|
||||||
If set then krb5_userok(3) will use principal to username mapping (see
|
If set and evaluated then krb5_userok(3) will use principal to username
|
||||||
auth_to_local below). If the principal maps to the requested username
|
mapping (see auth_to_local below). If the principal maps to the
|
||||||
then access is allowed.
|
requested username then access is allowed.
|
||||||
.It Li kuserok = Va SYSTEM-K5LOGIN[:directory]
|
.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
|
.Va luser
|
||||||
argument to krb5_kuserok(3) in the given directory or in
|
argument to krb5_kuserok(3) in the given directory or in
|
||||||
/etc/k5login.d/. If a directory is given then tokens will be expanded;
|
/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
|
argument to krb5_kuserok(3). K5login files are text files, with each
|
||||||
line containing just a principal name; principals apearing in a user's
|
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
|
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
|
.It Li kuserok = Va USER-K5LOGIN
|
||||||
If set then krb5_userok(3) will use ~luser/.k5login and
|
If set and evaluated then krb5_userok(3) will use ~luser/.k5login and
|
||||||
~luser/.k5login.d/*. User k5login files and directories must be owned
|
~luser/.k5login.d/*. User k5login files and directories must be owned by
|
||||||
by the user and must not have world nor group write permissions.
|
the user and must not have world nor group write permissions.
|
||||||
.It Li aname2lname-text-db = Va filename
|
.It Li aname2lname-text-db = Va filename
|
||||||
The named file must be a sorted (in increasing order) text file where
|
The named file must be a sorted (in increasing order) text file where
|
||||||
every line consists of an unparsed principal name optionally followed by
|
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_simple_plug;
|
||||||
static krb5plugin_kuserok_ftable kuserok_sys_k5login_plug;
|
static krb5plugin_kuserok_ftable kuserok_sys_k5login_plug;
|
||||||
static krb5plugin_kuserok_ftable kuserok_user_k5login_plug;
|
static krb5plugin_kuserok_ftable kuserok_user_k5login_plug;
|
||||||
|
static krb5plugin_kuserok_ftable kuserok_deny_plug;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reg_def_plugins_once(void *ctx)
|
reg_def_plugins_once(void *ctx)
|
||||||
@@ -88,6 +89,10 @@ reg_def_plugins_once(void *ctx)
|
|||||||
KRB5_PLUGIN_KUSEROK, &kuserok_user_k5login_plug);
|
KRB5_PLUGIN_KUSEROK, &kuserok_user_k5login_plug);
|
||||||
if (!plugin_reg_ret)
|
if (!plugin_reg_ret)
|
||||||
plugin_reg_ret = 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)
|
if (is_system_location || owner == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
krb5_set_error_message(context, EACCES,
|
||||||
|
"User k5login files not supported on Windows");
|
||||||
return EACCES;
|
return EACCES;
|
||||||
#else
|
#else
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@@ -134,37 +141,67 @@ check_owner(krb5_context context, krb5_boolean is_system_location,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef POSIX_GETPWNAM_R
|
#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;
|
return EACCES;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
pwd = getpwnam(luser);
|
pwd = getpwnam(luser);
|
||||||
if (owner != NULL && pwd == NULL)
|
if (owner != NULL && pwd == NULL) {
|
||||||
|
krb5_set_error_message(context, errno, "User unknown (getpwnam())");
|
||||||
return EACCES;
|
return EACCES;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (dir) {
|
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;
|
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;
|
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;
|
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 */
|
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;
|
return EACCES;
|
||||||
|
}
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (file) {
|
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;
|
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;
|
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 */
|
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)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
krb5_set_error_message(context, EACCES,
|
||||||
|
"k5login not owned by the user or root");
|
||||||
return EACCES;
|
return EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,11 +281,15 @@ check_directory(krb5_context context,
|
|||||||
if (lstat(dirname, &st) < 0)
|
if (lstat(dirname, &st) < 0)
|
||||||
return errno;
|
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;
|
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;
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
ret = check_owner(context, is_system_location, d, &st, NULL, owner);
|
ret = check_owner(context, is_system_location, d, &st, NULL, owner);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -293,7 +334,7 @@ check_an2ln(krb5_context context,
|
|||||||
|
|
||||||
lname = malloc(strlen(luser) + 1);
|
lname = malloc(strlen(luser) + 1);
|
||||||
if (lname == NULL)
|
if (lname == NULL)
|
||||||
return ENOMEM;
|
return krb5_enomem(context);
|
||||||
ret = krb5_aname_to_localname(context, principal, strlen(luser)+1, lname);
|
ret = krb5_aname_to_localname(context, principal, strlen(luser)+1, lname);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -512,20 +553,24 @@ kuserok_user_k5login_plug_f(void *plug_ctx, krb5_context context,
|
|||||||
profile_dir = k5login_dir;
|
profile_dir = k5login_dir;
|
||||||
if (profile_dir == NULL) {
|
if (profile_dir == NULL) {
|
||||||
#ifdef POSIX_GETPWNAM_R
|
#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;
|
return KRB5_PLUGIN_NO_HANDLE;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
pwd = getpwnam (luser);
|
pwd = getpwnam (luser);
|
||||||
#endif
|
#endif
|
||||||
if (pwd == NULL)
|
if (pwd == NULL) {
|
||||||
|
krb5_set_error_message(context, errno, "User unknown (getpwnam())");
|
||||||
return KRB5_PLUGIN_NO_HANDLE;
|
return KRB5_PLUGIN_NO_HANDLE;
|
||||||
|
}
|
||||||
profile_dir = pwd->pw_dir;
|
profile_dir = pwd->pw_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define KLOGIN "/.k5login"
|
#define KLOGIN "/.k5login"
|
||||||
|
|
||||||
if (asprintf(&path, "%s/.k5login.d", profile_dir) == -1)
|
if (asprintf(&path, "%s/.k5login.d", profile_dir) == -1)
|
||||||
return ENOMEM;
|
return krb5_enomem(context);
|
||||||
|
|
||||||
ret = _krb5_expand_path_tokensv(context, path, &path_exp,
|
ret = _krb5_expand_path_tokensv(context, path, &path_exp,
|
||||||
"luser", luser, NULL);
|
"luser", luser, NULL);
|
||||||
@@ -565,6 +610,19 @@ kuserok_user_k5login_plug_f(void *plug_ctx, krb5_context context,
|
|||||||
#endif
|
#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
|
static krb5_error_code
|
||||||
kuser_ok_null_plugin_init(krb5_context context, void **ctx)
|
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,
|
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