Use roken_get_*() instead of getpwuuid()
Using non-reentrant getpwuid() (or getpwnam(), or getspnam()) can be dangerous. We had a report of a login application / PAM that calls those, and Heimdal, by calling them too, clobbered the cached struct passwd used by the login app / PAM.
This commit is contained in:

committed by
Nico Williams

parent
95eb83c424
commit
620862049e
@@ -99,6 +99,7 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int f;
|
int f;
|
||||||
char tf[1024];
|
char tf[1024];
|
||||||
|
char shellbuf[MAX_PATH];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
char *path;
|
char *path;
|
||||||
@@ -166,13 +167,10 @@ main(int argc, char **argv)
|
|||||||
(unsigned long)((argc + 10)*sizeof(char *)));
|
(unsigned long)((argc + 10)*sizeof(char *)));
|
||||||
|
|
||||||
if(*argv == NULL) {
|
if(*argv == NULL) {
|
||||||
path = getenv("SHELL");
|
if (roken_get_shell(shellbuf, sizeof(shellbuf)) != NULL)
|
||||||
if(path == NULL){
|
path = strdup(shellbuf);
|
||||||
struct passwd *pw = k_getpwuid(geteuid());
|
else
|
||||||
if (pw == NULL)
|
path = strdup("/bin/sh");
|
||||||
errx(1, "no such user: %d", (int)geteuid());
|
|
||||||
path = strdup(pw->pw_shell);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
path = strdup(*argv++);
|
path = strdup(*argv++);
|
||||||
}
|
}
|
||||||
|
@@ -292,6 +292,7 @@ main (int argc, char **argv)
|
|||||||
int uid = getuid();
|
int uid = getuid();
|
||||||
OtpAlgorithm *alg = otp_find_alg (OTP_ALG_DEFAULT);
|
OtpAlgorithm *alg = otp_find_alg (OTP_ALG_DEFAULT);
|
||||||
int optidx = 0;
|
int optidx = 0;
|
||||||
|
char userbuf[128];
|
||||||
|
|
||||||
setprogname (argv[0]);
|
setprogname (argv[0]);
|
||||||
if(getarg(args, num_args, argc, argv, &optidx))
|
if(getarg(args, num_args, argc, argv, &optidx))
|
||||||
@@ -332,12 +333,9 @@ main (int argc, char **argv)
|
|||||||
return list_otps (argc, argv, user);
|
return list_otps (argc, argv, user);
|
||||||
|
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
struct passwd *pwd;
|
user = roken_get_username(userbuf, sizeof(userbuf));
|
||||||
|
if (user == NULL)
|
||||||
pwd = k_getpwuid(uid);
|
|
||||||
if (pwd == NULL)
|
|
||||||
err (1, "You don't exist");
|
err (1, "You don't exist");
|
||||||
user = pwd->pw_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -524,6 +524,7 @@ KRB_CAPABILITIES
|
|||||||
rk_DLADDR
|
rk_DLADDR
|
||||||
|
|
||||||
AC_CHECK_GETPWNAM_R_POSIX
|
AC_CHECK_GETPWNAM_R_POSIX
|
||||||
|
AC_CHECK_GETPWUID_R_POSIX
|
||||||
|
|
||||||
dnl detect doors on solaris
|
dnl detect doors on solaris
|
||||||
if test "$enable_pthread_support" != no; then
|
if test "$enable_pthread_support" != no; then
|
||||||
|
@@ -84,7 +84,7 @@ $(OBJ)\kadmin-commands.c $(OBJ)\kadmin-commands.h: kadmin-commands.in
|
|||||||
cd $(SRCDIR)
|
cd $(SRCDIR)
|
||||||
|
|
||||||
$(SBINDIR)\kadmin.exe: $(KADMIN_OBJS) $(KADMIN_LIBS)
|
$(SBINDIR)\kadmin.exe: $(KADMIN_OBJS) $(KADMIN_LIBS)
|
||||||
$(EXECONLINK)
|
$(EXECONLINK) Secur32.lib Shell32.lib
|
||||||
$(EXEPREP)
|
$(EXEPREP)
|
||||||
|
|
||||||
KADMIND_OBJS= \
|
KADMIND_OBJS= \
|
||||||
@@ -100,7 +100,7 @@ KADMIND_LIBS=\
|
|||||||
$(COMMON_LIBS)
|
$(COMMON_LIBS)
|
||||||
|
|
||||||
$(LIBEXECDIR)\kadmind.exe: $(KADMIND_OBJS) $(KADMIND_LIBS)
|
$(LIBEXECDIR)\kadmind.exe: $(KADMIND_OBJS) $(KADMIND_LIBS)
|
||||||
$(EXECONLINK)
|
$(EXECONLINK) Secur32.lib Shell32.lib
|
||||||
$(EXEPREP)
|
$(EXEPREP)
|
||||||
|
|
||||||
all:: $(INCFILES) $(SBIN_PROGRAMS) $(LIBEXEC_PROGRAMS)
|
all:: $(INCFILES) $(SBIN_PROGRAMS) $(LIBEXEC_PROGRAMS)
|
||||||
@@ -115,13 +115,13 @@ clean::
|
|||||||
NOINST_PROGRAMS=$(OBJ)\add_random_users.exe
|
NOINST_PROGRAMS=$(OBJ)\add_random_users.exe
|
||||||
|
|
||||||
$(OBJ)\add_random_users.exe: $(OBJ)\add_random_users.obj $(LIBKADM5SRV) $(LIBKADM5CLNT) $(COMMON_LIBS)
|
$(OBJ)\add_random_users.exe: $(OBJ)\add_random_users.obj $(LIBKADM5SRV) $(LIBKADM5CLNT) $(COMMON_LIBS)
|
||||||
$(EXECONLINK)
|
$(EXECONLINK) Secur32.lib Shell32.lib
|
||||||
$(EXEPREP_NODIST)
|
$(EXEPREP_NODIST)
|
||||||
|
|
||||||
TEST_BINARIES=$(OBJ)\test_util.exe
|
TEST_BINARIES=$(OBJ)\test_util.exe
|
||||||
|
|
||||||
$(OBJ)\test_util.exe: $(OBJ)\test_util.obj $(OBJ)\util.obj $(KADMIN_LIBS)
|
$(OBJ)\test_util.exe: $(OBJ)\test_util.obj $(OBJ)\util.obj $(KADMIN_LIBS)
|
||||||
$(EXECONLINK)
|
$(EXECONLINK) Secur32.lib Shell32.lib
|
||||||
$(EXEPREP_NODIST)
|
$(EXEPREP_NODIST)
|
||||||
|
|
||||||
test-binaries: $(TEST_BINARIES)
|
test-binaries: $(TEST_BINARIES)
|
||||||
|
@@ -819,45 +819,25 @@ static char *
|
|||||||
get_config_file_for_user(void)
|
get_config_file_for_user(void)
|
||||||
{
|
{
|
||||||
char *fn;
|
char *fn;
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
char *home;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fn = secure_getenv("SOFTPKCS11RC");
|
fn = secure_getenv("SOFTPKCS11RC");
|
||||||
if (fn)
|
if (fn)
|
||||||
fn = strdup(fn);
|
fn = strdup(fn);
|
||||||
home = secure_getenv("HOME");
|
|
||||||
if (fn == NULL && home == NULL) {
|
|
||||||
struct passwd *pw = getpwuid(getuid());
|
|
||||||
if(pw != NULL)
|
|
||||||
home = pw->pw_dir;
|
|
||||||
}
|
|
||||||
if (fn == NULL) {
|
if (fn == NULL) {
|
||||||
|
char homebuf[MAX_PATH];
|
||||||
|
const char *home = roken_get_appdatadir(homebuf, sizeof(homebuf));
|
||||||
|
|
||||||
if (home) {
|
if (home) {
|
||||||
ret = asprintf(&fn, "%s/.soft-token.rc", home);
|
ret = asprintf(&fn, "%s/.soft-token.rc", home);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
fn = NULL;
|
fn = NULL;
|
||||||
} else
|
} else {
|
||||||
|
#ifndef WIN32
|
||||||
fn = strdup("/etc/soft-token.rc");
|
fn = strdup("/etc/soft-token.rc");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else /* Windows */
|
|
||||||
|
|
||||||
char appdatafolder[MAX_PATH];
|
|
||||||
|
|
||||||
fn = getenv("SOFTPKCS11RC");
|
|
||||||
|
|
||||||
/* Retrieve the roaming AppData folder for the current user. The
|
|
||||||
current user is the user account represented by the current
|
|
||||||
thread token. */
|
|
||||||
|
|
||||||
if (fn == NULL &&
|
|
||||||
SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatafolder))) {
|
|
||||||
|
|
||||||
asprintf(&fn, "%s\\.soft-token.rc", appdatafolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
@@ -569,6 +569,7 @@ krb5_config_parse_file_multi (krb5_context context,
|
|||||||
if (ISTILDE(fname[0]) && ISPATHSEP(fname[1])) {
|
if (ISTILDE(fname[0]) && ISPATHSEP(fname[1])) {
|
||||||
#ifndef KRB5_USE_PATH_TOKENS
|
#ifndef KRB5_USE_PATH_TOKENS
|
||||||
const char *home = NULL;
|
const char *home = NULL;
|
||||||
|
char homebuf[MAX_PATH];
|
||||||
|
|
||||||
if (!_krb5_homedir_access(context)) {
|
if (!_krb5_homedir_access(context)) {
|
||||||
context->config_include_depth--;
|
context->config_include_depth--;
|
||||||
@@ -577,12 +578,7 @@ krb5_config_parse_file_multi (krb5_context context,
|
|||||||
return EPERM;
|
return EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
home = secure_getenv("HOME");
|
home = roken_get_appdatadir(homebuf, sizeof(homebuf));
|
||||||
if (home == NULL) {
|
|
||||||
struct passwd *pw = getpwuid(getuid());
|
|
||||||
if(pw != NULL)
|
|
||||||
home = pw->pw_dir;
|
|
||||||
}
|
|
||||||
if (home) {
|
if (home) {
|
||||||
int aret;
|
int aret;
|
||||||
|
|
||||||
|
@@ -37,113 +37,37 @@
|
|||||||
* Try to find out what's a reasonable default principal.
|
* Try to find out what's a reasonable default principal.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char*
|
|
||||||
get_env_user(void)
|
|
||||||
{
|
|
||||||
const char *user = getenv("USER");
|
|
||||||
if(user == NULL)
|
|
||||||
user = getenv("LOGNAME");
|
|
||||||
if(user == NULL)
|
|
||||||
user = getenv("USERNAME");
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Will only use operating-system dependant operation to get the
|
|
||||||
* default principal, for use of functions that in ccache layer to
|
|
||||||
* avoid recursive calls.
|
|
||||||
*/
|
|
||||||
|
|
||||||
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
||||||
_krb5_get_default_principal_local (krb5_context context,
|
_krb5_get_default_principal_local (krb5_context context,
|
||||||
krb5_principal *princ)
|
krb5_principal *princ)
|
||||||
{
|
{
|
||||||
krb5_error_code ret;
|
|
||||||
const char *user;
|
const char *user;
|
||||||
uid_t uid;
|
const char *second_component = NULL;
|
||||||
|
char userbuf[128];
|
||||||
|
|
||||||
*princ = NULL;
|
*princ = NULL;
|
||||||
|
|
||||||
uid = getuid();
|
/*
|
||||||
if(uid == 0) {
|
* NOTE: We depend on roken_get_username() preferentially using
|
||||||
user = getlogin();
|
* getlogin_r() first when !issuid() && getuid() == 0, otherwise we
|
||||||
if(user == NULL)
|
* won't figure out to output <username>/root@DEFAULT_REALM.
|
||||||
user = get_env_user();
|
*/
|
||||||
if(user != NULL && strcmp(user, "root") != 0)
|
user = roken_get_username(userbuf, sizeof(userbuf));
|
||||||
ret = krb5_make_principal(context, princ, NULL, user, "root", NULL);
|
if (user == NULL) {
|
||||||
else
|
krb5_set_error_message(context, ENOTTY,
|
||||||
ret = krb5_make_principal(context, princ, NULL, "root", NULL);
|
N_("unable to figure out current principal",
|
||||||
} else {
|
""));
|
||||||
struct passwd *pw = getpwuid(uid);
|
return ENOTTY; /* XXX */
|
||||||
if(pw != NULL)
|
|
||||||
user = pw->pw_name;
|
|
||||||
else {
|
|
||||||
user = get_env_user();
|
|
||||||
if(user == NULL)
|
|
||||||
user = getlogin();
|
|
||||||
}
|
|
||||||
if(user == NULL) {
|
|
||||||
krb5_set_error_message(context, ENOTTY,
|
|
||||||
N_("unable to figure out current "
|
|
||||||
"principal", ""));
|
|
||||||
return ENOTTY; /* XXX */
|
|
||||||
}
|
|
||||||
ret = krb5_make_principal(context, princ, NULL, user, NULL);
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
#ifndef WIN32
|
||||||
|
if (!issuid() && getuid() == 0 && strcmp(user, "root") != 0)
|
||||||
|
second_component = "root"; /* We'll use <user>/root */
|
||||||
|
#endif;
|
||||||
|
return krb5_make_principal(context, princ, NULL, user,
|
||||||
|
second_component, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* _WIN32 */
|
|
||||||
|
|
||||||
#define SECURITY_WIN32
|
|
||||||
#include <security.h>
|
|
||||||
|
|
||||||
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
|
||||||
_krb5_get_default_principal_local(krb5_context context,
|
|
||||||
krb5_principal *princ)
|
|
||||||
{
|
|
||||||
/* See if we can get the principal first. We only expect this to
|
|
||||||
work if logged into a domain. */
|
|
||||||
{
|
|
||||||
char username[1024];
|
|
||||||
ULONG sz = sizeof(username);
|
|
||||||
|
|
||||||
if (GetUserNameEx(NameUserPrincipal, username, &sz)) {
|
|
||||||
return krb5_parse_name_flags(context, username,
|
|
||||||
KRB5_PRINCIPAL_PARSE_ENTERPRISE,
|
|
||||||
princ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Just get the Windows username. This should pretty much always
|
|
||||||
work. */
|
|
||||||
{
|
|
||||||
char username[1024];
|
|
||||||
DWORD dsz = sizeof(username);
|
|
||||||
|
|
||||||
if (GetUserName(username, &dsz)) {
|
|
||||||
return krb5_make_principal(context, princ, NULL, username, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failing that, we look at the environment */
|
|
||||||
{
|
|
||||||
const char * username = get_env_user();
|
|
||||||
|
|
||||||
if (username == NULL) {
|
|
||||||
krb5_set_error_string(context,
|
|
||||||
"unable to figure out current principal");
|
|
||||||
return ENOTTY; /* Really? */
|
|
||||||
}
|
|
||||||
|
|
||||||
return krb5_make_principal(context, princ, NULL, username, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
|
||||||
krb5_get_default_principal (krb5_context context,
|
krb5_get_default_principal (krb5_context context,
|
||||||
krb5_principal *princ)
|
krb5_principal *princ)
|
||||||
|
Reference in New Issue
Block a user