break out special local mail processing (e.g., mapping to the
[unix-history] / usr / src / usr.bin / su / su.c
index 94db30a..7f1c6cd 100644 (file)
@@ -1,30 +1,34 @@
 /*
 /*
- * Copyright (c) 1988 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
  *
  * %sccs.include.redist.c%
  */
 
 #ifndef lint
  *
  * %sccs.include.redist.c%
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1988 The Regents of the University of California.\n\
- All rights reserved.\n";
+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
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)su.c       5.25 (Berkeley) %G%";
+static char sccsid[] = "@(#)su.c       8.3 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/resource.h>
-#include <syslog.h>
-#include <stdio.h>
-#include <pwd.h>
+
+#include <err.h>
+#include <errno.h>
 #include <grp.h>
 #include <grp.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <syslog.h>
 #include <unistd.h>
 #include <unistd.h>
-#include <paths.h>
 
 #ifdef KERBEROS
 #include <kerberosIV/des.h>
 
 #ifdef KERBEROS
 #include <kerberosIV/des.h>
@@ -38,21 +42,22 @@ int use_kerberos = 1;
 #define        ARGSTR  "-flm"
 #endif
 
 #define        ARGSTR  "-flm"
 #endif
 
+char   *ontty __P((void));
+int    chshell __P((char *));
+
+int
 main(argc, argv)
        int argc;
        char **argv;
 {
        extern char **environ;
 main(argc, argv)
        int argc;
        char **argv;
 {
        extern char **environ;
-       extern int errno, optind;
-       register struct passwd *pwd;
-       register char *p, **g;
+       struct passwd *pwd;
+       char *p, **g, *user, *shell, *username, *cleanenv[2], *nargv[4], **np;
        struct group *gr;
        struct group *gr;
-       uid_t ruid, getuid();
+       uid_t ruid;
        int asme, ch, asthem, fastlogin, prio;
        enum { UNSET, YES, NO } iscsh = UNSET;
        int asme, ch, asthem, fastlogin, prio;
        enum { UNSET, YES, NO } iscsh = UNSET;
-       char *user, *shell, *username, *cleanenv[2], *nargv[4], **np;
        char shellbuf[MAXPATHLEN];
        char shellbuf[MAXPATHLEN];
-       char *crypt(), *getpass(), *getenv(), *getlogin(), *ontty();
 
        np = &nargv[3];
        *np-- = NULL;
 
        np = &nargv[3];
        *np-- = NULL;
@@ -97,11 +102,11 @@ main(argc, argv)
        if (username == NULL || (pwd = getpwnam(username)) == NULL ||
            pwd->pw_uid != ruid)
                pwd = getpwuid(ruid);
        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);
        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);
        if (asme)
                if (pwd->pw_shell && *pwd->pw_shell)
                        shell = strcpy(shellbuf,  pwd->pw_shell);
@@ -117,22 +122,21 @@ main(argc, argv)
                exit(1);
        }
 
                exit(1);
        }
 
-       /* 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) {
-                               (void)fprintf(stderr,
-                                   "su: you are not in the correct group to su %s.\n", user);
-                               exit(1);
-                       }
-                       if (!strcmp(username, *g))
-                               break;
-               }
-
        if (ruid) {
 #ifdef KERBEROS
        if (ruid) {
 #ifdef KERBEROS
-               if (!use_kerberos || kerberos(username, user, pwd->pw_uid))
+           if (!use_kerberos || kerberos(username, user, pwd->pw_uid))
 #endif
 #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 target requires a password, verify it */
                if (*pwd->pw_passwd) {
                        p = getpass("Password:");
@@ -144,15 +148,13 @@ main(argc, argv)
                                exit(1);
                        }
                }
                                exit(1);
                        }
                }
