1 /*- 2 * Copyright (c) 2007 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Brian Ginsbach. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the NetBSD 19 * Foundation, Inc. and its contributors. 20 * 4. Neither the name of The NetBSD Foundation nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #include <sys/cdefs.h> 38 39 #ifndef lint 40 __RCSID("$NetBSD: newgrp.c,v 1.4 2007/10/17 21:07:49 christos Exp $"); 41 #endif /* not lint */ 42 43 #include <sys/param.h> 44 #include <sys/types.h> 45 46 #include <err.h> 47 #include <grp.h> 48 #include <libgen.h> 49 #include <paths.h> 50 #include <pwd.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 56 #ifdef LOGIN_CAP 57 #include <login_cap.h> 58 #endif 59 60 #include "grutil.h" 61 62 static void 63 usage(void) 64 { 65 (void)fprintf(stderr, "usage: %s [-l] [group]\n", getprogname()); 66 exit(EXIT_FAILURE); 67 } 68 69 int 70 main(int argc, char *argv[]) 71 { 72 extern char **environ; 73 struct passwd *pwd; 74 int c, lflag; 75 char *shell, sbuf[MAXPATHLEN + 2]; 76 uid_t uid; 77 #ifdef LOGIN_CAP 78 login_cap_t *lc; 79 u_int flags = LOGIN_SETUSER; 80 #endif 81 82 uid = getuid(); 83 pwd = getpwuid(uid); 84 if (pwd == NULL) 85 errx(EXIT_FAILURE, "who are you?"); 86 87 #ifdef LOGIN_CAP 88 if ((lc = login_getclass(pwd->pw_class)) == NULL) 89 errx(EXIT_FAILURE, "%s: unknown login class", pwd->pw_class); 90 #endif 91 92 lflag = 0; 93 while ((c = getopt(argc, argv, "-l")) != -1) { 94 switch (c) { 95 case '-': 96 case 'l': 97 if (lflag) 98 usage(); 99 lflag = 1; 100 break; 101 default: 102 usage(); 103 break; 104 } 105 } 106 107 argc -= optind; 108 argv += optind; 109 110 if (argc > 0) { 111 #if 0 112 pwd->pw_gid = newgrp(*argv, pwd); 113 addgrp(pwd->pw_gid); 114 if (setgid(pwd->pw_gid) < 0) 115 err(1, "setgid"); 116 #endif 117 #ifdef LOGIN_CAP 118 addgroup(lc, *argv, pwd, getuid(), "Password:"); 119 #else 120 addgroup(*argv, pwd, getuid(), "Password:"); 121 #endif 122 } else { 123 #ifdef LOGIN_CAP 124 flags |= LOGIN_SETGROUP; 125 #else 126 if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) 127 err(EXIT_FAILURE, "initgroups"); 128 if (setgid(pwd->pw_gid) == -1) 129 err(EXIT_FAILURE, "setgid"); 130 #endif 131 } 132 133 #ifdef LOGIN_CAP 134 if (setusercontext(lc, pwd, uid, flags) == -1) 135 err(EXIT_FAILURE, "setusercontext"); 136 if (!lflag) 137 login_close(lc); 138 #else 139 if (setuid(pwd->pw_uid) == -1) 140 err(EXIT_FAILURE, "setuid"); 141 #endif 142 143 if (*pwd->pw_shell == '\0') { 144 #ifdef TRUST_ENV_SHELL 145 shell = getenv("SHELL"); 146 if (shell != NULL) 147 pwd->pw_shell = shell; 148 else 149 #endif 150 pwd->pw_shell = __UNCONST(_PATH_BSHELL); 151 } 152 153 shell = pwd->pw_shell; 154 155 if (lflag) { 156 char *term; 157 #ifdef KERBEROS 158 char *krbtkfile; 159 #endif 160 161 if (chdir(pwd->pw_dir) == -1) 162 warn("%s", pwd->pw_dir); 163 164 term = getenv("TERM"); 165 #ifdef KERBEROS 166 krbtkfile = getenv("KRBTKFILE"); 167 #endif 168 169 /* create an empty environment */ 170 if ((environ = malloc(sizeof(char *))) == NULL) 171 err(EXIT_FAILURE, NULL); 172 environ[0] = NULL; 173 #ifdef LOGIN_CAP 174 if (setusercontext(lc, pwd, uid, LOGIN_SETENV | LOGIN_SETPATH) == -1) 175 err(EXIT_FAILURE, "setusercontext"); 176 login_close(lc); 177 #else 178 (void)setenv("PATH", _PATH_DEFPATH, 1); 179 #endif 180 if (term != NULL) 181 (void)setenv("TERM", term, 1); 182 #ifdef KERBEROS 183 if (krbtkfile != NULL) 184 (void)setenv("KRBTKFILE", krbtkfile, 1); 185 #endif 186 187 (void)setenv("LOGNAME", pwd->pw_name, 1); 188 (void)setenv("USER", pwd->pw_name, 1); 189 (void)setenv("HOME", pwd->pw_dir, 1); 190 (void)setenv("SHELL", pwd->pw_shell, 1); 191 192 sbuf[0] = '-'; 193 (void)strlcpy(sbuf + 1, basename(pwd->pw_shell), 194 sizeof(sbuf) - 1); 195 shell = sbuf; 196 } 197 198 (void)execl(pwd->pw_shell, shell, NULL); 199 err(EXIT_FAILURE, "%s", pwd->pw_shell); 200 /* NOTREACHED */ 201 } 202