]> git.ipfire.org Git - thirdparty/util-linux.git/blob - login-utils/newgrp.c
cca7b32446a99162bf4b992c5beeb5ded5bdf4ae
[thirdparty/util-linux.git] / login-utils / newgrp.c
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 */
4
5 /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
6 * - added Native Language Support
7 */
8
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
18 #include <errno.h>
19 #include <getopt.h>
20 #include <grp.h>
21 #include <pwd.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #ifdef HAVE_CRYPT_H
28 # include <crypt.h>
29 #endif
30
31 #include "c.h"
32 #include "closestream.h"
33 #include "nls.h"
34 #include "pathnames.h"
35
36 /* try to read password from gshadow */
37 static char *get_gshadow_pwd(char *groupname)
38 {
39 char buf[BUFSIZ];
40 char *pwd = NULL;
41 FILE *f;
42
43 if (groupname == NULL || *groupname == '\0')
44 return NULL;
45
46 f = fopen(_PATH_GSHADOW, "r");
47 if (!f)
48 return NULL;
49
50 while (fgets(buf, sizeof buf, f)) {
51 char *cp = strchr(buf, ':');
52 if (!cp)
53 /* any junk in gshadow? */
54 continue;
55 *cp = '\0';
56 if (strcmp(buf, groupname) == 0) {
57 if (cp - buf >= BUFSIZ)
58 /* only group name on line */
59 break;
60 pwd = cp + 1;
61 if ((cp = strchr(pwd, ':')) && pwd == cp + 1)
62 /* empty password */
63 pwd = NULL;
64 else if (cp)
65 *cp = '\0';
66 break;
67 }
68 }
69 fclose(f);
70 return pwd ? strdup(pwd) : NULL;
71 }
72
73 static int allow_setgid(struct passwd *pe, struct group *ge)
74 {
75 char **look;
76 int notfound = 1;
77 char *pwd, *xpwd;
78
79 if (getuid() == 0)
80 /* root may do anything */
81 return TRUE;
82 if (ge->gr_gid == pe->pw_gid)
83 /* You can switch back to your default group */
84 return TRUE;
85
86 look = ge->gr_mem;
87 while (*look && (notfound = strcmp(*look++, pe->pw_name))) ;
88
89 if (!notfound)
90 /* member of group => OK */
91 return TRUE;
92
93 /* Ask for password. Often there is no password in /etc/group, so
94 * contrary to login et al. we let an empty password mean the same
95 * as in /etc/passwd */
96
97 /* check /etc/gshadow */
98 if (!(pwd = get_gshadow_pwd(ge->gr_name)))
99 pwd = ge->gr_passwd;
100
101 if (pwd && *pwd && (xpwd = getpass(_("Password: ")))) {
102 char *cbuf = crypt(xpwd, pwd);
103
104 if (!cbuf)
105 warn(_("crypt() failed"));
106 else if (strcmp(pwd, cbuf) == 0)
107 return TRUE;
108 }
109
110 /* default to denial */
111 return FALSE;
112 }
113
114 static void __attribute__ ((__noreturn__)) usage(FILE * out)
115 {
116 fprintf(out, USAGE_HEADER);
117 fprintf(out, _(" %s <group>\n"), program_invocation_short_name);
118 fprintf(out, USAGE_OPTIONS);
119 fprintf(out, USAGE_HELP);
120 fprintf(out, USAGE_VERSION);
121 fprintf(out, USAGE_MAN_TAIL("newgrp(1)"));
122 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
123 }
124
125 int main(int argc, char *argv[])
126 {
127 struct passwd *pw_entry;
128 struct group *gr_entry;
129 char *shell;
130 char ch;
131 static const struct option longopts[] = {
132 {"version", no_argument, NULL, 'V'},
133 {"help", no_argument, NULL, 'h'},
134 {NULL, 0, NULL, 0}
135 };
136
137 setlocale(LC_ALL, "");
138 bindtextdomain(PACKAGE, LOCALEDIR);
139 textdomain(PACKAGE);
140 atexit(close_stdout);
141
142 while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1)
143 switch (ch) {
144 case 'V':
145 printf(UTIL_LINUX_VERSION);
146 return EXIT_SUCCESS;
147 case 'h':
148 usage(stdout);
149 default:
150 usage(stderr);
151 }
152
153 if (!(pw_entry = getpwuid(getuid())))
154 err(EXIT_FAILURE, _("who are you?"));
155
156 shell = (pw_entry->pw_shell && *pw_entry->pw_shell ?
157 pw_entry->pw_shell : _PATH_BSHELL);
158
159 if (argc < 2) {
160 if (setgid(pw_entry->pw_gid) < 0)
161 err(EXIT_FAILURE, _("setgid failed"));
162 } else {
163 errno = 0;
164 if (!(gr_entry = getgrnam(argv[1]))) {
165 if (errno)
166 err(EXIT_FAILURE, _("no such group"));
167 else
168 /* No group */
169 errx(EXIT_FAILURE, _("no such group"));
170 } else {
171 if (allow_setgid(pw_entry, gr_entry)) {
172 if (setgid(gr_entry->gr_gid) < 0)
173 err(EXIT_FAILURE, _("setgid failed"));
174 } else
175 errx(EXIT_FAILURE, _("permission denied"));
176 }
177 }
178
179 if (setuid(getuid()) < 0)
180 err(EXIT_FAILURE, _("setuid failed"));
181
182 fflush(stdout);
183 fflush(stderr);
184 execl(shell, shell, (char *)0);
185 warn(_("exec %s failed"), shell);
186 fflush(stderr);
187
188 return EXIT_FAILURE;
189 }