* [PATCH 0/3] Add support for using libuser to chsh
@ 2013-01-03 3:21 ` Cody Maloney
2013-01-03 3:21 ` [PATCH 1/3] chsh-chfn: Add flag for enabling/disabling libuser support Cody Maloney
` (3 more replies)
0 siblings, 4 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-03 3:21 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
Add support for libuser to chsh. This follows lchsh which is packaged with
libuser. If this set looks good, I will add libuser support to chfn.
Cody Maloney (3):
chsh-chfn: Add flag for enabling/disabling libuser support.
chsh: Move pam auth to its own function.
chsh: Add libuser support
configure.ac | 17 ++++++
login-utils/Makemodule.am | 5 ++
login-utils/chsh.c | 137 ++++++++++++++++++++++++++++++++++++++--------
3 files changed, 135 insertions(+), 24 deletions(-)
--
1.8.1
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH 1/3] chsh-chfn: Add flag for enabling/disabling libuser support.
2013-01-03 3:21 ` [PATCH 0/3] Add support for using libuser to chsh Cody Maloney
@ 2013-01-03 3:21 ` Cody Maloney
2013-01-03 3:22 ` [PATCH 2/3] chsh: Move pam auth to its own function Cody Maloney
` (2 subsequent siblings)
3 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-03 3:21 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
---
configure.ac | 17 +++++++++++++++++
login-utils/Makemodule.am | 5 +++++
2 files changed, 22 insertions(+)
diff --git a/configure.ac b/configure.ac
index 9c08fc0..bfe8cba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1095,6 +1095,23 @@ AS_HELP_STRING([--disable-chsh-only-listed], [chsh: allow shells not in /etc/she
[], enable_chsh_only_listed=yes
)
+AC_ARG_WITH([libuser], AS_HELP_STRING([--without-libuser], [compile without libuser (remote chsh)]),
+ [], with_user=auto
+)
+
+if test "x$with_user" = xno; then
+ AM_CONDITIONAL(HAVE_USER, false)
+else
+ PKG_CHECK_MODULES(LIBUSER,[libuser])
+ UL_CHECK_LIB(user, lu_start)
+ case "$with_user:$have_user" in
+ yes:no)
+ AC_MSG_ERROR([user selected but libuser not found])
+ ;;
+ esac
+fi
+
+
if test "x$enable_chsh_only_listed" = xyes; then
AC_DEFINE(ONLY_LISTED_SHELLS, 1, [Should chsh allow only shells in /etc/shells?])
fi
diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
index aef8177..479b87b 100644
--- a/login-utils/Makemodule.am
+++ b/login-utils/Makemodule.am
@@ -68,6 +68,11 @@ chfn_chsh_cflags = $(SUID_CFLAGS) $(AM_CFLAGS)
chfn_chsh_ldflags = $(SUID_LDFLAGS) $(AM_LDFLAGS)
chfn_chsh_ldadd = libcommon.la -lpam -lpam_misc
+if HAVE_USER
+chfn_chsh_ldflags += $(LIBUSER_LIBS)
+chfn_chsh_cflags += $(LIBUSER_CFLAGS)
+endif
+
if HAVE_SELINUX
chfn_chsh_sources += \
login-utils/selinux_utils.c \
--
1.8.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 2/3] chsh: Move pam auth to its own function.
2013-01-03 3:21 ` [PATCH 0/3] Add support for using libuser to chsh Cody Maloney
2013-01-03 3:21 ` [PATCH 1/3] chsh-chfn: Add flag for enabling/disabling libuser support Cody Maloney
@ 2013-01-03 3:22 ` Cody Maloney
2013-01-03 3:22 ` [PATCH 3/3] chsh: Add libuser support Cody Maloney
2013-01-13 9:12 ` [PATCH 2/3] chsh: Move pam auth to its own function Cody Maloney
3 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-03 3:22 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
This makes it easier to add support for libuser, which needs the same PAM
authentication.
---
login-utils/chsh.c | 54 +++++++++++++++++++++++++++++++-----------------------
1 file changed, 31 insertions(+), 23 deletions(-)
diff --git a/login-utils/chsh.c b/login-utils/chsh.c
index 6e9325d..b5c3e2e 100644
--- a/login-utils/chsh.c
+++ b/login-utils/chsh.c
@@ -53,6 +53,7 @@ struct sinfo {
char *shell;
};
+static int auth_pam(uid_t uid, struct passwd *pw);
static void parse_argv(int argc, char **argv, struct sinfo *pinfo);
static char *prompt(char *question, char *def_val);
static int check_shell(char *shell);
@@ -147,6 +148,31 @@ int main(int argc, char **argv)
printf(_("Changing shell for %s.\n"), pw->pw_name);
+ if(!auth_pam(uid, pw)) {
+ return EXIT_FAILURE;
+ }
+
+ if (!shell) {
+ shell = prompt(_("New shell"), oldshell);
+ if (!shell)
+ return EXIT_SUCCESS;
+ }
+
+ if (check_shell(shell) < 0)
+ return EXIT_FAILURE;
+
+ if (strcmp(oldshell, shell) == 0)
+ errx(EXIT_SUCCESS, _("Shell not changed."));
+ pw->pw_shell = shell;
+ if (setpwnam(pw) < 0)
+ err(EXIT_FAILURE, _("setpwnam failed\n"
+ "Shell *NOT* changed. Try again later."));
+
+ printf(_("Shell changed.\n"));
+ return EXIT_SUCCESS;
+}
+
+int auth_pam(uid_t uid, struct passwd *pw) {
#ifdef REQUIRE_PASSWORD
if (uid != 0) {
pam_handle_t *pamh = NULL;
@@ -155,47 +181,29 @@ int main(int argc, char **argv)
retcode = pam_start("chsh", pw->pw_name, &conv, &pamh);
if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
+ return FALSE;
retcode = pam_authenticate(pamh, 0);
if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
+ return FALSE;
retcode = pam_acct_mgmt(pamh, 0);
if (retcode == PAM_NEW_AUTHTOK_REQD)
retcode =
pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
+ return FALSE;
retcode = pam_setcred(pamh, 0);
if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
+ return FALSE;
pam_end(pamh, 0);
/* no need to establish a session; this isn't a
* session-oriented activity... */
}
+ return TRUE;
#endif /* REQUIRE_PASSWORD */
-
- if (!shell) {
- shell = prompt(_("New shell"), oldshell);
- if (!shell)
- return EXIT_SUCCESS;
- }
-
- if (check_shell(shell) < 0)
- return EXIT_FAILURE;
-
- if (strcmp(oldshell, shell) == 0)
- errx(EXIT_SUCCESS, _("Shell not changed."));
- pw->pw_shell = shell;
- if (setpwnam(pw) < 0)
- err(EXIT_FAILURE, _("setpwnam failed\n"
- "Shell *NOT* changed. Try again later."));
-
- printf(_("Shell changed.\n"));
- return EXIT_SUCCESS;
}
/*
--
1.8.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 3/3] chsh: Add libuser support
2013-01-03 3:21 ` [PATCH 0/3] Add support for using libuser to chsh Cody Maloney
2013-01-03 3:21 ` [PATCH 1/3] chsh-chfn: Add flag for enabling/disabling libuser support Cody Maloney
2013-01-03 3:22 ` [PATCH 2/3] chsh: Move pam auth to its own function Cody Maloney
@ 2013-01-03 3:22 ` Cody Maloney
2013-01-03 16:34 ` Miloslav Trmac
2013-01-13 9:12 ` [PATCH 2/3] chsh: Move pam auth to its own function Cody Maloney
3 siblings, 1 reply; 19+ messages in thread
From: Cody Maloney @ 2013-01-03 3:22 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 4357 bytes --]
This is based directly on lchsh which is a part of libuser.
---
login-utils/chsh.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 83 insertions(+), 2 deletions(-)
diff --git a/login-utils/chsh.c b/login-utils/chsh.c
index b5c3e2e..6db6b44 100644
--- a/login-utils/chsh.c
+++ b/login-utils/chsh.c
@@ -1,6 +1,7 @@
/*
* chsh.c -- change your login shell
* (c) 1994 by salvatore valente <svalente@athena.mit.edu>
+ * (c) 2012 by Cody Maloney <cmaloney@theoreticalchaos.com>
*
* this program is free software. you can redistribute it and
* modify it under the terms of the gnu general public license.
@@ -17,7 +18,7 @@
* suggestion from Zefram. Disallowing users with shells not in /etc/shells
* from changing their shell.
*
- * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
*/
@@ -48,11 +49,20 @@
# include "selinux_utils.h"
#endif
+
+#ifdef HAVE_LIBUSER
+# include <libuser/user.h>
+#endif
+
struct sinfo {
char *username;
char *shell;
};
+#ifdef HAVE_LIBUSER
+static int auth_lu(struct lu_context *ctx, uid_t uid, struct passwd *pw);
+#endif
+
static int auth_pam(uid_t uid, struct passwd *pw);
static void parse_argv(int argc, char **argv, struct sinfo *pinfo);
static char *prompt(char *question, char *def_val);
@@ -80,6 +90,13 @@ int main(int argc, char **argv)
struct sinfo info;
struct passwd *pw;
+#ifdef HAVE_LIBUSER
+ struct lu_context *ctx;
+ struct lu_error *error = NULL;
+ struct lu_ent *ent;
+ GValue val;
+#endif
+
sanitize_env();
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
@@ -132,7 +149,12 @@ int main(int argc, char **argv)
oldshell = _PATH_BSHELL; /* default */
/* reality check */
+#ifdef HAVE_LIBUSER
+ /* If we're setuid and not really root, disallow the password change. */
+ if (geteuid() != getuid() && uid != pw->pw_uid) {
+#else
if (uid != 0 && uid != pw->pw_uid) {
+#endif
errno = EACCES;
err(EXIT_FAILURE,
_("running UID doesn't match UID of user we're "
@@ -148,9 +170,11 @@ int main(int argc, char **argv)
printf(_("Changing shell for %s.\n"), pw->pw_name);
+#ifndef HAVE_LIBUSER
if(!auth_pam(uid, pw)) {
return EXIT_FAILURE;
}
+#endif
if (!shell) {
shell = prompt(_("New shell"), oldshell);
@@ -163,15 +187,72 @@ int main(int argc, char **argv)
if (strcmp(oldshell, shell) == 0)
errx(EXIT_SUCCESS, _("Shell not changed."));
+
+#ifdef HAVE_LIBUSER
+ ctx = lu_start(pw->pw_name, lu_user, NULL, NULL, NULL, NULL, &error);
+ if (ctx == NULL) {
+ errx(EXIT_FAILURE, _("Error initializing %s: %s.\n"), PACKAGE,
+ lu_strerror(error));
+ }
+
+ if(!auth_lu(ctx, uid, pw)) {
+ errno = EACCES;
+ errx(EXIT_FAILURE, _("Permisison denied for changing shell"));
+ }
+
+ /* Look up the user's record. */
+ ent = lu_ent_new();
+ if (lu_user_lookup_name(ctx, pw->pw_name, ent, &error) == FALSE) {
+ lu_end(ctx);
+ errx(EXIT_FAILURE, _("user \"%s\" does not exist."), pw->pw_name);
+ }
+
+ memset(&val, 0, sizeof(val));
+ g_value_init(&val, G_TYPE_STRING);
+ g_value_set_string(&val, shell);
+
+ lu_ent_clear(ent, LU_LOGINSHELL);
+ lu_ent_add(ent, LU_LOGINSHELL, &val);
+ if (!lu_user_modify(ctx, ent, &error)) {
+ g_value_unset(&val);
+ lu_ent_free(ent);
+ lu_end(ctx);
+ err(EXIT_FAILURE, _("Shell not changed: %s\n"), lu_strerror(error));
+ }
+ g_value_unset(&val);
+ lu_ent_free(ent);
+ lu_end(ctx);
+
+#else /* HAVE_LIBUSER */
pw->pw_shell = shell;
if (setpwnam(pw) < 0)
- err(EXIT_FAILURE, _("setpwnam failed\n"
+ errx(EXIT_FAILURE, _("setpwnam failed\n"
"Shell *NOT* changed. Try again later."));
+#endif /* HAVE_LIBUSER */
printf(_("Shell changed.\n"));
return EXIT_SUCCESS;
}
+#ifdef HAVE_LIBUSER
+static int auth_lu(struct lu_context *ctx, uid_t uid, struct passwd *pw) {
+ if(!lu_uses_elevated_privileges(ctx)) {
+ /* Drop privileges */
+ if (setegid(getgid()) == -1) {
+ errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
+ return FALSE;
+ }
+ if (seteuid(getuid()) == -1) {
+ errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ return auth_pam(uid, pw);
+}
+#endif
+
int auth_pam(uid_t uid, struct passwd *pw) {
#ifdef REQUIRE_PASSWORD
if (uid != 0) {
--
1.8.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH 3/3] chsh: Add libuser support
2013-01-03 3:22 ` [PATCH 3/3] chsh: Add libuser support Cody Maloney
@ 2013-01-03 16:34 ` Miloslav Trmac
2013-01-07 11:51 ` Karel Zak
0 siblings, 1 reply; 19+ messages in thread
From: Miloslav Trmac @ 2013-01-03 16:34 UTC (permalink / raw)
To: Cody Maloney; +Cc: util-linux
Hello,
----- Original Message -----
> @@ -148,9 +170,11 @@ int main(int argc, char **argv)
>
> printf(_("Changing shell for %s.\n"), pw->pw_name);
>
> +#ifndef HAVE_LIBUSER
> if(!auth_pam(uid, pw)) {
> return EXIT_FAILURE;
> }
> +#endif
>
> if (!shell) {
> shell = prompt(_("New shell"), oldshell);
> @@ -163,15 +187,72 @@ int main(int argc, char **argv)
>
> if (strcmp(oldshell, shell) == 0)
> errx(EXIT_SUCCESS, _("Shell not changed."));
> +
> +#ifdef HAVE_LIBUSER
> + ctx = lu_start(pw->pw_name, lu_user, NULL, NULL, NULL, NULL,
> &error);
AFAICS the "prompter" argument must not be NULL for LDAP to work. lu_prompt_console_quiet (not lu_prompt_console) is a good value.
> + memset(&val, 0, sizeof(val));
> + g_value_init(&val, G_TYPE_STRING);
> + g_value_set_string(&val, shell);
> +
> + lu_ent_clear(ent, LU_LOGINSHELL);
> + lu_ent_add(ent, LU_LOGINSHELL, &val);
If you don't mind depending on libuser >= 0.58, all of the above can be replaced with
> lu_ent_set_string(ent, LU_LOGINSHELL, shell);
and you can drop the "g_value_unset" calls as well.
> +#ifdef HAVE_LIBUSER
> +static int auth_lu(struct lu_context *ctx, uid_t uid, struct passwd
> *pw) {
> + if(!lu_uses_elevated_privileges(ctx)) {
> + /* Drop privileges */
"initgroups" needs to be called here to drop supplementar group memberships.
> + if (setegid(getgid()) == -1) {
> + errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
> + return FALSE;
> + }
> + if (seteuid(getuid()) == -1) {
> + errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
> + return FALSE;
> + }
> + return TRUE;
> + }
> +
> + return auth_pam(uid, pw);
> +}
> +#endif
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH 3/3] chsh: Add libuser support
2013-01-03 16:34 ` Miloslav Trmac
@ 2013-01-07 11:51 ` Karel Zak
2013-01-08 6:15 ` Cody Maloney
` (2 more replies)
0 siblings, 3 replies; 19+ messages in thread
From: Karel Zak @ 2013-01-07 11:51 UTC (permalink / raw)
To: Miloslav Trmac; +Cc: Cody Maloney, util-linux
On Thu, Jan 03, 2013 at 11:34:11AM -0500, Miloslav Trmac wrote:
> > + memset(&val, 0, sizeof(val));
> > + g_value_init(&val, G_TYPE_STRING);
> > + g_value_set_string(&val, shell);
> > +
> > + lu_ent_clear(ent, LU_LOGINSHELL);
> > + lu_ent_add(ent, LU_LOGINSHELL, &val);
> If you don't mind depending on libuser >= 0.58, all of the above can be replaced with
> > lu_ent_set_string(ent, LU_LOGINSHELL, shell);
> and you can drop the "g_value_unset" calls as well.
It would be nice to drop g_* junk :-)
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH 3/3] chsh: Add libuser support
2013-01-07 11:51 ` Karel Zak
@ 2013-01-08 6:15 ` Cody Maloney
2013-01-08 6:17 ` Cody Maloney
2013-01-08 6:18 ` Cody Maloney
2 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-08 6:15 UTC (permalink / raw)
To: Karel Zak; +Cc: Miloslav Trmac, util-linux
[-- Attachment #1: Type: text/plain, Size: 915 bytes --]
I definitely don't mind depending on the newer version. I'll update the
patch(es) with both your comments, and write up the patch for chfn. I
should have them done and sent to the list in the next couple of days.
Cody
On Mon, Jan 7, 2013 at 4:51 AM, Karel Zak <kzak@redhat.com> wrote:
> On Thu, Jan 03, 2013 at 11:34:11AM -0500, Miloslav Trmac wrote:
> > > + memset(&val, 0, sizeof(val));
> > > + g_value_init(&val, G_TYPE_STRING);
> > > + g_value_set_string(&val, shell);
> > > +
> > > + lu_ent_clear(ent, LU_LOGINSHELL);
> > > + lu_ent_add(ent, LU_LOGINSHELL, &val);
> > If you don't mind depending on libuser >= 0.58, all of the above can be
> replaced with
> > > lu_ent_set_string(ent, LU_LOGINSHELL, shell);
> > and you can drop the "g_value_unset" calls as well.
>
> It would be nice to drop g_* junk :-)
>
>
> Karel
>
> --
> Karel Zak <kzak@redhat.com>
> http://karelzak.blogspot.com
>
[-- Attachment #2: Type: text/html, Size: 1567 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] chsh: Add libuser support
2013-01-07 11:51 ` Karel Zak
2013-01-08 6:15 ` Cody Maloney
@ 2013-01-08 6:17 ` Cody Maloney
2013-01-08 6:18 ` Cody Maloney
2 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-08 6:17 UTC (permalink / raw)
To: Karel Zak; +Cc: Miloslav Trmac, util-linux
[-- Attachment #1: Type: text/plain, Size: 909 bytes --]
I definitely don't mind depending on the newer version. I'll update the
patch(es) with both your comments, and write up the patch for chfn. I
should have them done and sent to the list in the next couple of days.
On Mon, Jan 7, 2013 at 4:51 AM, Karel Zak <kzak@redhat.com> wrote:
> On Thu, Jan 03, 2013 at 11:34:11AM -0500, Miloslav Trmac wrote:
> > > + memset(&val, 0, sizeof(val));
> > > + g_value_init(&val, G_TYPE_STRING);
> > > + g_value_set_string(&val, shell);
> > > +
> > > + lu_ent_clear(ent, LU_LOGINSHELL);
> > > + lu_ent_add(ent, LU_LOGINSHELL, &val);
> > If you don't mind depending on libuser >= 0.58, all of the above can be
> replaced with
> > > lu_ent_set_string(ent, LU_LOGINSHELL, shell);
> > and you can drop the "g_value_unset" calls as well.
>
> It would be nice to drop g_* junk :-)
>
>
> Karel
>
> --
> Karel Zak <kzak@redhat.com>
> http://karelzak.blogspot.com
>
[-- Attachment #2: Type: text/html, Size: 1606 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] chsh: Add libuser support
2013-01-07 11:51 ` Karel Zak
2013-01-08 6:15 ` Cody Maloney
2013-01-08 6:17 ` Cody Maloney
@ 2013-01-08 6:18 ` Cody Maloney
2 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-08 6:18 UTC (permalink / raw)
Cc: util-linux
I definitely don't mind depending on the newer version. I'll update
the patch(es) with both your comments, and write up the patch for
chfn. I should have them done and sent to the list in the next couple
of days.
On Mon, Jan 7, 2013 at 4:51 AM, Karel Zak <kzak@redhat.com> wrote:
> On Thu, Jan 03, 2013 at 11:34:11AM -0500, Miloslav Trmac wrote:
>> > + memset(&val, 0, sizeof(val));
>> > + g_value_init(&val, G_TYPE_STRING);
>> > + g_value_set_string(&val, shell);
>> > +
>> > + lu_ent_clear(ent, LU_LOGINSHELL);
>> > + lu_ent_add(ent, LU_LOGINSHELL, &val);
>> If you don't mind depending on libuser >= 0.58, all of the above can be replaced with
>> > lu_ent_set_string(ent, LU_LOGINSHELL, shell);
>> and you can drop the "g_value_unset" calls as well.
>
> It would be nice to drop g_* junk :-)
>
>
> Karel
>
> --
> Karel Zak <kzak@redhat.com>
> http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 2/3] chsh: Move pam auth to its own function.
2013-01-03 3:21 ` [PATCH 0/3] Add support for using libuser to chsh Cody Maloney
` (2 preceding siblings ...)
2013-01-03 3:22 ` [PATCH 3/3] chsh: Add libuser support Cody Maloney
@ 2013-01-13 9:12 ` Cody Maloney
3 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-13 9:12 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
This makes it easier to add support for libuser, which needs the same PAM
authentication.
Signed-off-by: Cody Maloney <cmaloney@theoreticalchaos.com>
---
login-utils/chsh.c | 54 +++++++++++++++++++++++++++++++-----------------------
1 file changed, 31 insertions(+), 23 deletions(-)
diff --git a/login-utils/chsh.c b/login-utils/chsh.c
index 6e9325d..b5c3e2e 100644
--- a/login-utils/chsh.c
+++ b/login-utils/chsh.c
@@ -53,6 +53,7 @@ struct sinfo {
char *shell;
};
+static int auth_pam(uid_t uid, struct passwd *pw);
static void parse_argv(int argc, char **argv, struct sinfo *pinfo);
static char *prompt(char *question, char *def_val);
static int check_shell(char *shell);
@@ -147,6 +148,31 @@ int main(int argc, char **argv)
printf(_("Changing shell for %s.\n"), pw->pw_name);
+ if(!auth_pam(uid, pw)) {
+ return EXIT_FAILURE;
+ }
+
+ if (!shell) {
+ shell = prompt(_("New shell"), oldshell);
+ if (!shell)
+ return EXIT_SUCCESS;
+ }
+
+ if (check_shell(shell) < 0)
+ return EXIT_FAILURE;
+
+ if (strcmp(oldshell, shell) == 0)
+ errx(EXIT_SUCCESS, _("Shell not changed."));
+ pw->pw_shell = shell;
+ if (setpwnam(pw) < 0)
+ err(EXIT_FAILURE, _("setpwnam failed\n"
+ "Shell *NOT* changed. Try again later."));
+
+ printf(_("Shell changed.\n"));
+ return EXIT_SUCCESS;
+}
+
+int auth_pam(uid_t uid, struct passwd *pw) {
#ifdef REQUIRE_PASSWORD
if (uid != 0) {
pam_handle_t *pamh = NULL;
@@ -155,47 +181,29 @@ int main(int argc, char **argv)
retcode = pam_start("chsh", pw->pw_name, &conv, &pamh);
if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
+ return FALSE;
retcode = pam_authenticate(pamh, 0);
if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
+ return FALSE;
retcode = pam_acct_mgmt(pamh, 0);
if (retcode == PAM_NEW_AUTHTOK_REQD)
retcode =
pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
+ return FALSE;
retcode = pam_setcred(pamh, 0);
if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
+ return FALSE;
pam_end(pamh, 0);
/* no need to establish a session; this isn't a
* session-oriented activity... */
}
+ return TRUE;
#endif /* REQUIRE_PASSWORD */
-
- if (!shell) {
- shell = prompt(_("New shell"), oldshell);
- if (!shell)
- return EXIT_SUCCESS;
- }
-
- if (check_shell(shell) < 0)
- return EXIT_FAILURE;
-
- if (strcmp(oldshell, shell) == 0)
- errx(EXIT_SUCCESS, _("Shell not changed."));
- pw->pw_shell = shell;
- if (setpwnam(pw) < 0)
- err(EXIT_FAILURE, _("setpwnam failed\n"
- "Shell *NOT* changed. Try again later."));
-
- printf(_("Shell changed.\n"));
- return EXIT_SUCCESS;
}
/*
--
1.8.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 1/4] chsh-chfn: Add flag for enabling/disabling libuser support.
2013-01-13 9:12 [PATCH v2 0/4] Add support for using libuser to chsh and chfn Cody Maloney
2013-01-03 3:21 ` [PATCH 0/3] Add support for using libuser to chsh Cody Maloney
@ 2013-01-13 9:12 ` Cody Maloney
2013-01-13 9:12 ` [PATCH v2 2/4] chsh-chfn: Move pam auth to its own function, factoring out common code Cody Maloney
` (3 subsequent siblings)
5 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-13 9:12 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
Signed-off-by: Cody Maloney <cmaloney@theoreticalchaos.com>
---
configure.ac | 17 +++++++++++++++++
login-utils/Makemodule.am | 5 +++++
2 files changed, 22 insertions(+)
diff --git a/configure.ac b/configure.ac
index e937736..dd846cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1100,6 +1100,23 @@ AS_HELP_STRING([--disable-chsh-only-listed], [chsh: allow shells not in /etc/she
[], enable_chsh_only_listed=yes
)
+AC_ARG_WITH([libuser], AS_HELP_STRING([--without-libuser], [compile without libuser (remote chsh)]),
+ [], with_user=auto
+)
+
+if test "x$with_user" = xno; then
+ AM_CONDITIONAL(HAVE_USER, false)
+else
+ PKG_CHECK_MODULES(LIBUSER,[libuser >= 0.58])
+ UL_CHECK_LIB(user, lu_start)
+ case "$with_user:$have_user" in
+ yes:no)
+ AC_MSG_ERROR([user selected but libuser not found])
+ ;;
+ esac
+fi
+
+
if test "x$enable_chsh_only_listed" = xyes; then
AC_DEFINE(ONLY_LISTED_SHELLS, 1, [Should chsh allow only shells in /etc/shells?])
fi
diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
index aef8177..479b87b 100644
--- a/login-utils/Makemodule.am
+++ b/login-utils/Makemodule.am
@@ -68,6 +68,11 @@ chfn_chsh_cflags = $(SUID_CFLAGS) $(AM_CFLAGS)
chfn_chsh_ldflags = $(SUID_LDFLAGS) $(AM_LDFLAGS)
chfn_chsh_ldadd = libcommon.la -lpam -lpam_misc
+if HAVE_USER
+chfn_chsh_ldflags += $(LIBUSER_LIBS)
+chfn_chsh_cflags += $(LIBUSER_CFLAGS)
+endif
+
if HAVE_SELINUX
chfn_chsh_sources += \
login-utils/selinux_utils.c \
--
1.8.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v2 2/4] chsh-chfn: Move pam auth to its own function, factoring out common code
2013-01-13 9:12 [PATCH v2 0/4] Add support for using libuser to chsh and chfn Cody Maloney
2013-01-03 3:21 ` [PATCH 0/3] Add support for using libuser to chsh Cody Maloney
2013-01-13 9:12 ` [PATCH v2 1/4] chsh-chfn: Add flag for enabling/disabling libuser support Cody Maloney
@ 2013-01-13 9:12 ` Cody Maloney
2013-01-13 9:12 ` [PATCH v2 3/4] chsh: Add libuser support Cody Maloney
` (2 subsequent siblings)
5 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-13 9:12 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
This makes it easier to add support for libuser, which needs the same PAM
authentication. Also removes duplicate code between chsh and chfn.
Signed-off-by: Cody Maloney <cmaloney@theoreticalchaos.com>
---
login-utils/Makemodule.am | 2 ++
login-utils/auth.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
login-utils/auth.h | 13 +++++++++++++
login-utils/chfn.c | 33 +++------------------------------
login-utils/chsh.c | 33 +++------------------------------
5 files changed, 68 insertions(+), 60 deletions(-)
create mode 100644 login-utils/auth.c
create mode 100644 login-utils/auth.h
diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
index 479b87b..ee85329 100644
--- a/login-utils/Makemodule.am
+++ b/login-utils/Makemodule.am
@@ -62,6 +62,8 @@ dist_man_MANS += \
chfn_chsh_sources = \
login-utils/islocal.c \
login-utils/islocal.h \
+ login-utils/auth.c \
+ login-utils/auth.h \
login-utils/setpwnam.c \
login-utils/setpwnam.h
chfn_chsh_cflags = $(SUID_CFLAGS) $(AM_CFLAGS)
diff --git a/login-utils/auth.c b/login-utils/auth.c
new file mode 100644
index 0000000..373bd22
--- /dev/null
+++ b/login-utils/auth.c
@@ -0,0 +1,47 @@
+/*
+ * auth.c -- PAM authorization code, common between chsh and chfn
+ * (c) 2012 by Cody Maloney <cmaloney@theoreticalchaos.com>
+ *
+ * this program is free software. you can redistribute it and
+ * modify it under the terms of the gnu general public license.
+ * there is no warranty.
+ *
+ */
+
+#include "auth.h"
+
+#include "pamfail.h"
+
+int auth_pam(const char *service_name, uid_t uid, const char *username) {
+#ifdef REQUIRE_PASSWORD
+ if (uid != 0) {
+ pam_handle_t *pamh = NULL;
+ struct pam_conv conv = { misc_conv, NULL };
+ int retcode;
+
+ retcode = pam_start(service_name, username, &conv, &pamh);
+ if (pam_fail_check(pamh, retcode))
+ return FALSE;
+
+ retcode = pam_authenticate(pamh, 0);
+ if (pam_fail_check(pamh, retcode))
+ return FALSE;
+
+ retcode = pam_acct_mgmt(pamh, 0);
+ if (retcode == PAM_NEW_AUTHTOK_REQD)
+ retcode =
+ pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (pam_fail_check(pamh, retcode))
+ return FALSE;
+
+ retcode = pam_setcred(pamh, 0);
+ if (pam_fail_check(pamh, retcode))
+ return FALSE;
+
+ pam_end(pamh, 0);
+ /* no need to establish a session; this isn't a
+ * session-oriented activity... */
+ }
+ return TRUE;
+#endif /* REQUIRE_PASSWORD */
+}
diff --git a/login-utils/auth.h b/login-utils/auth.h
new file mode 100644
index 0000000..bf7c369
--- /dev/null
+++ b/login-utils/auth.h
@@ -0,0 +1,13 @@
+/*
+ * auth.h -- PAM authorization code, common between chsh and chfn
+ * (c) 2012 by Cody Maloney <cmaloney@theoreticalchaos.com>
+ *
+ * this program is free software. you can redistribute it and
+ * modify it under the terms of the gnu general public license.
+ * there is no warranty.
+ *
+ */
+
+#include <sys/types.h>
+
+extern int auth_pam(const char *service_name, uid_t uid, const char *username);
diff --git a/login-utils/chfn.c b/login-utils/chfn.c
index 76c0b03..e189558 100644
--- a/login-utils/chfn.c
+++ b/login-utils/chfn.c
@@ -31,12 +31,12 @@
#include <sys/types.h>
#include <unistd.h>
+#include "auth.h"
#include "c.h"
#include "env.h"
#include "closestream.h"
#include "islocal.h"
#include "nls.h"
-#include "pamfail.h"
#include "setpwnam.h"
#include "strutils.h"
#include "xalloc.h"
@@ -157,36 +157,9 @@ int main(int argc, char **argv)
printf(_("Changing finger information for %s.\n"), oldf.username);
-#ifdef REQUIRE_PASSWORD
- if (uid != 0) {
- pam_handle_t *pamh = NULL;
- struct pam_conv conv = { misc_conv, NULL };
- int retcode;
-
- retcode = pam_start("chfn", oldf.username, &conv, &pamh);
- if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
-
- retcode = pam_authenticate(pamh, 0);
- if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
-
- retcode = pam_acct_mgmt(pamh, 0);
- if (retcode == PAM_NEW_AUTHTOK_REQD)
- retcode =
- pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
- if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
-
- retcode = pam_setcred(pamh, 0);
- if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
-
- pam_end(pamh, 0);
- /* no need to establish a session; this isn't a
- * session-oriented activity... */
+ if(!auth_pam("chfn", uid, oldf.username)) {
+ return EXIT_FAILURE;
}
-#endif /* REQUIRE_PASSWORD */
if (interactive)
ask_info(&oldf, &newf);
diff --git a/login-utils/chsh.c b/login-utils/chsh.c
index 6e9325d..4113df5 100644
--- a/login-utils/chsh.c
+++ b/login-utils/chsh.c
@@ -32,12 +32,12 @@
#include <sys/types.h>
#include <unistd.h>
+#include "auth.h"
#include "c.h"
#include "env.h"
#include "closestream.h"
#include "islocal.h"
#include "nls.h"
-#include "pamfail.h"
#include "pathnames.h"
#include "setpwnam.h"
#include "xalloc.h"
@@ -147,36 +147,9 @@ int main(int argc, char **argv)
printf(_("Changing shell for %s.\n"), pw->pw_name);
-#ifdef REQUIRE_PASSWORD
- if (uid != 0) {
- pam_handle_t *pamh = NULL;
- struct pam_conv conv = { misc_conv, NULL };
- int retcode;
-
- retcode = pam_start("chsh", pw->pw_name, &conv, &pamh);
- if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
-
- retcode = pam_authenticate(pamh, 0);
- if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
-
- retcode = pam_acct_mgmt(pamh, 0);
- if (retcode == PAM_NEW_AUTHTOK_REQD)
- retcode =
- pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
- if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
-
- retcode = pam_setcred(pamh, 0);
- if (pam_fail_check(pamh, retcode))
- return EXIT_FAILURE;
-
- pam_end(pamh, 0);
- /* no need to establish a session; this isn't a
- * session-oriented activity... */
+ if(!auth_pam("chsh", uid, pw->pw_name)) {
+ return EXIT_FAILURE;
}
-#endif /* REQUIRE_PASSWORD */
if (!shell) {
shell = prompt(_("New shell"), oldshell);
--
1.8.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v2 3/4] chsh: Add libuser support
2013-01-13 9:12 [PATCH v2 0/4] Add support for using libuser to chsh and chfn Cody Maloney
` (2 preceding siblings ...)
2013-01-13 9:12 ` [PATCH v2 2/4] chsh-chfn: Move pam auth to its own function, factoring out common code Cody Maloney
@ 2013-01-13 9:12 ` Cody Maloney
2013-01-14 18:16 ` Miloslav Trmac
2013-01-13 9:12 ` [PATCH v2 4/4] chfn: " Cody Maloney
[not found] ` <50F2FBBE.7000305@gmail.com>
5 siblings, 1 reply; 19+ messages in thread
From: Cody Maloney @ 2013-01-13 9:12 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 6263 bytes --]
This is based directly on lchsh which is a part of libuser. libuser.{c,h}
exist because exactly the same code is needed for both chsh and chfn.
Signed-off-by: Cody Maloney <cmaloney@theoreticalchaos.com>
---
login-utils/Makemodule.am | 3 ++
login-utils/chsh.c | 24 ++++++++++++--
login-utils/libuser.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++
login-utils/libuser.h | 14 ++++++++
4 files changed, 123 insertions(+), 2 deletions(-)
create mode 100644 login-utils/libuser.c
create mode 100644 login-utils/libuser.h
diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
index ee85329..0c57118 100644
--- a/login-utils/Makemodule.am
+++ b/login-utils/Makemodule.am
@@ -73,6 +73,9 @@ chfn_chsh_ldadd = libcommon.la -lpam -lpam_misc
if HAVE_USER
chfn_chsh_ldflags += $(LIBUSER_LIBS)
chfn_chsh_cflags += $(LIBUSER_CFLAGS)
+chfn_chsh_sources+= \
+ login-utils/libuser.c \
+ login-utils/libuser.h
endif
if HAVE_SELINUX
diff --git a/login-utils/chsh.c b/login-utils/chsh.c
index 4113df5..fa2fa84 100644
--- a/login-utils/chsh.c
+++ b/login-utils/chsh.c
@@ -1,6 +1,7 @@
/*
* chsh.c -- change your login shell
* (c) 1994 by salvatore valente <svalente@athena.mit.edu>
+ * (c) 2012 by Cody Maloney <cmaloney@theoreticalchaos.com>
*
* this program is free software. you can redistribute it and
* modify it under the terms of the gnu general public license.
@@ -17,7 +18,7 @@
* suggestion from Zefram. Disallowing users with shells not in /etc/shells
* from changing their shell.
*
- * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
*/
@@ -32,7 +33,6 @@
#include <sys/types.h>
#include <unistd.h>
-#include "auth.h"
#include "c.h"
#include "env.h"
#include "closestream.h"
@@ -48,6 +48,14 @@
# include "selinux_utils.h"
#endif
+
+#ifdef HAVE_LIBUSER
+# include <libuser/user.h>
+# include "libuser.h"
+#else
+# include "auth.h"
+#endif
+
struct sinfo {
char *username;
char *shell;
@@ -131,7 +139,12 @@ int main(int argc, char **argv)
oldshell = _PATH_BSHELL; /* default */
/* reality check */
+#ifdef HAVE_LIBUSER
+ /* If we're setuid and not really root, disallow the password change. */
+ if (geteuid() != getuid() && uid != pw->pw_uid) {
+#else
if (uid != 0 && uid != pw->pw_uid) {
+#endif
errno = EACCES;
err(EXIT_FAILURE,
_("running UID doesn't match UID of user we're "
@@ -147,9 +160,11 @@ int main(int argc, char **argv)
printf(_("Changing shell for %s.\n"), pw->pw_name);
+#ifndef HAVE_LIBUSER
if(!auth_pam("chsh", uid, pw->pw_name)) {
return EXIT_FAILURE;
}
+#endif
if (!shell) {
shell = prompt(_("New shell"), oldshell);
@@ -162,10 +177,15 @@ int main(int argc, char **argv)
if (strcmp(oldshell, shell) == 0)
errx(EXIT_SUCCESS, _("Shell not changed."));
+
+#ifdef HAVE_LIBUSER
+ set_value_libuser("chsh", pw->pw_name, uid, LU_LOGINSHELL, shell);
+#else
pw->pw_shell = shell;
if (setpwnam(pw) < 0)
err(EXIT_FAILURE, _("setpwnam failed\n"
"Shell *NOT* changed. Try again later."));
+#endif
printf(_("Shell changed.\n"));
return EXIT_SUCCESS;
diff --git a/login-utils/libuser.c b/login-utils/libuser.c
new file mode 100644
index 0000000..9a3e3b1
--- /dev/null
+++ b/login-utils/libuser.c
@@ -0,0 +1,84 @@
+/*
+ * libuser.c -- Utilize libuser to set a user attribute
+ * (c) 2012 by Cody Maloney <cmaloney@theoreticalchaos.com>
+ *
+ * this program is free software. you can redistribute it and
+ * modify it under the terms of the gnu general public license.
+ * there is no warranty.
+ *
+ */
+
+#include "libuser.h"
+
+#include <grp.h>
+#include <libuser/user.h>
+#include <unistd.h>
+
+#include "auth.h"
+#include "c.h"
+#include "nls.h"
+
+static int auth_lu(const char *service_name, struct lu_context *ctx, uid_t uid,
+ const char *username);
+
+static int auth_lu(const char *service_name, struct lu_context *ctx, uid_t uid,
+ const char *username) {
+ if(!lu_uses_elevated_privileges(ctx)) {
+ /* Drop privileges */
+ if (setegid(getgid()) == -1) {
+ errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
+ return FALSE;
+ }
+ if (seteuid(getuid()) == -1) {
+ errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
+ return FALSE;
+ }
+ if (initgroups(username, 0)) {
+ errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ return auth_pam(service_name, uid, username);
+}
+
+int set_value_libuser(const char *service_name, const char *username, uid_t uid,
+ const char *attr, const char *val) {
+ struct lu_context *ctx;
+ struct lu_error *error = NULL;
+ struct lu_ent *ent;
+
+ ctx = lu_start(username, lu_user, NULL, NULL, lu_prompt_console_quiet,
+ NULL, &error);
+ if (ctx == NULL) {
+ err(EXIT_FAILURE, _("Error initializing %s: %s.\n"), PACKAGE,
+ lu_strerror(error));
+ return FALSE;
+ }
+
+ if(!auth_lu(service_name, ctx, uid, username)) {
+ errno = EACCES;
+ err(EXIT_FAILURE, _("Permisison denied for changing user attribute"));
+ return FALSE;
+ }
+
+ /* Look up the user's record. */
+ ent = lu_ent_new();
+ if (lu_user_lookup_name(ctx, username, ent, &error) == FALSE) {
+ lu_end(ctx);
+ err(EXIT_FAILURE, _("user \"%s\" does not exist."), username);
+ return FALSE;
+ }
+
+ lu_ent_set_string(ent, attr, val);
+ if (!lu_user_modify(ctx, ent, &error)) {
+ lu_ent_free(ent);
+ lu_end(ctx);
+ err(EXIT_FAILURE, _("Shell not changed: %s\n"), lu_strerror(error));
+ return FALSE;
+ }
+ lu_ent_free(ent);
+ lu_end(ctx);
+ return TRUE;
+}
diff --git a/login-utils/libuser.h b/login-utils/libuser.h
new file mode 100644
index 0000000..7454b99
--- /dev/null
+++ b/login-utils/libuser.h
@@ -0,0 +1,14 @@
+/*
+ * libuser.h -- Utilize libuser to set a user attribute
+ * (c) 2012 by Cody Maloney <cmaloney@theoreticalchaos.com>
+ *
+ * this program is free software. you can redistribute it and
+ * modify it under the terms of the gnu general public license.
+ * there is no warranty.
+ *
+ */
+
+#include <sys/types.h>
+
+extern int set_value_libuser(const char *service_name, const char *username,
+ uid_t uid, const char *attr, const char *val);
--
1.8.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v2 3/4] chsh: Add libuser support
2013-01-13 9:12 ` [PATCH v2 3/4] chsh: Add libuser support Cody Maloney
@ 2013-01-14 18:16 ` Miloslav Trmac
2013-01-17 0:52 ` Cody Maloney
0 siblings, 1 reply; 19+ messages in thread
From: Miloslav Trmac @ 2013-01-14 18:16 UTC (permalink / raw)
To: Cody Maloney; +Cc: util-linux
Hello,
----- Original Message -----
> diff --git a/login-utils/libuser.c b/login-utils/libuser.c
> new file mode 100644
> index 0000000..9a3e3b1
> --- /dev/null
> +++ b/login-utils/libuser.c
> +static int auth_lu(const char *service_name, struct lu_context *ctx,
> uid_t uid,
> + const char *username) {
> + if(!lu_uses_elevated_privileges(ctx)) {
> + /* Drop privileges */
> + if (setegid(getgid()) == -1) {
> + errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
> + return FALSE;
> + }
> + if (seteuid(getuid()) == -1) {
> + errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
> + return FALSE;
> + }
> + if (initgroups(username, 0)) {
> + errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
> + return FALSE;
> + }
I can't see how this can work: after seteuid() the program no longer has root privileges (CAP_SETGID) to change the groups.
(On second thought, if the program is setuid, the setuid execution mechanism doesn't change supplementary groups, so perhaps the call isn't strictly necessary; Still, initializing the groups makes the environment more deterministic. And as long as initgroups() is called, it should be called in a way that works.)
> + lu_ent_set_string(ent, attr, val);
> + if (!lu_user_modify(ctx, ent, &error)) {
> + lu_ent_free(ent);
> + lu_end(ctx);
> + err(EXIT_FAILURE, _("Shell not changed: %s\n"),
> lu_strerror(error));
This error message is fine for chsh, but not great for chfn.
Mirek
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v2 3/4] chsh: Add libuser support
2013-01-14 18:16 ` Miloslav Trmac
@ 2013-01-17 0:52 ` Cody Maloney
2013-01-28 22:01 ` Miloslav Trmac
0 siblings, 1 reply; 19+ messages in thread
From: Cody Maloney @ 2013-01-17 0:52 UTC (permalink / raw)
To: Miloslav Trmac; +Cc: util-linux
On Mon, Jan 14, 2013 at 10:16 AM, Miloslav Trmac <mitr@redhat.com> wrote:
> Hello,
> ----- Original Message -----
>> diff --git a/login-utils/libuser.c b/login-utils/libuser.c
>> new file mode 100644
>> index 0000000..9a3e3b1
>> --- /dev/null
>> +++ b/login-utils/libuser.c
>> +static int auth_lu(const char *service_name, struct lu_context *ctx,
>> uid_t uid,
>> + const char *username) {
>> + if(!lu_uses_elevated_privileges(ctx)) {
>> + /* Drop privileges */
>> + if (setegid(getgid()) == -1) {
>> + errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
>> + return FALSE;
>> + }
>> + if (seteuid(getuid()) == -1) {
>> + errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
>> + return FALSE;
>> + }
>> + if (initgroups(username, 0)) {
>> + errx(EXIT_FAILURE, _("Couldn't drop group privileges"));
>> + return FALSE;
>> + }
>
> I can't see how this can work: after seteuid() the program no longer has root privileges (CAP_SETGID) to change the groups.
>
> (On second thought, if the program is setuid, the setuid execution mechanism doesn't change supplementary groups, so perhaps the call isn't strictly necessary; Still, initializing the groups makes the environment more deterministic. And as long as initgroups() is called, it should be called in a way that works.)
I'm fine with/would prefer dropping the initgroups entirely (That the
initgroups man page, at least on my system, specifically talks about
reading them from /etc/group, never mentioning nss worries me). If
that's okay with you, otherwise I can move it to the beginning of
dropping privileges.
>
>> + lu_ent_set_string(ent, attr, val);
>> + if (!lu_user_modify(ctx, ent, &error)) {
>> + lu_ent_free(ent);
>> + lu_end(ctx);
>> + err(EXIT_FAILURE, _("Shell not changed: %s\n"),
>> lu_strerror(error));
>
> This error message is fine for chsh, but not great for chfn.
Good catch. I'll change it to "Unable to change user attribute".
Thanks,
Cody
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v2 3/4] chsh: Add libuser support
2013-01-17 0:52 ` Cody Maloney
@ 2013-01-28 22:01 ` Miloslav Trmac
0 siblings, 0 replies; 19+ messages in thread
From: Miloslav Trmac @ 2013-01-28 22:01 UTC (permalink / raw)
To: Cody Maloney; +Cc: util-linux
Hello,
----- Original Message -----
> On Mon, Jan 14, 2013 at 10:16 AM, Miloslav Trmac <mitr@redhat.com>
> wrote:
> > (On second thought, if the program is setuid, the setuid execution
> > mechanism doesn't change supplementary groups, so perhaps the call
> > isn't strictly necessary; Still, initializing the groups makes the
> > environment more deterministic. And as long as initgroups() is
> > called, it should be called in a way that works.)
>
> I'm fine with/would prefer dropping the initgroups entirely (That the
> initgroups man page, at least on my system, specifically talks about
> reading them from /etc/group, never mentioning nss worries me). If
> that's okay with you, otherwise I can move it to the beginning of
> dropping privileges.
Sorry about the late reply; after discussing it with colleagues, it seems that dropping the initgroups() is completely safe here.
Mirek
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 4/4] chfn: Add libuser support
2013-01-13 9:12 [PATCH v2 0/4] Add support for using libuser to chsh and chfn Cody Maloney
` (3 preceding siblings ...)
2013-01-13 9:12 ` [PATCH v2 3/4] chsh: Add libuser support Cody Maloney
@ 2013-01-13 9:12 ` Cody Maloney
[not found] ` <50F2FBBE.7000305@gmail.com>
5 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-13 9:12 UTC (permalink / raw)
To: util-linux; +Cc: mitr, Cody Maloney
Signed-off-by: Cody Maloney <cmaloney@theoreticalchaos.com>
---
login-utils/chfn.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/login-utils/chfn.c b/login-utils/chfn.c
index e189558..80abefa 100644
--- a/login-utils/chfn.c
+++ b/login-utils/chfn.c
@@ -1,6 +1,7 @@
/*
* chfn.c -- change your finger information
* (c) 1994 by salvatore valente <svalente@athena.mit.edu>
+ * (c) 2012 by Cody Maloney <cmaloney@theoreticalchaos.com>
*
* this program is free software. you can redistribute it and
* modify it under the terms of the gnu general public license.
@@ -31,7 +32,6 @@
#include <sys/types.h>
#include <unistd.h>
-#include "auth.h"
#include "c.h"
#include "env.h"
#include "closestream.h"
@@ -47,6 +47,13 @@
# include "selinux_utils.h"
#endif
+#ifdef HAVE_LIBUSER
+# include <libuser/user.h>
+# include "libuser.h"
+#else
+# include "auth.h"
+#endif
+
static char buf[1024];
struct finfo {
@@ -149,17 +156,24 @@ int main(int argc, char **argv)
}
#endif
- /* Reality check */
- if (uid != 0 && uid != oldf.pw->pw_uid) {
+#ifdef HAVE_LIBUSER
+ /* If we're setuid and not really root, disallow the password change. */
+ if (geteuid() != getuid() && uid != pw->pw_uid) {
+#else
+ if (uid != 0 && uid != pw->pw_uid) {
+#endif
errno = EACCES;
- err(EXIT_FAILURE, NULL);
+ err(EXIT_FAILURE, _("running UID doesn't match UID of user we're "
+ "altering, change denied")););
}
printf(_("Changing finger information for %s.\n"), oldf.username);
+#ifndef HAVE_LIBUSER
if(!auth_pam("chfn", uid, oldf.username)) {
return EXIT_FAILURE;
}
+#endif
if (interactive)
ask_info(&oldf, &newf);
@@ -445,9 +459,14 @@ static int save_new_data(struct finfo *pinfo)
gecos[len] = 0;
}
+#ifdef HAVE_LIBUSER
+ if(set_value_libuser("chfn", pinfo->pw->pw_name, pinfo->pw->pw_uid,
+ LU_GECOS, gecos)) {
+#else /* HAVE_LIBUSER */
/* write the new struct passwd to the passwd file. */
pinfo->pw->pw_gecos = gecos;
if (setpwnam(pinfo->pw) < 0) {
+#endif
warn("setpwnam");
printf(_
("Finger information *NOT* changed. Try again later.\n"));
--
1.8.1
^ permalink raw reply related [flat|nested] 19+ messages in thread[parent not found: <50F2FBBE.7000305@gmail.com>]
* Re: [PATCH v2 0/4] Add support for using libuser to chsh and chfn
[not found] ` <50F2FBBE.7000305@gmail.com>
@ 2013-01-13 19:31 ` Cody Maloney
0 siblings, 0 replies; 19+ messages in thread
From: Cody Maloney @ 2013-01-13 19:31 UTC (permalink / raw)
To: Bruce Dubbs, util-linux
>
> I'm not sure if I understand the changes completely, but it does not appear
> that the changes adding PAM to chfn and chsh are optional. By default, we
> do not use PAM and need a way build these programs without it.
>
If you look at the patch where I extract the pam function (2/4), I
don't change the code flow in the case where pam is not used
(REQUIRE_PASSWORD isn't defined). By default, REQUIRE_PASSWORD is
defined (and can be disabled with the configure flag
--disable-required-password).
Whether or not the pam headers are included has not changed. (They
were included previously even when REQUIRE_PASSWORD wasn't defined),
see patch 2/4. This means if you tried to build either of these
without the PAM headers on your system previously, it wouldn't of
worked. This may be a bug in and of itself which would be relatively
simple to fix now (don't compile/link auth.c, ifdef out the auth_pam
call, and remove the ifdefs from auth_pam.c).
In the case that the programs are run by root and REQUIRE_PASSWORD is
defined, the PAM authentication has an auth bypass for when run by
root (but not just setuid).
The libuser code is entirely optional, and does not mandate PAM in and of
itself. if you turn off REQUIRE_PASSWORD, libuser won't require a
password from the user as it's password from the user goes through the
same auth_pam function to get the password. Without REQUIRE_PASSWORD,
we basically just do any auth that libuser requires internally (A
password to an LDAP server, potentially, for instance), then don't
further authenticate the user via PAM.
I hope that answers/addresses your concerns, if not let me know.
Cody
>
> -- Bruce Dubbs
> linuxfromscratch.org
^ permalink raw reply [flat|nested] 19+ messages in thread