summaryrefslogtreecommitdiffstats
path: root/src/newgrp.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-26 16:18:37 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-26 16:18:37 +0000
commitb6b00dd55e035bfbe311a527b567962ffa77ee43 (patch)
treecafc4d13785448e5a78bd40a51697ee07f07ac12 /src/newgrp.c
parentAdding debian version 1:4.13+dfsg1-5. (diff)
downloadshadow-b6b00dd55e035bfbe311a527b567962ffa77ee43.tar.xz
shadow-b6b00dd55e035bfbe311a527b567962ffa77ee43.zip
Merging upstream version 1:4.15.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/newgrp.c127
1 files changed, 58 insertions, 69 deletions
diff --git a/src/newgrp.c b/src/newgrp.c
index 9982083..1b3d76b 100644
--- a/src/newgrp.c
+++ b/src/newgrp.c
@@ -16,20 +16,24 @@
#include <pwd.h>
#include <stdio.h>
#include <assert.h>
+
+#include "agetpass.h"
+#include "alloc.h"
#include "defines.h"
#include "getdef.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+
/*
* Global variables
*/
-const char *Prog;
+static const char *Prog;
extern char **newenvp;
-extern char **environ;
#ifdef HAVE_SETGROUPS
static int ngroups;
@@ -158,7 +162,7 @@ static void check_perms (const struct group *grp,
* get the password from her, and set the salt for
* the decryption from the group file.
*/
- cp = getpass (_("Password: "));
+ cp = agetpass (_("Password: "));
if (NULL == cp) {
goto failure;
}
@@ -169,7 +173,7 @@ static void check_perms (const struct group *grp,
* must match the previously encrypted value in the file.
*/
cpasswd = pw_encrypt (cp, grp->gr_passwd);
- strzero (cp);
+ erase_pass (cp);
if (NULL == cpasswd) {
fprintf (stderr,
@@ -184,12 +188,10 @@ static void check_perms (const struct group *grp,
if (grp->gr_passwd[0] == '\0' ||
strcmp (cpasswd, grp->gr_passwd) != 0) {
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "authentication new-gid=%lu",
- (unsigned long) grp->gr_gid);
+ SNPRINTF(audit_buf, "authentication new-gid=%lu",
+ (unsigned long) grp->gr_gid);
audit_logger (AUDIT_GRP_AUTH, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
#endif
SYSLOG ((LOG_INFO,
"Invalid password for group '%s' from '%s'",
@@ -199,12 +201,10 @@ static void check_perms (const struct group *grp,
goto failure;
}
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "authentication new-gid=%lu",
- (unsigned long) grp->gr_gid);
+ SNPRINTF(audit_buf, "authentication new-gid=%lu",
+ (unsigned long) grp->gr_gid);
audit_logger (AUDIT_GRP_AUTH, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 1);
+ audit_buf, NULL, getuid (), 1);
#endif
}
@@ -217,21 +217,17 @@ failure:
closelog ();
#ifdef WITH_AUDIT
if (groupname) {
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-group=%s", groupname);
+ SNPRINTF(audit_buf, "changing new-group=%s", groupname);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
} else {
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
}
#endif
exit (EXIT_FAILURE);
}
-#ifdef USE_SYSLOG
/*
* syslog_sg - log the change of group to syslog
*
@@ -292,6 +288,9 @@ static void syslog_sg (const char *name, const char *group)
(void) signal (SIGTSTP, SIG_IGN);
(void) signal (SIGTTIN, SIG_IGN);
(void) signal (SIGTTOU, SIG_IGN);
+ /* set SIGCHLD to default for waitpid */
+ (void) signal(SIGCHLD, SIG_DFL);
+
child = fork ();
if ((pid_t)-1 == child) {
/* error in fork() */
@@ -299,15 +298,13 @@ static void syslog_sg (const char *name, const char *group)
is_newgrp ? "newgrp" : "sg", strerror (errno));
#ifdef WITH_AUDIT
if (group) {
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-group=%s", group);
+ SNPRINTF(audit_buf,
+ "changing new-group=%s", group);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
} else {
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
}
#endif
exit (EXIT_FAILURE);
@@ -365,7 +362,6 @@ static void syslog_sg (const char *name, const char *group)
free(free_login);
free(free_tty);
}
-#endif /* USE_SYSLOG */
/*
* newgrp - change the invokers current real and effective group id
@@ -394,12 +390,15 @@ int main (int argc, char **argv)
#ifdef WITH_AUDIT
audit_help_open ();
#endif
+
+ check_fds ();
+
(void) setlocale (LC_ALL, "");
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
/*
- * Save my name for error messages and save my real gid incase of
+ * Save my name for error messages and save my real gid in case of
* errors. If there is an error i have to exec a new login shell for
* the user since her old shell won't have fork'd to create the
* process. Skip over the program name to the next command line
@@ -421,11 +420,18 @@ int main (int argc, char **argv)
* but we do not need to restore the previous process persona and we
* don't need to re-exec anything. -- JWP
*/
- Prog = Basename (argv[0]);
+
+ /*
+ * Ensure that "Prog" is always either "newgrp" or "sg" to avoid
+ * injecting arbitrary strings into our stderr/stdout, as this can
+ * be an exploit vector.
+ */
+ is_newgrp = (strcmp (Basename (argv[0]), "newgrp") == 0);
+ Prog = is_newgrp ? "newgrp" : "sg";
+
log_set_progname(Prog);
log_set_logfd(stderr);
- is_newgrp = (strcmp (Prog, "newgrp") == 0);
- OPENLOG (is_newgrp ? "newgrp" : "sg");
+ OPENLOG (Prog);
argc--;
argv++;
@@ -437,8 +443,7 @@ int main (int argc, char **argv)
Prog);
#ifdef WITH_AUDIT
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
#endif
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
(unsigned long) getuid ()));
@@ -507,7 +512,7 @@ int main (int argc, char **argv)
if ((argc > 0) && (argv[0][0] == '-')) {
usage ();
goto failure;
- } else if (argv[0] != (char *) 0) {
+ } else if (argv[0] != NULL) {
group = argv[0];
} else {
/*
@@ -541,7 +546,7 @@ int main (int argc, char **argv)
/* don't use getgroups(0, 0) - it doesn't work on some systems */
i = 16;
for (;;) {
- grouplist = (GETGROUPS_T *) xmalloc (i * sizeof (GETGROUPS_T));
+ grouplist = XMALLOC(i, GETGROUPS_T);
ngroups = getgroups (i, grouplist);
if (i > ngroups && !(ngroups == -1 && errno == EINVAL)) {
break;
@@ -554,15 +559,12 @@ int main (int argc, char **argv)
perror ("getgroups");
#ifdef WITH_AUDIT
if (group) {
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-group=%s", group);
+ SNPRINTF(audit_buf, "changing new-group=%s", group);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
} else {
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
}
#endif
exit (EXIT_FAILURE);
@@ -628,7 +630,7 @@ int main (int argc, char **argv)
}
#endif /* HAVE_SETGROUPS */
/*
- * For splitted groups (due to limitations of NIS), check all
+ * For split groups (due to limitations of NIS), check all
* groups of the same GID like the requested group for
* membership of the current user.
*/
@@ -665,11 +667,9 @@ int main (int argc, char **argv)
* all successful validations pass through this point. The group id
* will be set, and the group added to the concurrent groupset.
*/
-#ifdef USE_SYSLOG
if (getdef_bool ("SYSLOG_SG_ENAB")) {
syslog_sg (name, group);
}
-#endif /* USE_SYSLOG */
gid = grp->gr_gid;
@@ -718,11 +718,9 @@ int main (int argc, char **argv)
if (setgid (gid) != 0) {
perror ("setgid");
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-gid=%lu", (unsigned long) gid);
+ SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
#endif
exit (EXIT_FAILURE);
}
@@ -730,11 +728,9 @@ int main (int argc, char **argv)
if (setuid (getuid ()) != 0) {
perror ("setuid");
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-gid=%lu", (unsigned long) gid);
+ SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
#endif
exit (EXIT_FAILURE);
}
@@ -745,13 +741,11 @@ int main (int argc, char **argv)
*/
if (cflag) {
closelog ();
- execl (SHELL, "sh", "-c", command, (char *) 0);
+ execl (SHELL, "sh", "-c", command, (char *) NULL);
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-gid=%lu", (unsigned long) gid);
+ SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
#endif
perror (SHELL);
exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
@@ -815,17 +809,15 @@ int main (int argc, char **argv)
}
#ifdef WITH_AUDIT
- snprintf (audit_buf, sizeof(audit_buf), "changing new-gid=%lu",
- (unsigned long) gid);
+ SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 1);
+ audit_buf, NULL, getuid (), 1);
#endif
/*
* Exec the login shell and go away. We are trying to get back to
* the previous environment which should be the user's login shell.
*/
- err = shell (prog, initflag ? (char *) 0 : progbase, newenvp);
+ err = shell (prog, initflag ? NULL : progbase, newenvp);
exit ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
/*@notreached@*/
failure:
@@ -843,15 +835,12 @@ int main (int argc, char **argv)
closelog ();
#ifdef WITH_AUDIT
if (NULL != group) {
- snprintf (audit_buf, sizeof(audit_buf),
- "changing new-group=%s", group);
+ SNPRINTF(audit_buf, "changing new-group=%s", group);
audit_logger (AUDIT_CHGRP_ID, Prog,
- audit_buf, NULL,
- (unsigned int) getuid (), 0);
+ audit_buf, NULL, getuid (), 0);
} else {
audit_logger (AUDIT_CHGRP_ID, Prog,
- "changing", NULL,
- (unsigned int) getuid (), 0);
+ "changing", NULL, getuid (), 0);
}
#endif
exit (EXIT_FAILURE);