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 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 32 #ifndef lint 33 __RCSID("$NetBSD: newgrp.c,v 1.6 2008/04/28 20:24:14 martin Exp $"); 34 #endif /* not lint */ 35 36 #include <sys/param.h> 37 #include <sys/types.h> 38 39 #include <err.h> 40 #include <grp.h> 41 #include <libgen.h> 42 #include <paths.h> 43 #include <pwd.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #ifdef LOGIN_CAP 50 #include <login_cap.h> 51 #endif 52 53 #include "grutil.h" 54 55 static void 56 usage(void) 57 { 58 (void)fprintf(stderr, "usage: %s [-l] [group]\n", getprogname()); 59 exit(EXIT_FAILURE); 60 } 61 62 int 63 main(int argc, char *argv[]) 64 { 65 extern char **environ; 66 struct passwd *pwd; 67 int c, lflag; 68 char *shell, sbuf[MAXPATHLEN + 2]; 69 uid_t uid; 70 #ifdef LOGIN_CAP 71 login_cap_t *lc; 72 u_int flags = LOGIN_SETUSER; 73 #endif 74 75 uid = getuid(); 76 pwd = getpwuid(uid); 77 if (pwd == NULL) 78 errx(EXIT_FAILURE, "who are you?"); 79 80 #ifdef LOGIN_CAP 81 if ((lc = login_getclass(pwd->pw_class)) == NULL) 82 errx(EXIT_FAILURE, "%s: unknown login class", pwd->pw_class); 83 #endif 84 85 (void)setprogname(argv[0]); 86 lflag = 0; 87 while ((c = getopt(argc, argv, "-l")) != -1) { 88 switch (c) { 89 case '-': 90 case 'l': 91 if (lflag) 92 usage(); 93 lflag = 1; 94 break; 95 default: 96 usage(); 97 break; 98 } 99 } 100 101 argc -= optind; 102 argv += optind; 103 104 if (argc > 0) { 105 #if 0 106 pwd->pw_gid = newgrp(*argv, pwd); 107 addgrp(pwd->pw_gid); 108 if (setgid(pwd->pw_gid) < 0) 109 err(1, "setgid"); 110 #endif 111 #ifdef LOGIN_CAP 112 addgroup(lc, *argv, pwd, getuid(), "Password:"); 113 #else 114 addgroup(*argv, pwd, getuid(), "Password:"); 115 #endif 116 } else { 117 #ifdef LOGIN_CAP 118 flags |= LOGIN_SETGROUP; 119 #else 120 if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) 121 err(EXIT_FAILURE, "initgroups"); 122 if (setgid(pwd->pw_gid) == -1) 123 err(EXIT_FAILURE, "setgid"); 124 #endif 125 } 126 127 #ifdef LOGIN_CAP 128 if (setusercontext(lc, pwd, uid, flags) == -1) 129 err(EXIT_FAILURE, "setusercontext"); 130 if (!lflag) 131 login_close(lc); 132 #else 133 if (setuid(pwd->pw_uid) == -1) 134 err(EXIT_FAILURE, "setuid"); 135 #endif 136 137 if (*pwd->pw_shell == '\0') { 138 #ifdef TRUST_ENV_SHELL 139 shell = getenv("SHELL"); 140 if (shell != NULL) 141 pwd->pw_shell = shell; 142 else 143 #endif 144 pwd->pw_shell = __UNCONST(_PATH_BSHELL); 145 } 146 147 shell = pwd->pw_shell; 148 149 if (lflag) { 150 char *term; 151 #ifdef KERBEROS 152 char *krbtkfile; 153 #endif 154 155 if (chdir(pwd->pw_dir) == -1) 156 warn("%s", pwd->pw_dir); 157 158 term = getenv("TERM"); 159 #ifdef KERBEROS 160 krbtkfile = getenv("KRBTKFILE"); 161 #endif 162 163 /* create an empty environment */ 164 if ((environ = malloc(sizeof(char *))) == NULL) 165 err(EXIT_FAILURE, NULL); 166 environ[0] = NULL; 167 #ifdef LOGIN_CAP 168 if (setusercontext(lc, pwd, uid, LOGIN_SETENV | LOGIN_SETPATH) == -1) 169 err(EXIT_FAILURE, "setusercontext"); 170 login_close(lc); 171 #else 172 (void)setenv("PATH", _PATH_DEFPATH, 1); 173 #endif 174 if (term != NULL) 175 (void)setenv("TERM", term, 1); 176 #ifdef KERBEROS 177 if (krbtkfile != NULL) 178 (void)setenv("KRBTKFILE", krbtkfile, 1); 179 #endif 180 181 (void)setenv("LOGNAME", pwd->pw_name, 1); 182 (void)setenv("USER", pwd->pw_name, 1); 183 (void)setenv("HOME", pwd->pw_dir, 1); 184 (void)setenv("SHELL", pwd->pw_shell, 1); 185 186 sbuf[0] = '-'; 187 (void)strlcpy(sbuf + 1, basename(pwd->pw_shell), 188 sizeof(sbuf) - 1); 189 shell = sbuf; 190 } 191 192 (void)execl(pwd->pw_shell, shell, NULL); 193 err(EXIT_FAILURE, "%s", pwd->pw_shell); 194 /* NOTREACHED */ 195 } 196