|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.