diff options
Diffstat (limited to '')
-rw-r--r-- | src/newgrp.c | 127 |
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); |