Annotation of 43BSDReno/old/athena/ksu/ksu.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * $Source: /mit/kerberos/src/kuser/RCS/ksu.c,v $
                      3:  * $Author: jtkohl $
                      4:  */
                      5: 
                      6: /*
                      7:  * Copyright (c) 1988 The Regents of the University of California.
                      8:  * All rights reserved.
                      9:  *
                     10:  * Redistribution and use in source and binary forms are permitted
                     11:  * provided that the above copyright notice and this paragraph are
                     12:  * duplicated in all such forms and that any documentation,
                     13:  * advertising materials, and other materials related to such
                     14:  * distribution and use acknowledge that the software was developed
                     15:  * by the University of California, Berkeley.  The name of the
                     16:  * University may not be used to endorse or promote products derived
                     17:  * from this software without specific prior written permission.
                     18:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     20:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     21:  */
                     22: 
                     23: /*
                     24:  * Kerberos additions Copyright 1987, 1988 by the Massachusetts Institute
                     25:  * of Technology. For copying and distribution information, please see
                     26:  * the file <mit-copyright.h>.
                     27:  */
                     28: 
                     29: #ifndef lint
                     30: static char rcsid_ksu_c[] =
                     31: "$Header: ksu.c,v 4.0 89/01/23 10:00:28 jtkohl Exp $";
                     32: #endif lint
                     33: 
                     34: #ifndef lint
                     35: char copyright[] =
                     36: "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
                     37:  All rights reserved.\n";
                     38: #endif /* not lint */
                     39: 
                     40: #ifndef lint
                     41: static char sccsid[] = "@(#)su.c       5.11 (Berkeley) 12/7/88";
                     42: #endif /* not lint */
                     43: 
                     44: #include <kerberos/mit-copyright.h>
                     45: #include <sys/param.h>
                     46: #include <sys/time.h>
                     47: #include <sys/resource.h>
                     48: #include <syslog.h>
                     49: #include <stdio.h>
                     50: #include <pwd.h>
                     51: #include <grp.h>
                     52: #include <kerberos/krb.h>
                     53: #include <netdb.h>
                     54: #include <sys/ioctl.h>
                     55: 
                     56: #ifndef LOG_AUTH
                     57: #define LOG_AUTH 0
                     58: #endif /* LOG_AUTH */
                     59: 
                     60: /* for Ultrix and friends ... */
                     61: #ifndef MAXHOSTNAMELEN
                     62: #define MAXHOSTNAMELEN 64
                     63: #endif
                     64: 
                     65: extern char *krb_err_txt[];
                     66: int     kerno;
                     67: char    lrealm[REALM_SZ];
                     68: char    krbtkfile[128];
                     69: 
                     70: #define MAXPWSIZE      128     /* Biggest string we accept for a password
                     71:                                   (includes space for null terminator) */
                     72: 
                     73: main(argc, argv)
                     74:        int argc;
                     75:        char **argv;
                     76: {
                     77:        extern char **environ;
                     78:        extern int errno, optind;
                     79:        register struct passwd *pwd;
                     80:        register char *p, **g;
                     81:        struct group *gr;
                     82:        uid_t ruid, getuid();
                     83: #ifdef NO_GETUSERSHELL
                     84:        int ch, fulllogin, fastlogin, prio;
                     85: #else
                     86:        int asme, ch, fulllogin, fastlogin, prio;
                     87: #endif /* NO_GETUSERSHELL */
                     88:        enum { UNSET, YES, NO } iscsh = UNSET;
                     89:        char *user, *shell, *username, *cleanenv[2], *nargv[4], **np;
                     90:        char namebuf[50], shellbuf[MAXPATHLEN];
                     91:        char *crypt(), *getpass(), *getenv(), *getlogin(), *rindex(), *strcpy();
                     92: #ifdef NOENCRYPTION
                     93: #define read_long_pw_string placebo_read_pw_string
                     94: #else
                     95: #define read_long_pw_string des_read_pw_string
                     96: #endif
                     97:        int read_long_pw_string();
                     98:        char pw_buf[MAXPWSIZE];
                     99:        char   *mytty;
                    100:   
                    101:        mytty = isatty(2) ? (char *) ttyname(2) : "(no tty)";
                    102: 
                    103:        np = &nargv[3];
                    104:        *np-- = NULL;
                    105: #ifdef NO_GETUSERSHELL
                    106:        fulllogin = fastlogin = 0;
                    107: #define GETOPTARG "-flm"
                    108: #else
                    109:        asme = fulllogin = fastlogin = 0;
                    110: #define        GETOPTARG "-fl"
                    111: #endif
                    112:        while ((ch = getopt(argc, argv, GETOPTARG)) != EOF)
                    113:                switch((char)ch) {
                    114:                case 'f':
                    115:                        fastlogin = 1;
                    116:                        break;
                    117:                case '-':
                    118:                case 'l':
                    119:                        fulllogin = 1;
                    120:                        break;
                    121: #ifndef NO_GETUSERSHELL
                    122:                case 'm':
                    123:                        asme = 1;
                    124:                        break;
                    125: #endif
                    126:                case '?':
                    127:                default:
                    128: #ifdef NO_GETUSERSHELL
                    129:                        fprintf(stderr, "usage: ksu [-fl] [login]\n");
                    130: #else
                    131:                        fprintf(stderr, "usage: ksu [-flm] [login]\n");
                    132: #endif /* NO_GETUSERSHELL */
                    133:                        exit(1);
                    134:                }
                    135:        argv += optind;
                    136: 
                    137:        errno = 0;
                    138:        prio = getpriority(PRIO_PROCESS, 0);
                    139:        if (errno)
                    140:                prio = 0;
                    141:        (void)setpriority(PRIO_PROCESS, 0, -2);
                    142: 
                    143:        /* get current login name and shell */
                    144:        if ((pwd = getpwuid(ruid = getuid())) == NULL) {
                    145:                fprintf(stderr, "ksu: who are you?\n");
                    146:                exit(1);
                    147:        }
                    148:        username = strcpy(namebuf, pwd->pw_name);
                    149: #ifndef NO_GETUSERSHELL
                    150:        if (asme)
                    151:                if (pwd->pw_shell && *pwd->pw_shell)
                    152:                        shell = strcpy(shellbuf,  pwd->pw_shell);
                    153:                else {
                    154:                        shell = "/bin/sh";
                    155:                        iscsh = NO;
                    156:                }
                    157: #endif
                    158: 
                    159:        /* get target login information */
                    160:        user = *argv ? *argv : "root";
                    161:        if ((pwd = getpwnam(user)) == NULL) {
                    162:                fprintf(stderr, "ksu: unknown login %s\n", user);
                    163:                exit(1);
                    164:        }
                    165: 
                    166:        /*
                    167:         * Only allow those with kerberos root instances in the /.klogin
                    168:         * file to su to root. 
                    169:         */
                    170:        if (pwd->pw_uid == 0) {
                    171:            KTEXT_ST ticket;
                    172:            AUTH_DAT authdata;
                    173:            char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
                    174:            unsigned long faddr;
                    175:            struct hostent *hp;
                    176: 
                    177:            /* First lets see if he has a chance! */
                    178:            if (krb_get_lrealm(lrealm, 1) != KSUCCESS) {
                    179:                fprintf(stderr,"Unable to get local realm\n");
                    180:                exit(1);
                    181:            }
                    182:            if (koktologin(username, lrealm)) {
                    183:                fprintf(stderr,"You are not allowed to ksu to root\n");
                    184:                exit(1);
                    185:            }
                    186:            sprintf(krbtkfile, "/tmp/tkt_root_%d", getuid());
                    187:            setuid(0);          /* so ticket file has good protection */
                    188:            if (read_long_pw_string(pw_buf, sizeof(pw_buf)-1,
                    189:                                   "Your root instance password: ", 0)) {
                    190:                fprintf(stderr,"Error reading password.\n");
                    191:                exit(1);
                    192:            }
                    193:            p = pw_buf;
                    194:            setenv("KRBTKFILE", krbtkfile, 1);
                    195:            kerno = krb_get_pw_in_tkt(username, "root", lrealm, "krbtgt",
                    196:                                      lrealm, 2, p);
                    197:            bzero(p, strlen(p));
                    198:            if (kerno != KSUCCESS) {
                    199:                printf("Unable to ksu: %s\n", krb_err_txt[kerno]);
                    200:                syslog(LOG_NOTICE|LOG_AUTH, "ksu: BAD SU %s on %s: %s",
                    201:                       username, mytty, krb_err_txt[kerno]);
                    202:                exit(1);
                    203:            }
                    204:            setpriority(PRIO_PROCESS, 0, -2);
                    205:            /*
                    206:             * Now use the ticket for something useful, to make sure
                    207:             * it is valid.
                    208:             */
                    209:            if (gethostname(hostname, sizeof(hostname)) == -1) {
                    210:                perror("cannot retrieve hostname");
                    211:                dest_tkt();
                    212:                exit(1);
                    213:            }
                    214:            (void) strncpy(savehost, krb_get_phost(hostname),
                    215:                           sizeof(savehost));
                    216:            savehost[sizeof(savehost)-1] = 0;
                    217: 
                    218:            kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
                    219:            if (kerno == KDC_PR_UNKNOWN) {
                    220:                printf("Warning: tgt not verified\n");
                    221:                syslog(LOG_NOTICE|LOG_AUTH, "ksu: %s on %s: tgt not verified",
                    222:                       username, mytty);
                    223:            } else if (kerno != KSUCCESS) {
                    224:                printf("Unable to use tgt: %s\n", krb_err_txt[kerno]);
                    225:                syslog(LOG_NOTICE|LOG_AUTH, "ksu: failed su: %s on %s: %s",
                    226:                       username, mytty, krb_err_txt[kerno]);
                    227:                dest_tkt();
                    228:                exit(1);
                    229:            } else {
                    230:                if (!(hp = gethostbyname(hostname))) {
                    231:                    printf("Unable to get address of %s\n",hostname);
                    232:                    dest_tkt();
                    233:                    exit(1);
                    234:                }
                    235:                bcopy((char *)hp->h_addr, (char *) &faddr, sizeof(faddr));
                    236:                if ((kerno = krb_rd_req(&ticket, "rcmd", savehost,
                    237:                                        faddr, &authdata, "")) != KSUCCESS) {
                    238:                    printf("Unable to verify rcmd ticket: %s\n",
                    239:                           krb_err_txt[kerno]);
                    240:                    syslog(LOG_NOTICE|LOG_AUTH, "ksu: failed su: %s on %s: %s",
                    241:                           username, mytty, krb_err_txt[kerno]);
                    242:                    dest_tkt();
                    243:                    exit(1);
                    244:                }               
                    245:            }
                    246:            printf("Don't forget to kdestroy before exiting the root shell.\n");
                    247:        } else
                    248:        /* if target requires a password, verify it */
                    249:        if (ruid && *pwd->pw_passwd) {
                    250:                p = getpass("Password:");
                    251:                if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
                    252:                        fprintf(stderr, "Sorry\n");
                    253:                        if (pwd->pw_uid == 0)
                    254:                                syslog(LOG_CRIT|LOG_AUTH, "ksu: BAD SU %s on %s", username, mytty);
                    255:                        exit(1);
                    256:                }
                    257:        }
                    258: 
                    259: #ifndef NO_GETUSERSHELL
                    260:        if (asme) {
                    261:                /* if asme and non-standard target shell, must be root */
                    262:                if (!chshell(pwd->pw_shell) && ruid) {
                    263:                        fprintf(stderr, "ksu: Permission denied.\n");
                    264:                        dest_tkt();
                    265:                        exit(1);
                    266:                }
                    267:        }
                    268:        else
                    269: #endif
                    270:        if (pwd->pw_shell && *pwd->pw_shell) {
                    271:                shell = pwd->pw_shell;
                    272:                iscsh = UNSET;
                    273:        } else {
                    274:                shell = "/bin/sh";
                    275:                iscsh = NO;
                    276:        }
                    277: 
                    278:        /* if we're forking a csh, we want to slightly muck the args */
                    279:        if (iscsh == UNSET) {
                    280:                if (p = rindex(shell, '/'))
                    281:                        ++p;
                    282:                else
                    283:                        p = shell;
                    284:                iscsh = strcmp(p, "csh") ? NO : YES;
                    285:        }
                    286: 
                    287:        /* set permissions */
                    288:        if (setgid(pwd->pw_gid) < 0) {
                    289:                perror("ksu: setgid");
                    290:                dest_tkt();
                    291:                exit(1);
                    292:        }
                    293:        if (initgroups(user, pwd->pw_gid)) {
                    294:                fprintf(stderr, "ksu: initgroups failed\n");
                    295:                dest_tkt();
                    296:                exit(1);
                    297:        }
                    298:        if (setuid(pwd->pw_uid) < 0) {
                    299:                perror("ksu: setuid");
                    300:                dest_tkt();
                    301:                exit(1);
                    302:        }
                    303: 
                    304: #ifndef NO_GETUSERSHELL
                    305:        if (!asme) {
                    306: #endif
                    307:                if (fulllogin) {
                    308:                        p = getenv("TERM");
                    309:                        cleanenv[0] = "PATH=:/usr/ucb:/bin:/usr/bin";
                    310:                        cleanenv[1] = NULL;
                    311:                        environ = cleanenv;
                    312:                        (void)setenv("TERM", p, 1);
                    313:                        if (chdir(pwd->pw_dir) < 0) {
                    314:                                fprintf(stderr, "ksu: no directory\n");
                    315:                                dest_tkt();
                    316:                                exit(1);
                    317:                        }
                    318:                }
                    319:                if (fulllogin || pwd->pw_uid)
                    320:                        (void)setenv("USER", pwd->pw_name, 1);
                    321:                (void)setenv("HOME", pwd->pw_dir, 1);
                    322:                (void)setenv("SHELL", shell, 1);
                    323: #ifndef NO_GETUSERSHELL
                    324:        }
                    325: #endif
                    326: 
                    327:        if (iscsh == YES) {
                    328:                if (fastlogin)
                    329:                        *np-- = "-f";
                    330: #ifndef NO_GETUSERSHELL
                    331:                if (asme)
                    332:                        *np-- = "-m";
                    333: #endif
                    334:        }
                    335: 
                    336:        /* csh strips the first character... */
                    337:        *np = fulllogin ? "-ksu" : iscsh == YES ? "_ksu" : "ksu";
                    338: 
                    339:        if (pwd->pw_uid == 0)
                    340:                syslog(LOG_NOTICE|LOG_AUTH, "ksu: %s on %s",
                    341:                    username, mytty);
                    342: 
                    343:        (void)setpriority(PRIO_PROCESS, 0, prio);
                    344: 
                    345:        execv(shell, np);
                    346:        fprintf(stderr, "ksu: no shell.\n");
                    347:        dest_tkt();
                    348:        exit(1);
                    349: }
                    350: 
                    351: #ifndef NO_GETUSERSHELL
                    352: chshell(sh)
                    353:        char *sh;
                    354: {
                    355:        char *cp, *getusershell();
                    356: 
                    357:        while ((cp = getusershell()) != NULL)
                    358:                if (!strcmp(cp, sh))
                    359:                        return(1);
                    360:        return(0);
                    361: }
                    362: #endif /* NO_GETUSERSHELL */
                    363: 
                    364: koktologin(name, realm)
                    365:     char   *name;
                    366:     char   *realm;
                    367: {
                    368:     struct auth_dat kdata_st;
                    369:     AUTH_DAT *kdata = &kdata_st;
                    370:     /* Cons together an AUTH_DAT structure for kuserok */
                    371:     bzero((caddr_t) kdata, sizeof(*kdata));
                    372:     strcpy(kdata->pname, name);
                    373:     strcpy(kdata->pinst, "root");
                    374:     strcpy(kdata->prealm, realm);
                    375:     return (kuserok(kdata, "root"));
                    376: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.