+           }
        }
 
        if (asme) {
                /* if asme and non-standard target shell, must be root */
        }
 
        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;
        } else if (pwd->pw_shell && *pwd->pw_shell) {
                shell = pwd->pw_shell;
                iscsh = UNSET;
@@ -163,7 +165,7 @@ main(argc, argv)
 
        /* if we're forking a csh, we want to slightly muck the args */
        if (iscsh == UNSET) {
 
        /* if we're forking a csh, we want to slightly muck the args */
        if (iscsh == UNSET) {
-               if (p = rindex(shell, '/'))
+               if (p = strrchr(shell, '/'))
                        ++p;
                else
                        p = shell;
                        ++p;
                else
                        p = shell;
@@ -171,18 +173,12 @@ main(argc, argv)
        }
 
        /* set permissions */
        }
 
        /* 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))
+               errx(1, "initgroups failed");
+       if (setuid(pwd->pw_uid) < 0)
+               err(1, "setuid");
 
        if (!asme) {
                if (asthem) {
 
        if (!asme) {
                if (asthem) {
@@ -191,10 +187,8 @@ main(argc, argv)
                        cleanenv[1] = NULL;
                        environ = cleanenv;
                        (void)setenv("TERM", p, 1);
                        cleanenv[1] = NULL;
                        environ = cleanenv;
                        (void)setenv("TERM", p, 1);
-                       if (chdir(pwd->pw_dir) < 0) {
-                               fprintf(stderr, "su: no directory\n");
-                               exit(1);
-                       }
+                       if (chdir(pwd->pw_dir) < 0)
+                               errx(1, "no directory");
                }
                if (asthem || pwd->pw_uid)
                        (void)setenv("USER", pwd->pw_name, 1);
                }
                if (asthem || pwd->pw_uid)
                        (void)setenv("USER", pwd->pw_name, 1);
@@ -219,31 +213,30 @@ main(argc, argv)
        (void)setpriority(PRIO_PROCESS, 0, prio);
 
        execv(shell, np);
        (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
 chshell(sh)
        char *sh;
 {
 chshell(sh)
        char *sh;
 {
-       register char *cp;
-       char *getusershell();
+       char *cp;
 
        while ((cp = getusershell()) != NULL)
 
        while ((cp = getusershell()) != NULL)
-               if (!strcmp(cp, sh))
-                       return(1);
-       return(0);
+               if (strcmp(cp, sh) == 0)
+                       return (1);
+       return (0);
 }
 
 char *
 ontty()
 {
 }
 
 char *
 ontty()
 {
-       char *p, *ttyname();
+       char *p;
        static char buf[MAXPATHLEN + 4];
 
        buf[0] = 0;
        if (p = ttyname(STDERR_FILENO))
        static char buf[MAXPATHLEN + 4];
 
        buf[0] = 0;
        if (p = ttyname(STDERR_FILENO))
-               sprintf(buf, " on %s", p);
+               snprintf(buf, sizeof(buf), " on %s", p);
        return (buf);
 }
 
        return (buf);
 }
 
@@ -256,33 +249,31 @@ kerberos(username, user, uid)
        KTEXT_ST ticket;
        AUTH_DAT authdata;
        struct hostent *hp;
        KTEXT_ST ticket;
        AUTH_DAT authdata;
        struct hostent *hp;
-       register char *p;
+       char *p;
        int kerno;
        u_long faddr;
        char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN];
        char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
        int kerno;
        u_long faddr;
        char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN];
        char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
-       char *ontty(), *krb_get_phost();
+       char *krb_get_phost();
 
 
-       if (krb_get_lrealm(lrealm, 1) != KSUCCESS) {
-               (void)fprintf(stderr, "su: couldn't get local realm.\n");
-               return(1);
-       }
+       if (krb_get_lrealm(lrealm, 1) != KSUCCESS)
+               return (1);
        if (koktologin(username, lrealm, user) && !uid) {
        if (koktologin(username, lrealm, user) && !uid) {
-               (void)fprintf(stderr, "kerberos su: not in %s's ACL.\n", user);
-               return(1);
+               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)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) {
        /*
         * 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) {
-               perror("su: setuid");
-               return(1);
+               warn("setuid");
+               return (1);
        }
        }
-       (void)unlink(krbtkfile);
 
        /*
         * Little trick here -- if we are su'ing to root,
 
        /*
         * Little trick here -- if we are su'ing to root,
@@ -300,30 +291,30 @@ kerberos(username, user, uid)
 
        if (kerno != KSUCCESS) {
                if (kerno == KDC_PR_UNKNOWN) {
 
        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);
                                (uid == 0 ? username : user),
                                (uid == 0 ? "root" : ""), lrealm);
-                       return(1);
+                       return (1);
                }
                }
-               (void)printf("su: unable to su: %s\n", krb_err_txt[kerno]);
+               warnx("kerberos: unable to su: %s", krb_err_txt[kerno]);
                syslog(LOG_NOTICE|LOG_AUTH,
                syslog(LOG_NOTICE|LOG_AUTH,
-                   "su: BAD Kerberos SU: %s to %s%s: %s",
+                   "BAD Kerberos SU: %s to %s%s: %s",
                    username, user, ontty(), krb_err_txt[kerno]);
                    username, user, ontty(), krb_err_txt[kerno]);
-               return(1);
+               return (1);
        }
 
        if (chown(krbtkfile, uid, -1) < 0) {
        }
 
        if (chown(krbtkfile, uid, -1) < 0) {
-               perror("su: chown:");
+               warn("chown");
                (void)unlink(krbtkfile);
                (void)unlink(krbtkfile);
-               return(1);
+               return (1);
        }
 
        (void)setpriority(PRIO_PROCESS, 0, -2);
 
        if (gethostname(hostname, sizeof(hostname)) == -1) {
        }
 
        (void)setpriority(PRIO_PROCESS, 0, -2);
 
        if (gethostname(hostname, sizeof(hostname)) == -1) {
-               perror("su: hostname");
+               warn("gethostname");
                dest_tkt();
                dest_tkt();
-               return(1);
+               return (1);
        }
 
        (void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
        }
 
        (void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost));
@@ -332,50 +323,51 @@ kerberos(username, user, uid)
        kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
 
        if (kerno == KDC_PR_UNKNOWN) {
        kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
 
        if (kerno == KDC_PR_UNKNOWN) {
-               (void)printf("Warning: tgt not verified.\n");
+               warnx("Warning: TGT not verified.");
                syslog(LOG_NOTICE|LOG_AUTH,
                syslog(LOG_NOTICE|LOG_AUTH,
-                       "su: %s to %s%s, TGT not verified",
-                       username, user, ontty());
+                   "%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) {
        } else if (kerno != KSUCCESS) {
-               (void)printf("Unable to use TGT: %s\n", krb_err_txt[kerno]);
-               syslog(LOG_NOTICE|LOG_AUTH, "su: failed su: %s to %s%s: %s",
+               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();
                    username, user, ontty(), krb_err_txt[kerno]);
                dest_tkt();
-               return(1);
+               return (1);
        } else {
                if (!(hp = gethostbyname(hostname))) {
        } else {
                if (!(hp = gethostbyname(hostname))) {
-                       (void)printf("su: can't get addr of %s\n", hostname);
+                       warnx("can't get addr of %s", hostname);
                        dest_tkt();
                        dest_tkt();
-                       return(1);
+                       return (1);
                }
                }
-               (void)bcopy((char *)hp->h_addr, (char *)&faddr, sizeof(faddr));
+               memmove((char *)&faddr, (char *)hp->h_addr, sizeof(faddr));
 
                if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
                    &authdata, "")) != KSUCCESS) {
 
                if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr,
                    &authdata, "")) != KSUCCESS) {
-                       (void)printf("su: unable to verify rcmd ticket: %s\n",
+                       warnx("kerberos: unable to verify rcmd ticket: %s\n",
                            krb_err_txt[kerno]);
                        syslog(LOG_NOTICE|LOG_AUTH,
                            krb_err_txt[kerno]);
                        syslog(LOG_NOTICE|LOG_AUTH,
-                           "su: failed su: %s to %s%s: %s", username,
-                           ontty(), user, krb_err_txt[kerno]);
+                           "failed su: %s to %s%s: %s", username,
+                            user, ontty(), krb_err_txt[kerno]);
                        dest_tkt();
                        dest_tkt();
-                       return(1);
+                       return (1);
                }
        }
                }
        }
-       return(0);
+       return (0);
 }
 
 koktologin(name, realm, toname)
        char *name, *realm, *toname;
 {
 }
 
 koktologin(name, realm, toname)
        char *name, *realm, *toname;
 {
-       register AUTH_DAT *kdata;
+       AUTH_DAT *kdata;
        AUTH_DAT kdata_st;
 
        kdata = &kdata_st;
        AUTH_DAT kdata_st;
 
        kdata = &kdata_st;
-       bzero((caddr_t) kdata, sizeof(*kdata));
+       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);
        (void)strcpy(kdata->pname, name);
        (void)strcpy(kdata->pinst,
            ((strcmp(toname, "root") == 0) ? "root" : ""));
        (void)strcpy(kdata->prealm, realm);
-       return(kuserok(kdata, toname));
+       return (kuserok(kdata, toname));
 }
 #endif
 }
 #endif