summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/su/su.134
-rw-r--r--usr.bin/su/su.c134
2 files changed, 89 insertions, 79 deletions
diff --git a/usr.bin/su/su.1 b/usr.bin/su/su.1
index 4809407d143..293c981bc06 100644
--- a/usr.bin/su/su.1
+++ b/usr.bin/su/su.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: su.1,v 1.3 1996/06/26 05:39:34 deraadt Exp $
+.\" $OpenBSD: su.1,v 1.4 1996/10/12 20:40:38 millert Exp $
.\" Copyright (c) 1988, 1990 The Regents of the University of California.
.\" All rights reserved.
.\"
@@ -57,7 +57,7 @@ are passed to the shell.
.Nm Su
will resort to the local password file to find the password for
.Ar login
-if there is a Kerberos error.
+if there is a Kerberos error or if Kerberos is not installed.
If
.Nm su
is executed by root, no password is requested and a shell
@@ -112,7 +112,7 @@ are modified as above.
is set to the target login.
.Ev PATH
is set to
-.Dq Pa /bin:/usr/bin .
+.Dq Pa /usr/bin:/bin .
.Ev TERM
is imported from your current environment.
The invoked shell is the target login's, and
@@ -136,6 +136,17 @@ and
.Fl m
options are mutually exclusive; the last one specified
overrides any previous ones.
+.Pp
+If the optional
+.Ar "shell arguments"
+are provided on the command line, they are passed to the login shell of
+the target login. This allows it to pass arbitrary commands via
+the
+.Fl c
+option as understood by most shells. Note that
+.Fl c
+usually expects a single argument only; you have to quote it when
+passing multiple words.
.Pp
If group 0 (normally
.Dq wheel )
@@ -152,6 +163,23 @@ 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 EXAMPLES
+.Bl -tag -width 5n -compact
+.It Li "su bin -c makewhatis"
+Runs the command
+.Li makewhatis
+as user
+.Li bin .
+You will be asked for bin's password unless your real UID is 0.
+.Pp
+.It Li "su bin -c 'makewhatis /usr/local/man'"
+Same as above, but the target command consists of more than a
+single word.
+.Pp
+.It Li "su -l foo"
+Pretend a login for user
+.Li foo .
+.El
.Sh SEE ALSO
.Xr csh 1 ,
.Xr login 1 ,
diff --git a/usr.bin/su/su.c b/usr.bin/su/su.c
index 9ba66b8153b..94a3aff8323 100644
--- a/usr.bin/su/su.c
+++ b/usr.bin/su/su.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: su.c,v 1.7 1996/10/12 17:13:57 millert Exp $ */
+/* $OpenBSD: su.c,v 1.8 1996/10/12 20:40:37 millert Exp $ */
/*
* Copyright (c) 1988 The Regents of the University of California.
@@ -41,20 +41,27 @@ char copyright[] =
#ifndef lint
/*static char sccsid[] = "from: @(#)su.c 5.26 (Berkeley) 7/6/91";*/
-static char rcsid[] = "$OpenBSD: su.c,v 1.7 1996/10/12 17:13:57 millert Exp $";
+static char rcsid[] = "$OpenBSD: su.c,v 1.8 1996/10/12 20:40:37 millert Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
-#include <syslog.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <paths.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
-#include <pwd.h>
-#include <grp.h>
#include <string.h>
+#include <syslog.h>
#include <unistd.h>
-#include <paths.h>
+
+#ifdef SKEY
+#include <skey.h>
+#endif
#ifdef KERBEROS
#include <kerberosIV/des.h>
@@ -68,8 +75,8 @@ int use_kerberos = 1;
#define ARGSTR "-flm"
#endif
-extern char *crypt();
-int chshell();
+char *ontty __P((void));
+int chshell __P((char *));
int
main(argc, argv)
@@ -77,7 +84,6 @@ main(argc, argv)
char **argv;
{
extern char **environ;
- extern int errno, optind;
register struct passwd *pwd;
register char *p, **g;
struct group *gr;
@@ -86,7 +92,6 @@ main(argc, argv)
enum { UNSET, YES, NO } iscsh = UNSET;
char *user, *shell, *avshell, *username, *cleanenv[10], **np;
char shellbuf[MAXPATHLEN], avshellbuf[MAXPATHLEN];
- char *getpass(), *getenv(), *getlogin(), *ontty();
asme = asthem = fastlogin = 0;
while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
@@ -130,10 +135,8 @@ main(argc, argv)
if (username == NULL || (pwd = getpwnam(username)) == NULL ||
pwd->pw_uid != ruid)
pwd = getpwuid(ruid);
- if (pwd == NULL) {
- fprintf(stderr, "su: who are you?\n");
- exit(1);
- }
+ if (pwd == NULL)
+ errx(1, "who are you?");
username = strdup(pwd->pw_name);
if (asme)
if (pwd->pw_shell && *pwd->pw_shell)
@@ -147,10 +150,8 @@ main(argc, argv)
user = *argv ? *argv : "root";
np = *argv ? argv : argv-1;
- if ((pwd = getpwnam(user)) == NULL) {
- fprintf(stderr, "su: unknown login %s\n", user);
- exit(1);
- }
+ if ((pwd = getpwnam(user)) == NULL)
+ errx(1, "unknown login %s", user);
if (ruid) {
#ifdef KERBEROS
@@ -161,13 +162,9 @@ main(argc, argv)
if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0))
&& gr->gr_mem && *(gr->gr_mem))
for (g = gr->gr_mem;; ++g) {
- if (!*g) {
- (void)fprintf(stderr,
- "su: you are not in the correct group to su %s.\n",
- user);
- exit(1);
- }
- if (!strcmp(username, *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 */
@@ -175,15 +172,10 @@ main(argc, argv)
p = getpass("Password:");
#ifdef SKEY
if (strcasecmp(p, "s/key") == 0) {
- if (skey_haskey(user)) {
- fprintf(stderr, "Sorry, you have no s/key.\n");
- exit(1);
- } else {
- if (skey_authenticate(user)) {
- goto badlogin;
- }
- }
-
+ if (skey_haskey(user))
+ errx(1, "Sorry, you have no s/key.");
+ else if (skey_authenticate(user))
+ goto badlogin;
} else
#endif
if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
@@ -196,15 +188,18 @@ badlogin:
}
}
}
+ if (pwd->pw_expire && time(NULL) >= pwd->pw_expire) {
+ fprintf(stderr, "Sorry - account expired\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) {
- (void)fprintf(stderr,
- "su: permission denied (shell).\n");
- exit(1);
- }
+ 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;
@@ -213,7 +208,7 @@ badlogin:
iscsh = NO;
}
- if (p = rindex(shell, '/'))
+ if (p = strrchr(shell, '/'))
avshell = p+1;
else
avshell = shell;
@@ -223,18 +218,12 @@ badlogin:
iscsh = strcmp(avshell, "csh") ? NO : YES;
/* set permissions */
- if (setgid(pwd->pw_gid) < 0) {
- perror("su: setgid");
- exit(1);
- }
- if (initgroups(user, pwd->pw_gid)) {
- (void)fprintf(stderr, "su: initgroups failed.\n");
- exit(1);
- }
- if (setuid(pwd->pw_uid) < 0) {
- perror("su: setuid");
- exit(1);
- }
+ if (setgid(pwd->pw_gid) < 0)
+ err(1, "setgid");
+ if (initgroups(user, pwd->pw_gid))
+ err(1, "initgroups failed");
+ if (setuid(pwd->pw_uid) < 0)
+ err(1, "setuid");
if (!asme) {
if (asthem) {
@@ -247,10 +236,8 @@ badlogin:
seteuid(pwd->pw_uid);
setegid(pwd->pw_gid);
- if (chdir(pwd->pw_dir) < 0) {
- fprintf(stderr, "su: no directory\n");
- exit(1);
- }
+ if (chdir(pwd->pw_dir) < 0)
+ errx(1, "no directory");
seteuid(0);
setegid(0); /* XXX use a saved gid instead? */
}
@@ -287,8 +274,7 @@ badlogin:
(void)setpriority(PRIO_PROCESS, 0, prio);
execv(shell, np);
- (void)fprintf(stderr, "su: %s not found.\n", shell);
- exit(1);
+ err(1, "%s", shell);
}
int
@@ -296,10 +282,9 @@ chshell(sh)
char *sh;
{
register char *cp;
- char *getusershell();
while ((cp = getusershell()) != NULL)
- if (!strcmp(cp, sh))
+ if (strcmp(cp, sh) == 0)
return (1);
return (0);
}
@@ -312,7 +297,7 @@ ontty()
buf[0] = 0;
if (p = ttyname(STDERR_FILENO))
- sprintf(buf, " on %s", p);
+ snprintf(buf, sizeof(buf), " on %s", p);
return (buf);
}
@@ -337,7 +322,8 @@ kerberos(username, user, uid)
(void)fprintf(stderr, "kerberos su: not in %s's ACL.\n", user);
return (1);
}
- (void)sprintf(krbtkfile, "%s_%s_%d", TKT_ROOT, user, getuid());
+ (void)snprintf(krbtkfile, sizeof(krbtkfile), "%s_%s_%d", TKT_ROOT,
+ user, getuid());
(void)setenv("KRBTKFILE", krbtkfile, 1);
(void)krb_set_tkt_string(krbtkfile);
@@ -346,7 +332,7 @@ kerberos(username, user, uid)
* to make the kerberos library do the right thing.
*/
if (setuid(0) < 0) {
- perror("su: setuid");
+ warn("setuid");
return (1);
}
@@ -366,13 +352,12 @@ kerberos(username, user, uid)
if (kerno != KSUCCESS) {
if (kerno == KDC_PR_UNKNOWN) {
- fprintf(stderr, "principal unknown: %s.%s@%s\n",
+ warnx("kerberos principal unknown: %s.%s@%s",
(uid == 0 ? username : user),
(uid == 0 ? "root" : ""), lrealm);
return (1);
}
- (void)fprintf(stderr, "su: unable to su: %s\n",
- krb_err_txt[kerno]);
+ warnx("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]);
@@ -380,7 +365,7 @@ kerberos(username, user, uid)
}
if (chown(krbtkfile, uid, -1) < 0) {
- perror("su: chown:");
+ warn("chown");
(void)unlink(krbtkfile);
return (1);
}
@@ -388,7 +373,7 @@ kerberos(username, user, uid)
(void)setpriority(PRIO_PROCESS, 0, -2);
if (gethostname(hostname, sizeof(hostname)) == -1) {
- perror("su: gethostname");
+ warn("gethostname");
dest_tkt();
return (1);
}
@@ -399,22 +384,20 @@ kerberos(username, user, uid)
kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
if (kerno == KDC_PR_UNKNOWN) {
- (void)fprintf(stderr, "Warning: TGT not verified.\n");
+ 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) {
- (void)fprintf(stderr, "Unable to use TGT: %s\n",
- krb_err_txt[kerno]);
+ 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))) {
- (void)fprintf(stderr, "su: can't get addr of %s\n",
- hostname);
+ warnx("can't get addr of %s", hostname);
dest_tkt();
return (1);
}
@@ -422,9 +405,8 @@ kerberos(username, user, uid)
if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
&authdata, "")) != KSUCCESS) {
- (void)fprintf(stderr,
- "su: unable to verify rcmd ticket: %s\n",
- krb_err_txt[kerno]);
+ warnx("unable to verify rcmd ticket: %s",
+ krb_err_txt[kerno]);
syslog(LOG_NOTICE|LOG_AUTH,
"failed su: %s to %s%s: %s", username,
user, ontty(), krb_err_txt[kerno]);