From owner-freebsd-standards Thu Mar 21 23:40:50 2002 Delivered-To: freebsd-standards@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 2776937B41B for ; Thu, 21 Mar 2002 23:40:04 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g2M7e4W67209; Thu, 21 Mar 2002 23:40:04 -0800 (PST) (envelope-from gnats) Received: from descent.robbins.dropbear.id.au (095.b.003.mel.iprimus.net.au [210.50.32.95]) by hub.freebsd.org (Postfix) with ESMTP id 1629C37B404 for ; Thu, 21 Mar 2002 23:38:47 -0800 (PST) Received: (from tim@localhost) by descent.robbins.dropbear.id.au (8.11.6/8.11.6) id g2M7b5x01824; Fri, 22 Mar 2002 18:37:05 +1100 (EST) (envelope-from tim) Message-Id: <200203220737.g2M7b5x01824@descent.robbins.dropbear.id.au> Date: Fri, 22 Mar 2002 18:37:05 +1100 (EST) From: "Tim J. Robbins" Reply-To: "Tim J. Robbins" To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: standards/36190: P1003.1-2001 newgrp command Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG >Number: 36190 >Category: standards >Synopsis: P1003.1-2001 newgrp command >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-standards >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Thu Mar 21 23:40:03 PST 2002 >Closed-Date: >Last-Modified: >Originator: Tim J. Robbins >Release: FreeBSD 4.5-STABLE i386 >Organization: >Environment: System: FreeBSD descent.robbins.dropbear.id.au 4.5-STABLE FreeBSD 4.5-STABLE #17: Thu Mar 21 19:48:18 EST 2002 tim@descent.robbins.dropbear.id.au:/usr/obj/usr/src/sys/DESCENT i386 >Description: FreeBSD is missing the P1003.1-2001 newgrp command. Many people believe 4.2BSD's group system makes this command unnecessary, but the standard still requires it. >How-To-Repeat: newgrp >Fix: This is an implementation of the newgrp utility. It obviously needs to be suid root to work, which is a security risk, and a risk I don't believe is worth taking in most cases. I suggest making newgrp suid a compile-time option like with ssh because most people won't use it. # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # Makefile # newgrp.c # newgrp.1 # echo x - Makefile sed 's/^X//' >Makefile << 'END-of-Makefile' X# $FreeBSD$ X# $Id: Makefile,v 1.1 2002/02/17 22:59:24 tim Exp $ X XPROG= newgrp XDPADD= ${LIBCRYPT} XLDADD= -lcrypt -lutil X XBINMODE=4555 XINSTALLFLAGS=-fschg X X.include END-of-Makefile echo x - newgrp.c sed 's/^X//' >newgrp.c << 'END-of-newgrp.c' X/*- X * Copyright (c) 2002 Tim J. Robbins. X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X/* X * newgrp -- change to a new group X */ X X#include X__FBSDID("$FreeBSD$"); X__RCSID("$Id: newgrp.c,v 1.5 2002/03/19 10:53:30 tim Exp $"); X X#include X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xvoid addgroup(const char *grpname); Xvoid restoregrps(void); Xvoid usage(void); X Xstruct passwd *pwd; X X/* Change groups back to those from the password/group databases */ Xvoid Xrestoregrps(void) X{ X X if (initgroups(pwd->pw_name, pwd->pw_gid)) { X warn("initgroups"); X return; X } X X if (setgid(pwd->pw_gid)) X warn("setgid"); X} X X/* Change gid and egid to specified group */ Xvoid Xaddgroup(const char *grpname) X{ X gid_t grps[NGROUPS_MAX]; X struct group *grp; X char *ep; X char **p; X long lgid; X gid_t egid; X int dbmember, i, newegmem, egmem, ngrps; X X /* X * Get group database entry for the specified group. First try it X * as a name, then a group ID. X */ X if ((grp = getgrnam(grpname)) == NULL) X if ((lgid = strtol(grpname, &ep, 10)) <= 0 || *ep != '\0' || X (grp = getgrgid((gid_t)lgid)) == NULL ) { X warnx("%s: bad group name", grpname); X return; X } X X /* Check whether user is a member of the requested group */ X dbmember = 0; X if (pwd->pw_gid == grp->gr_gid) X dbmember = 1; X for (p = grp->gr_mem; *p != NULL; p++) X if (strcmp(*p, pwd->pw_name) == 0) { X dbmember = 1; X break; X } X X /* Non-members need a password if one exists (except superuser). */ X if (!dbmember && *grp->gr_passwd != '\0' && getuid() != 0) { X char *pass; X X pass = getpass("Password:"); X if (pass == NULL || X strcmp(grp->gr_passwd, crypt(pass, grp->gr_passwd)) != 0) { X (void)fprintf(stderr, "Sorry\n"); X return; X } X } X X if ((ngrps = getgroups(NGROUPS_MAX, (gid_t *)grps)) < 0) { X warn("getgroups"); X return; X } X /* Determine whether current egid is in supp. group list */ X egid = getegid(); X egmem = 0; X for (i = 0; i < ngrps; i++) X if (grps[i] == egid) { X egmem = 1; X break; X } X /* Determine whether new egid is in supp. group list */ X newegmem = 0; X for (i = 0; i < ngrps; i++) X if (grps[i] == grp->gr_gid) { X newegmem = 1; X break; X } X X if (!egmem) { X /* X * "If the new effective group ID is not in the supplementary X * group list, newgrp will add the new effective group ID to X * the list, if there is room to add it." X */ X if (ngrps == NGROUPS_MAX) X warnx("too many groups"); X else { X grps[ngrps++] = grp->gr_gid; X if (setgroups(ngrps, (const gid_t *)grps)) X warn("setgroups"); X } X } X X if (newegmem) { X /* X * "If the new effective group ID is in the supplementary X * group list, newgrp will delete it." X */ X for (i = 0; i < ngrps; i++) X if (grps[i] == grp->gr_gid) X break; X ngrps--; X memmove(&grps[i], &grps[i + 1], (ngrps - i) * X sizeof(gid_t)); X if (setgroups(ngrps, (const gid_t *)grps)) X warn("setgroups"); X } X X /* Finally set grop id. */ X if (setgid(grp->gr_gid)) X warn("setgid"); X} X Xint Xmain(int argc, char *argv[]) X{ X const char *shell; X int ch, login; X X login = 0; X while ((ch = getopt(argc, argv, "-l")) > 0) { X switch (ch) { X case '-': X case 'l': X login = 1; X break; X default: X usage(); X /*NOTREACHED*/ X } X } X X argc -= optind; X argv += optind; X X if ((pwd = getpwuid(getuid())) == NULL) X errx(1, "who are you?"); X X if (*argv == NULL) X restoregrps(); X else X addgroup(*argv); X X if (setuid(getuid()) != 0) X err(1, "setuid"); X X if (!login) { X /* X * Not setting up login environment, keep all the old X * exported variables and current directory. X */ X if ((shell = getenv("SHELL")) == NULL) X shell = _PATH_BSHELL; X execl(shell, basename(shell), NULL); X err(1, "%s", shell); X } else { X /* X * Setting up login environment. Clean the environment, X * HOME, SHELL and USER environment variables from password X * database, default PATH, retain old TERM. X */ X char *args[2], *envs[6]; X char **ep = envs; X char *term; X login_cap_t *lc; X X shell = pwd->pw_shell; X if (*shell == '\0') X shell = _PATH_BSHELL; X if (chdir(pwd->pw_dir)) { X warn("%s", pwd->pw_dir); X chdir("/"); X } X X asprintf(ep++, "USER=%s", pwd->pw_name); X asprintf(ep++, "SHELL=%s", shell); X asprintf(ep++, "HOME=%s", pwd->pw_dir); X asprintf(ep++, "PATH=%s", _PATH_DEFPATH); X if ((term = getenv("TERM")) != NULL) X asprintf(ep++, "TERM=%s", term); X *ep = NULL; X X lc = login_getpwclass(pwd); X setclassenvironment(lc, pwd, 1); X X asprintf(&args[0], "-%s", basename(shell)); X args[1] = NULL; X X execve(shell, args, envs); X err(1, "%s", shell); X } X X /*NOTREACHED*/ X return (1); X} X Xvoid Xusage(void) X{ X X fprintf(stderr, "usage: newgrp [-] [-l] [group]\n"); X exit(1); X} END-of-newgrp.c echo x - newgrp.1 sed 's/^X//' >newgrp.1 << 'END-of-newgrp.1' X.\" Copyright (c) 2002 Tim J. Robbins. X.\" All rights reserved. X.\" X.\" Redistribution and use in source and binary forms, with or without X.\" modification, are permitted provided that the following conditions X.\" are met: X.\" 1. Redistributions of source code must retain the above copyright X.\" notice, this list of conditions and the following disclaimer. X.\" 2. Redistributions in binary form must reproduce the above copyright X.\" notice, this list of conditions and the following disclaimer in the X.\" documentation and/or other materials provided with the distribution. X.\" X.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND X.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X.\" SUCH DAMAGE. X.\" X.\" $FreeBSD$ X.\" $Id: newgrp.1,v 1.4 2002/03/20 08:16:47 tim Exp $ X.\" X.Dd January 29, 2002 X.Dt NEWGRP 1 X.Os X.Sh NAME X.Nm newgrp X.Nd change to a new group X.Sh SYNOPSIS X.Nm X.Op Fl X.Op Fl l X.Op Ar group X.Sh DESCRIPTION XThe X.Nm Xutility creates a new shell execution environment with modified Xreal and effective group IDs. X.Pp XThe options are as follows: X.Bl -tag -width indent X.It Fl l Fl XSimulate a full login. The X.Ev HOME , X.Ev SHELL , X.Ev USER Xenvironment variables are set to the values from the current user's password Xdatabase entry. X.Ev PATH Xis set to the system default. XAll other environment variables are discarded except for X.Ev TERM . X.El X.Pp XIf the X.Ar group Xoperand is present, a new shell is started with the specified effective Xand real group IDs. XThe user will be prompted for a password if they are not a member of the Xspecified group. X.Pp XOtherwise, the real, effective and supplementary group IDs are restored to Xthose from the current user's password database Xentry. X.Sh ENVIRONMENT XNot modified except as described for the X.Fl l Xoption. X.Pp XThe X.Ev SHELL Xvariable is used to determine the shell to execute. X.Sh SEE ALSO X.Xr login 1 , X.Xr su 1 , X.Xr group 5 , X.Xr passwd 5 , X.Xr environ 7 X.Sh DIAGNOSTICS XWarning messages will be emitted if the requested group IDs cannot be set X(invalid group, bad password, ...) and if the shell cannot be executed. X.Sh STANDARDS XThe X.Nm Xutility is expected to comply with the X.St -p1003.1-2001 Xspecification. X.Sh BUGS XGroup passwords are inherently insecure as there is no way to stop Xusers obtaining the crypted passwords from the group database. XTheir use is discouraged. END-of-newgrp.1 exit >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message