Add DENY rule for krb5_kuserok() and update manpage

This commit is contained in:
Nicolas Williams
2011-12-08 10:58:18 -06:00
parent 8e63cff2cc
commit b9f8e6d956
2 changed files with 102 additions and 29 deletions

View File

@@ -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,
};