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