summaryrefslogtreecommitdiffstats
path: root/usr.bin/su
diff options
context:
space:
mode:
authorrgrimes <rgrimes@FreeBSD.org>1994-05-27 12:33:43 +0000
committerrgrimes <rgrimes@FreeBSD.org>1994-05-27 12:33:43 +0000
commitf9ab90d9d6d02989a075d0f0074496d5b1045e4b (patch)
treeadd7e996bac5289cdc55e6935750c352505560a9 /usr.bin/su
parentbe22b15ae2ff8d7fe06b6e14fddf0c5b444a95da (diff)
downloadFreeBSD-src-f9ab90d9d6d02989a075d0f0074496d5b1045e4b.zip
FreeBSD-src-f9ab90d9d6d02989a075d0f0074496d5b1045e4b.tar.gz
BSD 4.4 Lite Usr.bin Sources
Diffstat (limited to 'usr.bin/su')
-rw-r--r--usr.bin/su/Makefile11
-rw-r--r--usr.bin/su/su.1172
-rw-r--r--usr.bin/su/su.c399
3 files changed, 582 insertions, 0 deletions
diff --git a/usr.bin/su/Makefile b/usr.bin/su/Makefile
new file mode 100644
index 0000000..e3e023a
--- /dev/null
+++ b/usr.bin/su/Makefile
@@ -0,0 +1,11 @@
+# @(#)Makefile 8.1 (Berkeley) 7/19/93
+
+PROG= su
+CFLAGS+=-DKERBEROS
+DPADD= ${LIBKRB} ${LIBDES}
+LDADD= -lkrb -ldes
+BINOWN= root
+BINMODE=4555
+INSTALLFLAGS=-fschg
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/su/su.1 b/usr.bin/su/su.1
new file mode 100644
index 0000000..ea9edcf
--- /dev/null
+++ b/usr.bin/su/su.1
@@ -0,0 +1,172 @@
+.\" Copyright (c) 1988, 1990, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)su.1 8.2 (Berkeley) 4/18/94
+.\"
+.Dd April 18, 1994
+.Dt SU 1
+.Os
+.Sh NAME
+.Nm su
+.Nd substitute user identity
+.Sh SYNOPSIS
+.Nm su
+.Op Fl Kflm
+.Op Ar login
+.Sh DESCRIPTION
+.Nm Su
+requests the Kerberos password for
+.Ar login
+(or for
+.Dq Ar login Ns .root ,
+if no login is provided), and switches to
+that user and group ID after obtaining a Kerberos ticket granting ticket.
+A shell is then executed.
+.Nm Su
+will resort to the local password file to find the password for
+.Ar login
+if there is a Kerberos error.
+If
+.Nm su
+is executed by root, no password is requested and a shell
+with the appropriate user ID is executed; no additional Kerberos tickets
+are obtained.
+.Pp
+By default, the environment is unmodified with the exception of
+.Ev USER ,
+.Ev HOME ,
+and
+.Ev SHELL .
+.Ev HOME
+and
+.Ev SHELL
+are set to the target login's default values.
+.Ev USER
+is set to the target login, unless the target login has a user ID of 0,
+in which case it is unmodified.
+The invoked shell is the target login's.
+This is the traditional behavior of
+.Nm su .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl K
+Do not attempt to use Kerberos to authenticate the user.
+.It Fl f
+If the invoked shell is
+.Xr csh 1 ,
+this option prevents it from reading the
+.Dq Pa .cshrc
+file.
+.It Fl l
+Simulate a full login.
+The environment is discarded except for
+.Ev HOME ,
+.Ev SHELL ,
+.Ev PATH ,
+.Ev TERM ,
+and
+.Ev USER .
+.Ev HOME
+and
+.Ev SHELL
+are modified as above.
+.Ev USER
+is set to the target login.
+.Ev PATH
+is set to
+.Dq Pa /bin:/usr/bin .
+.Ev TERM
+is imported from your current environment.
+The invoked shell is the target login's, and
+.Nm su
+will change directory to the target login's home directory.
+.It Fl m
+Leave the environment unmodified.
+The invoked shell is your login shell, and no directory changes are made.
+As a security precaution, if the target user's shell is a non-standard
+shell (as defined by
+.Xr getusershell 3 )
+and the caller's real uid is
+non-zero,
+.Nm su
+will fail.
+.El
+.Pp
+The
+.Fl l
+and
+.Fl m
+options are mutually exclusive; the last one specified
+overrides any previous ones.
+.Pp
+Only users in group 0 (normally
+.Dq wheel )
+can
+.Nm su
+to
+.Dq root .
+.Pp
+By default (unless the prompt is reset by a startup file) the super-user
+prompt is set to
+.Dq Sy \&#
+to remind one of its awesome power.
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr login 1 ,
+.Xr sh 1 ,
+.Xr kinit 1 ,
+.Xr kerberos 1 ,
+.Xr passwd 5 ,
+.Xr group 5 ,
+.Xr environ 7
+.Sh ENVIRONMENT
+Environment variables used by
+.Nm su :
+.Bl -tag -width HOME
+.It Ev HOME
+Default home directory of real user ID unless modified as
+specified above.
+.It Ev PATH
+Default search path of real user ID unless modified as specified above.
+.It Ev TERM
+Provides terminal type which may be retained for the substituted
+user ID.
+.It Ev USER
+The user ID is always the effective ID (the target user ID) after an
+.Nm su
+unless the user ID is 0 (root).
+.El
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v7 .
diff --git a/usr.bin/su/su.c b/usr.bin/su/su.c
new file mode 100644
index 0000000..f06ef2f
--- /dev/null
+++ b/usr.bin/su/su.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)su.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include <netdb.h>
+
+#define ARGSTR "-Kflm"
+
+int use_kerberos = 1;
+#else
+#define ARGSTR "-flm"
+#endif
+
+char *ontty __P((void));
+int chshell __P((char *));
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern char **environ;
+ struct passwd *pwd;
+ char *p, **g, *user, *shell, *username, *cleanenv[2], *nargv[4], **np;
+ struct group *gr;
+ uid_t ruid;
+ int asme, ch, asthem, fastlogin, prio;
+ enum { UNSET, YES, NO } iscsh = UNSET;
+ char shellbuf[MAXPATHLEN];
+
+ np = &nargv[3];
+ *np-- = NULL;
+ asme = asthem = fastlogin = 0;
+ while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
+ switch((char)ch) {
+#ifdef KERBEROS
+ case 'K':
+ use_kerberos = 0;
+ break;
+#endif
+ case 'f':
+ fastlogin = 1;
+ break;
+ case '-':
+ case 'l':
+ asme = 0;
+ asthem = 1;
+ break;
+ case 'm':
+ asme = 1;
+ asthem = 0;
+ break;
+ case '?':
+ default:
+ (void)fprintf(stderr, "usage: su [%s] [login]\n",
+ ARGSTR);
+ exit(1);
+ }
+ argv += optind;
+
+ errno = 0;
+ prio = getpriority(PRIO_PROCESS, 0);
+ if (errno)
+ prio = 0;
+ (void)setpriority(PRIO_PROCESS, 0, -2);
+ openlog("su", LOG_CONS, 0);
+
+ /* get current login name and shell */
+ ruid = getuid();
+ username = getlogin();
+ if (username == NULL || (pwd = getpwnam(username)) == NULL ||
+ pwd->pw_uid != ruid)
+ pwd = getpwuid(ruid);
+ if (pwd == NULL)
+ errx(1, "who are you?");
+ username = strdup(pwd->pw_name);
+ if (username == NULL)
+ err(1, NULL);
+ if (asme)
+ if (pwd->pw_shell && *pwd->pw_shell)
+ shell = strcpy(shellbuf, pwd->pw_shell);
+ else {
+ shell = _PATH_BSHELL;
+ iscsh = NO;
+ }
+
+ /* get target login information, default to root */
+ user = *argv ? *argv : "root";
+ if ((pwd = getpwnam(user)) == NULL) {
+ fprintf(stderr, "su: unknown login %s\n", user);
+ exit(1);
+ }
+
+ if (ruid) {
+#ifdef KERBEROS
+ if (!use_kerberos || kerberos(username, user, pwd->pw_uid))
+#endif
+ {
+ /* only allow those in group zero to su to root. */
+ if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0)))
+ for (g = gr->gr_mem;; ++g) {
+ if (!*g)
+ errx(1,
+ "you are not in the correct group to su %s.",
+ user);
+ if (strcmp(username, *g) == 0)
+ break;
+ }
+ /* if target requires a password, verify it */
+ if (*pwd->pw_passwd) {
+ p = getpass("Password:");
+ if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
+ fprintf(stderr, "Sorry\n");
+ syslog(LOG_AUTH|LOG_WARNING,
+ "BAD SU %s to %s%s", username,
+ user, ontty());
+ exit(1);
+ }
+ }
+ }
+ }
+
+ if (asme) {
+ /* if asme and non-standard target shell, must be root */
+ if (!chshell(pwd->pw_shell) && ruid)
+ errx(1, "permission denied (shell).");
+ } else if (pwd->pw_shell && *pwd->pw_shell) {
+ shell = pwd->pw_shell;
+ iscsh = UNSET;
+ } else {
+ shell = _PATH_BSHELL;
+ iscsh = NO;
+ }
+
+ /* if we're forking a csh, we want to slightly muck the args */
+ if (iscsh == UNSET) {
+ if (p = strrchr(shell, '/'))
+ ++p;
+ else
+ p = shell;
+ iscsh = strcmp(p, "csh") ? NO : YES;
+ }
+
+ /* set permissions */
+ if (setgid(pwd->pw_gid) < 0)
+ err(1, "setgid");
+ if (initgroups(user, pwd->pw_gid))
+ errx(1, "initgroups failed");
+ if (setuid(pwd->pw_uid) < 0)
+ err(1, "setuid");
+
+ if (!asme) {
+ if (asthem) {
+ p = getenv("TERM");
+ cleanenv[0] = _PATH_DEFPATH;
+ cleanenv[1] = NULL;
+ environ = cleanenv;
+ (void)setenv("TERM", p, 1);
+ if (chdir(pwd->pw_dir) < 0)
+ errx(1, "no directory");
+ }
+ if (asthem || pwd->pw_uid)
+ (void)setenv("USER", pwd->pw_name, 1);
+ (void)setenv("HOME", pwd->pw_dir, 1);
+ (void)setenv("SHELL", shell, 1);
+ }
+
+ if (iscsh == YES) {
+ if (fastlogin)
+ *np-- = "-f";
+ if (asme)
+ *np-- = "-m";
+ }
+
+ /* csh strips the first character... */
+ *np = asthem ? "-su" : iscsh == YES ? "_su" : "su";
+
+ if (ruid != 0)
+ syslog(LOG_NOTICE|LOG_AUTH, "%s to %s%s",
+ username, user, ontty());
+
+ (void)setpriority(PRIO_PROCESS, 0, prio);
+
+ execv(shell, np);
+ err(1, "%s", shell);
+}
+
+int
+chshell(sh)
+ char *sh;
+{
+ char *cp;
+
+ while ((cp = getusershell()) != NULL)
+ if (strcmp(cp, sh) == 0)
+ return (1);
+ return (0);
+}
+
+char *
+ontty()
+{
+ char *p;
+ static char buf[MAXPATHLEN + 4];
+
+ buf[0] = 0;
+ if (p = ttyname(STDERR_FILENO))
+ snprintf(buf, sizeof(buf), " on %s", p);
+ return (buf);
+}
+
+#ifdef KERBEROS
+kerberos(username, user, uid)
+ char *username, *user;
+ int uid;
+{
+ extern char *krb_err_txt[];
+ KTEXT_ST ticket;
+ AUTH_DAT authdata;
+ struct hostent *hp;
+ char *p;
+ int kerno;
+ u_long faddr;
+ char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN];
+ char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
+ char *krb_get_phost();
+
+ if (krb_get_lrealm(lrealm, 1) != KSUCCESS)
+ return (1);
+ if (koktologin(username, lrealm, user) && !uid) {
+ warnx("kerberos: not in %s's ACL.", user);
+ return (1);
+ }
+ (void)sprintf(krbtkfile, "%s_%s_%d", TKT_ROOT, user, getuid());
+
+ (void)setenv("KRBTKFILE", krbtkfile, 1);
+ (void)krb_set_tkt_string(krbtkfile);
+ /*
+ * Set real as well as effective ID to 0 for the moment,
+ * to make the kerberos library do the right thing.
+ */
+ if (setuid(0) < 0) {
+ warn("setuid");
+ return (1);
+ }
+
+ /*
+ * Little trick here -- if we are su'ing to root,
+ * we need to get a ticket for "xxx.root", where xxx represents
+ * the name of the person su'ing. Otherwise (non-root case),
+ * we need to get a ticket for "yyy.", where yyy represents
+ * the name of the person being su'd to, and the instance is null
+ *
+ * We should have a way to set the ticket lifetime,
+ * with a system default for root.
+ */
+ kerno = krb_get_pw_in_tkt((uid == 0 ? username : user),
+ (uid == 0 ? "root" : ""), lrealm,
+ "krbtgt", lrealm, DEFAULT_TKT_LIFE, 0);
+
+ if (kerno != KSUCCESS) {
+ if (kerno == KDC_PR_UNKNOWN) {
+ warnx("kerberos: principal unknown: %s.%s@%s",
+ (uid == 0 ? username : user),
+ (uid == 0 ? "root" : ""), lrealm);
+ return (1);
+ }
+ warnx("kerberos: unable to su: %s", krb_err_txt[kerno]);
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "BAD Kerberos SU: %s to %s%s: %s",
+ username, user, ontty(), krb_err_txt[kerno]);
+ return (1);
+ }
+
+ if (chown(krbtkfile, uid, -1) < 0) {
+ warn("chown");
+ (void)unlink(krbtkfile);
+ return (1);
+ }
+
+ (void)setpriority(PRIO_PROCESS, 0, -2);
+
+ if (gethostname(hostname, sizeof(hostname)) == -1) {
+ warn("gethostname");
+ dest_tkt();
+ return (1);
+ }
+
+ (void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
+ savehost[sizeof(savehost) - 1] = '\0';
+
+ kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
+
+ if (kerno == KDC_PR_UNKNOWN) {
+ warnx("Warning: TGT not verified.");
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "%s to %s%s, TGT not verified (%s); %s.%s not registered?",
+ username, user, ontty(), krb_err_txt[kerno],
+ "rcmd", savehost);
+ } else if (kerno != KSUCCESS) {
+ warnx("Unable to use TGT: %s", krb_err_txt[kerno]);
+ syslog(LOG_NOTICE|LOG_AUTH, "failed su: %s to %s%s: %s",
+ username, user, ontty(), krb_err_txt[kerno]);
+ dest_tkt();
+ return (1);
+ } else {
+ if (!(hp = gethostbyname(hostname))) {
+ warnx("can't get addr of %s", hostname);
+ dest_tkt();
+ return (1);
+ }
+ memmove((char *)&faddr, (char *)hp->h_addr, sizeof(faddr));
+
+ if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
+ &authdata, "")) != KSUCCESS) {
+ warnx("kerberos: unable to verify rcmd ticket: %s\n",
+ krb_err_txt[kerno]);
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "failed su: %s to %s%s: %s", username,
+ user, ontty(), krb_err_txt[kerno]);
+ dest_tkt();
+ return (1);
+ }
+ }
+ return (0);
+}
+
+koktologin(name, realm, toname)
+ char *name, *realm, *toname;
+{
+ AUTH_DAT *kdata;
+ AUTH_DAT kdata_st;
+
+ kdata = &kdata_st;
+ memset((char *)kdata, 0, sizeof(*kdata));
+ (void)strcpy(kdata->pname, name);
+ (void)strcpy(kdata->pinst,
+ ((strcmp(toname, "root") == 0) ? "root" : ""));
+ (void)strcpy(kdata->prealm, realm);
+ return (kuserok(kdata, toname));
+}
+#endif
OpenPOWER on IntegriCloud