]> git.ipfire.org Git - thirdparty/util-linux.git/blame - login-utils/newgrp.c
newgrp: use xstrdup to check allocation succeeded
[thirdparty/util-linux.git] / login-utils / newgrp.c
CommitLineData
b7cfaaf8
SK
1/* setgrp.c - by Michael Haardt. Set the gid if possible
2 * Added a bit more error recovery/reporting - poe
3 * Vesa Roukonen added code for asking password */
6dbe3af9 4
b50945d4 5/* 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
7eda085c
KZ
6 * - added Native Language Support
7 */
8
ba0c9030
SK
9/*
10 * This command is deprecated. The utility is in maintenance mode,
11 * meaning we keep them in source tree for backward compatibility
12 * only. Do not waste time making this command better, unless the
13 * fix is about security or other very critical issue.
14 *
15 * See Documentation/deprecated.txt for more information.
16 */
17
b7cfaaf8
SK
18#include <errno.h>
19#include <getopt.h>
6dbe3af9 20#include <grp.h>
b7cfaaf8 21#include <pwd.h>
6dbe3af9 22#include <stdio.h>
66ee8158 23#include <stdlib.h>
b7cfaaf8
SK
24#include <string.h>
25#include <unistd.h>
ad564ead 26
0aeb57ac 27#ifdef HAVE_CRYPT_H
b7cfaaf8 28# include <crypt.h>
0aeb57ac
FG
29#endif
30
ad564ead 31#include "c.h"
439cdf1e 32#include "closestream.h"
7eda085c 33#include "nls.h"
b7cfaaf8 34#include "pathnames.h"
5fb01f43 35#include "xalloc.h"
6dbe3af9 36
66a9411e 37/* try to read password from gshadow */
b7cfaaf8 38static char *get_gshadow_pwd(char *groupname)
66a9411e
KZ
39{
40 char buf[BUFSIZ];
41 char *pwd = NULL;
1f19513b 42 FILE *f;
66a9411e 43
1f19513b
KZ
44 if (groupname == NULL || *groupname == '\0')
45 return NULL;
46
47 f = fopen(_PATH_GSHADOW, "r");
48 if (!f)
66a9411e
KZ
49 return NULL;
50
b7cfaaf8
SK
51 while (fgets(buf, sizeof buf, f)) {
52 char *cp = strchr(buf, ':');
66a9411e 53 if (!cp)
b7cfaaf8
SK
54 /* any junk in gshadow? */
55 continue;
66a9411e 56 *cp = '\0';
b7cfaaf8
SK
57 if (strcmp(buf, groupname) == 0) {
58 if (cp - buf >= BUFSIZ)
59 /* only group name on line */
60 break;
61 pwd = cp + 1;
62 if ((cp = strchr(pwd, ':')) && pwd == cp + 1)
63 /* empty password */
64 pwd = NULL;
66a9411e
KZ
65 else if (cp)
66 *cp = '\0';
67 break;
68 }
69 }
70 fclose(f);
5fb01f43 71 return pwd ? xstrdup(pwd) : NULL;
66a9411e
KZ
72}
73
b7cfaaf8 74static int allow_setgid(struct passwd *pe, struct group *ge)
6dbe3af9 75{
b7cfaaf8
SK
76 char **look;
77 int notfound = 1;
78 char *pwd, *xpwd;
79
80 if (getuid() == 0)
81 /* root may do anything */
82 return TRUE;
83 if (ge->gr_gid == pe->pw_gid)
84 /* You can switch back to your default group */
85 return TRUE;
86
87 look = ge->gr_mem;
88 while (*look && (notfound = strcmp(*look++, pe->pw_name))) ;
89
90 if (!notfound)
91 /* member of group => OK */
92 return TRUE;
93
94 /* Ask for password. Often there is no password in /etc/group, so
95 * contrary to login et al. we let an empty password mean the same
96 * as in /etc/passwd */
97
98 /* check /etc/gshadow */
99 if (!(pwd = get_gshadow_pwd(ge->gr_name)))
100 pwd = ge->gr_passwd;
101
19a1ca6c
KZ
102 if (pwd && *pwd && (xpwd = getpass(_("Password: ")))) {
103 char *cbuf = crypt(xpwd, pwd);
104
105 if (!cbuf)
106 warn(_("crypt() failed"));
107 else if (strcmp(pwd, cbuf) == 0)
b7cfaaf8 108 return TRUE;
19a1ca6c 109 }
b7cfaaf8
SK
110
111 /* default to denial */
112 return FALSE;
6dbe3af9
KZ
113}
114
e947e273
SK
115static void __attribute__ ((__noreturn__)) usage(FILE * out)
116{
b7cfaaf8
SK
117 fprintf(out, USAGE_HEADER);
118 fprintf(out, _(" %s <group>\n"), program_invocation_short_name);
119 fprintf(out, USAGE_OPTIONS);
120 fprintf(out, USAGE_HELP);
121 fprintf(out, USAGE_VERSION);
122 fprintf(out, USAGE_MAN_TAIL("newgrp(1)"));
123 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
e947e273
SK
124}
125
b7cfaaf8 126int main(int argc, char *argv[])
6dbe3af9 127{
b7cfaaf8
SK
128 struct passwd *pw_entry;
129 struct group *gr_entry;
130 char *shell;
131 char ch;
132 static const struct option longopts[] = {
133 {"version", no_argument, NULL, 'V'},
134 {"help", no_argument, NULL, 'h'},
135 {NULL, 0, NULL, 0}
136 };
137
138 setlocale(LC_ALL, "");
139 bindtextdomain(PACKAGE, LOCALEDIR);
140 textdomain(PACKAGE);
439cdf1e 141 atexit(close_stdout);
b7cfaaf8
SK
142
143 while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1)
144 switch (ch) {
145 case 'V':
146 printf(UTIL_LINUX_VERSION);
147 return EXIT_SUCCESS;
148 case 'h':
149 usage(stdout);
150 default:
151 usage(stderr);
152 }
e947e273 153
b7cfaaf8
SK
154 if (!(pw_entry = getpwuid(getuid())))
155 err(EXIT_FAILURE, _("who are you?"));
156
c6f23b3b
KZ
157 shell = (pw_entry->pw_shell && *pw_entry->pw_shell ?
158 pw_entry->pw_shell : _PATH_BSHELL);
b7cfaaf8
SK
159
160 if (argc < 2) {
161 if (setgid(pw_entry->pw_gid) < 0)
162 err(EXIT_FAILURE, _("setgid failed"));
6dbe3af9 163 } else {
b7cfaaf8
SK
164 errno = 0;
165 if (!(gr_entry = getgrnam(argv[1]))) {
166 if (errno)
167 err(EXIT_FAILURE, _("no such group"));
168 else
169 /* No group */
170 errx(EXIT_FAILURE, _("no such group"));
171 } else {
172 if (allow_setgid(pw_entry, gr_entry)) {
173 if (setgid(gr_entry->gr_gid) < 0)
174 err(EXIT_FAILURE, _("setgid failed"));
175 } else
176 errx(EXIT_FAILURE, _("permission denied"));
177 }
6dbe3af9 178 }
6dbe3af9 179
b7cfaaf8
SK
180 if (setuid(getuid()) < 0)
181 err(EXIT_FAILURE, _("setuid failed"));
6dbe3af9 182
b7cfaaf8
SK
183 fflush(stdout);
184 fflush(stderr);
185 execl(shell, shell, (char *)0);
07ff972e 186 warn(_("failed to execute %s"), shell);
b7cfaaf8 187 fflush(stderr);
1fa30199 188
b7cfaaf8 189 return EXIT_FAILURE;
6dbe3af9 190}