su.c revision 36391
11556Srgrimes/* 21556Srgrimes * Copyright (c) 1988, 1993, 1994 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * Redistribution and use in source and binary forms, with or without 61556Srgrimes * modification, are permitted provided that the following conditions 71556Srgrimes * are met: 81556Srgrimes * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 3. All advertising materials mentioning features or use of this software 141556Srgrimes * must display the following acknowledgement: 151556Srgrimes * This product includes software developed by the University of 161556Srgrimes * California, Berkeley and its contributors. 171556Srgrimes * 4. Neither the name of the University nor the names of its contributors 181556Srgrimes * may be used to endorse or promote products derived from this software 191556Srgrimes * without specific prior written permission. 201556Srgrimes * 211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311556Srgrimes * SUCH DAMAGE. 321556Srgrimes */ 331556Srgrimes 341556Srgrimes#ifndef lint 351556Srgrimesstatic const char copyright[] = 361556Srgrimes"@(#) Copyright (c) 1988, 1993, 1994\n\ 371556Srgrimes The Regents of the University of California. All rights reserved.\n"; 381556Srgrimes#endif /* not lint */ 3936049Scharnier 4036049Scharnier#ifndef lint 4136049Scharnier#if 0 4236049Scharnierstatic char sccsid[] = "@(#)su.c 8.3 (Berkeley) 4/2/94"; 4350471Speter#endif 441556Srgrimesstatic const char rcsid[] = 451556Srgrimes "$Id: su.c,v 1.26 1998/05/25 03:34:52 steve Exp $"; 461556Srgrimes#endif /* not lint */ 471556Srgrimes 481556Srgrimes#include <sys/param.h> 491556Srgrimes#include <sys/time.h> 501556Srgrimes#include <sys/resource.h> 511556Srgrimes 521556Srgrimes#include <err.h> 531556Srgrimes#include <errno.h> 541556Srgrimes#include <grp.h> 551556Srgrimes#include <paths.h> 561556Srgrimes#include <pwd.h> 571556Srgrimes#include <stdio.h> 581556Srgrimes#include <stdlib.h> 591556Srgrimes#include <string.h> 601556Srgrimes#include <syslog.h> 611556Srgrimes#include <unistd.h> 621556Srgrimes 631556Srgrimes#ifdef LOGIN_CAP 641556Srgrimes#include <login_cap.h> 651556Srgrimes#ifdef LOGIN_CAP_AUTH 661556Srgrimes#undef SKEY 671556Srgrimes#undef KERBEROS 681556Srgrimes#endif 691556Srgrimes#endif 701556Srgrimes 711556Srgrimes#ifdef SKEY 721556Srgrimes#include <skey.h> 731556Srgrimes#endif 741556Srgrimes 751556Srgrimes#ifdef KERBEROS 761556Srgrimes#include <des.h> 771556Srgrimes#include <krb.h> 7876017Skris#include <netdb.h> 791556Srgrimes 801556Srgrimes#ifdef LOGIN_CAP 811556Srgrimes#define ARGSTR "-Kflmc:" 821556Srgrimes#else 831556Srgrimes#define ARGSTR "-Kflm" 841556Srgrimes#endif 851556Srgrimes 861556Srgrimesstatic int kerberos(char *username, char *user, int uid, char *pword); 871556Srgrimesstatic int koktologin(char *name, char *toname); 881556Srgrimes 891556Srgrimesint use_kerberos = 1; 901556Srgrimes#else /* !KERBEROS */ 911556Srgrimes#ifdef LOGIN_CAP 921556Srgrimes#define ARGSTR "-flmc:" 931556Srgrimes#else 941556Srgrimes#define ARGSTR "-flm" 951556Srgrimes#endif 961556Srgrimes#endif /* KERBEROS */ 9746684Skris 981556Srgrimeschar *ontty __P((void)); 991556Srgrimesint chshell __P((char *)); 1001556Srgrimesstatic void usage __P((void)); 1011556Srgrimes 1021556Srgrimesint 1031556Srgrimesmain(argc, argv) 1041556Srgrimes int argc; 1051556Srgrimes char **argv; 1061556Srgrimes{ 1071556Srgrimes extern char **environ; 1081556Srgrimes struct passwd *pwd; 1091556Srgrimes#ifdef WHEELSU 1101556Srgrimes char *targetpass; 1111556Srgrimes int iswheelsu; 1121556Srgrimes#endif /* WHEELSU */ 1131556Srgrimes char *p, **g, *user, *shell=NULL, *username, **cleanenv, **nargv, **np; 1141556Srgrimes struct group *gr; 1151556Srgrimes uid_t ruid; 1161556Srgrimes gid_t gid; 1171556Srgrimes int asme, ch, asthem, fastlogin, prio, i; 1181556Srgrimes enum { UNSET, YES, NO } iscsh = UNSET; 1191556Srgrimes#ifdef LOGIN_CAP 1201556Srgrimes login_cap_t *lc; 1211556Srgrimes char *class=NULL; 1221556Srgrimes int setwhat; 1231556Srgrimes#ifdef LOGIN_CAP_AUTH 1241556Srgrimes char *style, *approvep, *auth_method = NULL; 1251556Srgrimes#endif 12676017Skris#endif 1271556Srgrimes#ifdef KERBEROS 1281556Srgrimes char *k; 1291556Srgrimes#endif 1301556Srgrimes char shellbuf[MAXPATHLEN]; 1311556Srgrimes 1321556Srgrimes#ifdef WHEELSU 1331556Srgrimes iswheelsu = 1341556Srgrimes#endif /* WHEELSU */ 1351556Srgrimes asme = asthem = fastlogin = 0; 1361556Srgrimes user = "root"; 1371556Srgrimes while(optind < argc) 1381556Srgrimes if((ch = getopt(argc, argv, ARGSTR)) != -1) 1391556Srgrimes switch((char)ch) { 1401556Srgrimes#ifdef KERBEROS 14176017Skris case 'K': 1421556Srgrimes use_kerberos = 0; 1431556Srgrimes break; 1441556Srgrimes#endif 1451556Srgrimes case 'f': 1461556Srgrimes fastlogin = 1; 1471556Srgrimes break; 1481556Srgrimes case '-': 1491556Srgrimes case 'l': 1501556Srgrimes asme = 0; 1511556Srgrimes asthem = 1; 1521556Srgrimes break; 1531556Srgrimes case 'm': 1541556Srgrimes asme = 1; 1551556Srgrimes asthem = 0; 15676017Skris break; 1571556Srgrimes#ifdef LOGIN_CAP 1581556Srgrimes case 'c': 1591556Srgrimes class = optarg; 1601556Srgrimes break; 1611556Srgrimes#endif 1628855Srgrimes case '?': 1631556Srgrimes default: 1641556Srgrimes usage(); 1651556Srgrimes } 1661556Srgrimes else 1671556Srgrimes { 1681556Srgrimes user = argv[optind++]; 1691556Srgrimes break; 1701556Srgrimes } 1711556Srgrimes 1721556Srgrimes if (strlen(user) > MAXLOGNAME - 1) { 1731556Srgrimes (void)fprintf(stderr, "su: username too long.\n"); 1741556Srgrimes exit(1); 1751556Srgrimes } 1761556Srgrimes 1771556Srgrimes if (user == NULL) 1781556Srgrimes usage(); 1791556Srgrimes 1801556Srgrimes if ((nargv = malloc (sizeof (char *) * (argc + 4))) == NULL) { 1811556Srgrimes errx(1, "malloc failure"); 1821556Srgrimes } 1838855Srgrimes 1841556Srgrimes nargv[argc + 3] = NULL; 1851556Srgrimes for (i = argc; i >= optind; i--) 1861556Srgrimes nargv[i + 3] = argv[i]; 1871556Srgrimes np = &nargv[i + 3]; 18876017Skris 1891556Srgrimes argv += optind; 1901556Srgrimes 1911556Srgrimes errno = 0; 1921556Srgrimes prio = getpriority(PRIO_PROCESS, 0); 1931556Srgrimes if (errno) 1941556Srgrimes prio = 0; 1951556Srgrimes (void)setpriority(PRIO_PROCESS, 0, -2); 1961556Srgrimes openlog("su", LOG_CONS, 0); 1971556Srgrimes 1981556Srgrimes /* get current login name and shell */ 1991556Srgrimes ruid = getuid(); 2001556Srgrimes username = getlogin(); 2011556Srgrimes if (username == NULL || (pwd = getpwnam(username)) == NULL || 2021556Srgrimes pwd->pw_uid != ruid) 2031556Srgrimes pwd = getpwuid(ruid); 20476017Skris if (pwd == NULL) 2051556Srgrimes errx(1, "who are you?"); 2061556Srgrimes username = strdup(pwd->pw_name); 2071556Srgrimes gid = pwd->pw_gid; 2081556Srgrimes if (username == NULL) 2091556Srgrimes err(1, NULL); 21076017Skris if (asme) { 2111556Srgrimes if (pwd->pw_shell != NULL && *pwd->pw_shell != '\0') { 2121556Srgrimes /* copy: pwd memory is recycled */ 2131556Srgrimes shell = strncpy(shellbuf, pwd->pw_shell, sizeof shellbuf); 2141556Srgrimes shellbuf[sizeof shellbuf - 1] = '\0'; 2151556Srgrimes } else { 2161556Srgrimes shell = _PATH_BSHELL; 2171556Srgrimes iscsh = NO; 2181556Srgrimes } 2191556Srgrimes } 2201556Srgrimes 22176017Skris#ifdef LOGIN_CAP_AUTH 2221556Srgrimes if (auth_method = strchr(user, ':')) { 2231556Srgrimes *auth_method = '\0'; 2241556Srgrimes auth_method++; 2251556Srgrimes if (*auth_method == '\0') 2261556Srgrimes auth_method = NULL; 2271556Srgrimes } 22876017Skris#endif /* !LOGIN_CAP_AUTH */ 2291556Srgrimes 2301556Srgrimes /* get target login information, default to root */ 2311556Srgrimes if ((pwd = getpwnam(user)) == NULL) { 2321556Srgrimes errx(1, "unknown login: %s", user); 2331556Srgrimes } 2341556Srgrimes#ifdef LOGIN_CAP 2351556Srgrimes if (class==NULL) { 2361556Srgrimes lc = login_getpwclass(pwd); 2371556Srgrimes } else { 23846684Skris if (ruid) 2391556Srgrimes errx(1, "only root may use -c"); 2401556Srgrimes lc = login_getclass(class); 2411556Srgrimes if (lc == NULL) 2421556Srgrimes errx(1, "unknown class: %s", class); 2431556Srgrimes } 2441556Srgrimes#endif 2451556Srgrimes 2461556Srgrimes#ifdef WHEELSU 2471556Srgrimes targetpass = strdup(pwd->pw_passwd); 2481556Srgrimes#endif /* WHEELSU */ 2491556Srgrimes 2501556Srgrimes if (ruid) { 2511556Srgrimes#ifdef KERBEROS 2521556Srgrimes if (use_kerberos && koktologin(username, user) 2531556Srgrimes && !pwd->pw_uid) { 2541556Srgrimes warnx("kerberos: not in %s's ACL.", user); 2551556Srgrimes use_kerberos = 0; 2561556Srgrimes } 2571556Srgrimes#endif 25876017Skris { 2591556Srgrimes /* 2601556Srgrimes * Only allow those with pw_gid==0 or those listed in 2611556Srgrimes * group zero to su to root. If group zero entry is 2621556Srgrimes * missing or empty, then allow anyone to su to root. 2631556Srgrimes * iswheelsu will only be set if the user is EXPLICITLY 2641556Srgrimes * listed in group zero. 2651556Srgrimes */ 2661556Srgrimes if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0)) && 2671556Srgrimes gr->gr_mem && *(gr->gr_mem)) 2681556Srgrimes for (g = gr->gr_mem;; ++g) { 2698855Srgrimes if (!*g) 2701556Srgrimes if (gid == 0) 2711556Srgrimes break; 2721556Srgrimes else 2731556Srgrimes errx(1, "you are not in the correct group to su %s.", user); 2741556Srgrimes if (strcmp(username, *g) == 0) { 2751556Srgrimes#ifdef WHEELSU 2761556Srgrimes iswheelsu = 1; 2771556Srgrimes#endif /* WHEELSU */ 2781556Srgrimes break; 2791556Srgrimes } 2801556Srgrimes } 2811556Srgrimes } 28276017Skris /* if target requires a password, verify it */ 2831556Srgrimes if (*pwd->pw_passwd) { 2841556Srgrimes#ifdef LOGIN_CAP_AUTH 2851556Srgrimes /* 2861556Srgrimes * This hands off authorisation to an authorisation program, 2871556Srgrimes * depending on the styles available for the "auth-su", 2881556Srgrimes * authorisation styles. 2891556Srgrimes */ 2901556Srgrimes if ((style = login_getstyle(lc, auth_method, "su")) == NULL) 2911556Srgrimes errx(1, "auth method available for su.\n"); 2921556Srgrimes if (authenticate(user, lc ? lc->lc_class : "default", style, "su") != 0) { 2931556Srgrimes#ifdef WHEELSU 2941556Srgrimes if (!iswheelsu || authenticate(username, lc ? lc->lc_class : "default", style, "su") != 0) { 2951556Srgrimes#endif /* WHEELSU */ 2961556Srgrimes { 2971556Srgrimes fprintf(stderr, "Sorry\n"); 2981556Srgrimes syslog(LOG_AUTH|LOG_WARNING,"BAD SU %s to %s%s", username, user, ontty()); 2991556Srgrimes exit(1); 3001556Srgrimes } 30176017Skris } 3021556Srgrimes 3031556Srgrimes /* 3041556Srgrimes * If authentication succeeds, run any approval 3051556Srgrimes * program, if applicable for this class. 3061556Srgrimes */ 3071556Srgrimes approvep = login_getcapstr(lc, "approve", NULL, NULL); 3081556Srgrimes if (approvep==NULL || auth_script(approvep, approvep, username, lc->lc_class, 0) == 0) { 3091556Srgrimes int r = auth_scan(AUTH_OKAY); 3101556Srgrimes /* See what the authorise program says */ 3111556Srgrimes if (!(r & AUTH_ROOTOKAY) && pwd->pw_uid == 0) { 3121556Srgrimes fprintf(stderr, "Sorry\n"); 3131556Srgrimes syslog(LOG_AUTH|LOG_WARNING,"UNAPPROVED ROOT SU %s%s", user, ontty()); 3141556Srgrimes exit(1); 3151556Srgrimes } 3161556Srgrimes } 3171556Srgrimes#else /* !LOGIN_CAP_AUTH */ 3181556Srgrimes#ifdef SKEY 3191556Srgrimes#ifdef WHEELSU 3201556Srgrimes if (iswheelsu) { 3211556Srgrimes pwd = getpwnam(username); 3221556Srgrimes } 3231556Srgrimes#endif /* WHEELSU */ 3241556Srgrimes p = skey_getpass("Password:", pwd, 1); 3251556Srgrimes if (!(!strcmp(pwd->pw_passwd, skey_crypt(p, pwd->pw_passwd, pwd, 1)) 3261556Srgrimes#ifdef WHEELSU 3271556Srgrimes || (iswheelsu && !strcmp(targetpass, crypt(p,targetpass))) 3281556Srgrimes#endif /* WHEELSU */ 32976017Skris )) { 3301556Srgrimes#else 3311556Srgrimes p = getpass("Password:"); 3321556Srgrimes if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) { 3331556Srgrimes#endif 3341556Srgrimes#ifdef KERBEROS 3351556Srgrimes if (!use_kerberos || (use_kerberos && kerberos(username, user, pwd->pw_uid, p))) 3361556Srgrimes#endif 3371556Srgrimes { 33876017Skris fprintf(stderr, "Sorry\n"); 3391556Srgrimes syslog(LOG_AUTH|LOG_WARNING, "BAD SU %s to %s%s", username, user, ontty()); 3401556Srgrimes exit(1); 3411556Srgrimes } 3421556Srgrimes } 34376017Skris#ifdef WHEELSU 3441556Srgrimes if (iswheelsu) { 3451556Srgrimes pwd = getpwnam(user); 3461556Srgrimes } 3471556Srgrimes#endif /* WHEELSU */ 3481556Srgrimes#endif /* LOGIN_CAP_AUTH */ 3491556Srgrimes } 3501556Srgrimes if (pwd->pw_expire && time(NULL) >= pwd->pw_expire) { 3511556Srgrimes fprintf(stderr, "Sorry - account expired\n"); 3521556Srgrimes syslog(LOG_AUTH|LOG_WARNING, 3531556Srgrimes "BAD SU %s to %s%s", username, 3541556Srgrimes user, ontty()); 3551556Srgrimes exit(1); 3561556Srgrimes } 3571556Srgrimes } 3581556Srgrimes 3591556Srgrimes if (asme) { 3601556Srgrimes /* if asme and non-standard target shell, must be root */ 3611556Srgrimes if (!chshell(pwd->pw_shell) && ruid) 36276017Skris errx(1, "permission denied (shell)."); 3631556Srgrimes } else if (pwd->pw_shell && *pwd->pw_shell) { 3641556Srgrimes shell = pwd->pw_shell; 3651556Srgrimes iscsh = UNSET; 3661556Srgrimes } else { 3671556Srgrimes shell = _PATH_BSHELL; 3681556Srgrimes iscsh = NO; 3691556Srgrimes } 3701556Srgrimes 3711556Srgrimes /* if we're forking a csh, we want to slightly muck the args */ 3721556Srgrimes if (iscsh == UNSET) { 3731556Srgrimes p = strrchr(shell, '/'); 3741556Srgrimes if (p) 3751556Srgrimes ++p; 3761556Srgrimes else 3771556Srgrimes p = shell; 3781556Srgrimes if ((iscsh = strcmp(p, "csh") ? NO : YES) == NO) 3791556Srgrimes iscsh = strcmp(p, "tcsh") ? NO : YES; 3801556Srgrimes } 3811556Srgrimes 3821556Srgrimes (void)setpriority(PRIO_PROCESS, 0, prio); 38376017Skris 3841556Srgrimes#ifdef LOGIN_CAP 3851556Srgrimes /* Set everything now except the environment & umask */ 3861556Srgrimes setwhat = LOGIN_SETUSER|LOGIN_SETGROUP|LOGIN_SETRESOURCES|LOGIN_SETPRIORITY; 3871556Srgrimes /* 3881556Srgrimes * Don't touch resource/priority settings if -m has been 3891556Srgrimes * used or -l and -c hasn't, and we're not su'ing to root. 3901556Srgrimes */ 3911556Srgrimes if ((asme || (!asthem && class == NULL)) && pwd->pw_uid) 3921556Srgrimes setwhat &= ~(LOGIN_SETPRIORITY|LOGIN_SETRESOURCES); 3931556Srgrimes if (setusercontext(lc, pwd, pwd->pw_uid, setwhat) < 0) 3941556Srgrimes err(1, "setusercontext"); 3951556Srgrimes#else 3961556Srgrimes /* set permissions */ 3971556Srgrimes if (setgid(pwd->pw_gid) < 0) 3981556Srgrimes err(1, "setgid"); 3991556Srgrimes if (initgroups(user, pwd->pw_gid)) 4001556Srgrimes errx(1, "initgroups failed"); 4011556Srgrimes if (setuid(pwd->pw_uid) < 0) 4021556Srgrimes err(1, "setuid"); 4031556Srgrimes#endif 4041556Srgrimes 4051556Srgrimes if (!asme) { 4061556Srgrimes if (asthem) { 4071556Srgrimes p = getenv("TERM"); 4081556Srgrimes#ifdef KERBEROS 4091556Srgrimes k = getenv("KRBTKFILE"); 4101556Srgrimes#endif 4111556Srgrimes if ((cleanenv = calloc(20, sizeof(char*))) == NULL) 4121556Srgrimes errx(1, "calloc"); 4131556Srgrimes cleanenv[0] = NULL; 4141556Srgrimes environ = cleanenv; 4151556Srgrimes#ifdef LOGIN_CAP 4161556Srgrimes /* set the su'd user's environment & umask */ 4171556Srgrimes setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH|LOGIN_SETUMASK|LOGIN_SETENV); 4181556Srgrimes#else 4191556Srgrimes (void)setenv("PATH", _PATH_DEFPATH, 1); 4201556Srgrimes#endif 4211556Srgrimes if (p) 4221556Srgrimes (void)setenv("TERM", p, 1); 4231556Srgrimes#ifdef KERBEROS 4241556Srgrimes if (k) 4251556Srgrimes (void)setenv("KRBTKFILE", k, 1); 4261556Srgrimes#endif 4271556Srgrimes if (chdir(pwd->pw_dir) < 0) 4281556Srgrimes errx(1, "no directory"); 42976017Skris } 4301556Srgrimes if (asthem || pwd->pw_uid) 4311556Srgrimes (void)setenv("USER", pwd->pw_name, 1); 4321556Srgrimes (void)setenv("HOME", pwd->pw_dir, 1); 4331556Srgrimes (void)setenv("SHELL", shell, 1); 4341556Srgrimes } 4351556Srgrimes if (iscsh == YES) { 4361556Srgrimes if (fastlogin) 4371556Srgrimes *np-- = "-f"; 4381556Srgrimes if (asme) 4391556Srgrimes *np-- = "-m"; 4401556Srgrimes } 4411556Srgrimes 4421556Srgrimes /* csh strips the first character... */ 4431556Srgrimes *np = asthem ? "-su" : iscsh == YES ? "_su" : "su"; 4441556Srgrimes 44576017Skris if (ruid != 0) 4461556Srgrimes syslog(LOG_NOTICE|LOG_AUTH, "%s to %s%s", 4471556Srgrimes username, user, ontty()); 4481556Srgrimes 4491556Srgrimes login_close(lc); 4501556Srgrimes 4511556Srgrimes execv(shell, np); 4521556Srgrimes err(1, "%s", shell); 4531556Srgrimes} 4541556Srgrimes 4551556Srgrimesstatic void 4561556Srgrimesusage() 4571556Srgrimes{ 4581556Srgrimes (void)fprintf(stderr, "usage: su [%s] [login [args]]\n", ARGSTR); 4591556Srgrimes exit(1); 4601556Srgrimes} 4611556Srgrimes 4621556Srgrimesint 4631556Srgrimeschshell(sh) 4641556Srgrimes char *sh; 4651556Srgrimes{ 4661556Srgrimes int r = 0; 4671556Srgrimes char *cp; 4681556Srgrimes 46976017Skris setusershell(); 4701556Srgrimes while (!r && (cp = getusershell()) != NULL) 4711556Srgrimes r = strcmp(cp, sh) == 0; 4721556Srgrimes endusershell(); 4731556Srgrimes return r; 4741556Srgrimes} 4751556Srgrimes 4761556Srgrimeschar * 4771556Srgrimesontty() 4781556Srgrimes{ 4791556Srgrimes char *p; 4801556Srgrimes static char buf[MAXPATHLEN + 4]; 4811556Srgrimes 4821556Srgrimes buf[0] = 0; 4831556Srgrimes p = ttyname(STDERR_FILENO); 4841556Srgrimes if (p) 4851556Srgrimes snprintf(buf, sizeof(buf), " on %s", p); 4861556Srgrimes return (buf); 4871556Srgrimes} 4881556Srgrimes 4891556Srgrimes#ifdef KERBEROS 4901556Srgrimesint 4911556Srgrimeskerberos(username, user, uid, pword) 4921556Srgrimes char *username, *user; 4931556Srgrimes int uid; 4941556Srgrimes char *pword; 4951556Srgrimes{ 4961556Srgrimes KTEXT_ST ticket; 4971556Srgrimes AUTH_DAT authdata; 4981556Srgrimes int kerno; 4991556Srgrimes u_long faddr; 5001556Srgrimes char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN]; 5011556Srgrimes char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN]; 5021556Srgrimes char *krb_get_phost(); 5031556Srgrimes struct hostent *hp; 50476017Skris 5051556Srgrimes if (krb_get_lrealm(lrealm, 1) != KSUCCESS) 5061556Srgrimes return (1); 5071556Srgrimes (void)sprintf(krbtkfile, "%s_%s_%lu", TKT_ROOT, user, 5081556Srgrimes (unsigned long)getuid()); 5091556Srgrimes 5101556Srgrimes (void)setenv("KRBTKFILE", krbtkfile, 1); 5111556Srgrimes (void)krb_set_tkt_string(krbtkfile); 5121556Srgrimes /* 5131556Srgrimes * Set real as well as effective ID to 0 for the moment, 5141556Srgrimes * to make the kerberos library do the right thing. 5151556Srgrimes */ 5161556Srgrimes if (setuid(0) < 0) { 5171556Srgrimes warn("setuid"); 5181556Srgrimes return (1); 5191556Srgrimes } 5201556Srgrimes 5211556Srgrimes /* 5221556Srgrimes * Little trick here -- if we are su'ing to root, 5231556Srgrimes * we need to get a ticket for "xxx.root", where xxx represents 5241556Srgrimes * the name of the person su'ing. Otherwise (non-root case), 5251556Srgrimes * we need to get a ticket for "yyy.", where yyy represents 5261556Srgrimes * the name of the person being su'd to, and the instance is null 5271556Srgrimes * 5281556Srgrimes * We should have a way to set the ticket lifetime, 5291556Srgrimes * with a system default for root. 5301556Srgrimes */ 5311556Srgrimes kerno = krb_get_pw_in_tkt((uid == 0 ? username : user), 5321556Srgrimes (uid == 0 ? "root" : ""), lrealm, 5331556Srgrimes "krbtgt", lrealm, DEFAULT_TKT_LIFE, pword); 5341556Srgrimes 5351556Srgrimes if (kerno != KSUCCESS) { 5361556Srgrimes if (kerno == KDC_PR_UNKNOWN) { 5371556Srgrimes warnx("kerberos: principal unknown: %s.%s@%s", 5381556Srgrimes (uid == 0 ? username : user), 5391556Srgrimes (uid == 0 ? "root" : ""), lrealm); 5401556Srgrimes return (1); 5411556Srgrimes } 5421556Srgrimes warnx("kerberos: unable to su: %s", krb_err_txt[kerno]); 5431556Srgrimes syslog(LOG_NOTICE|LOG_AUTH, 5441556Srgrimes "BAD Kerberos SU: %s to %s%s: %s", 5451556Srgrimes username, user, ontty(), krb_err_txt[kerno]); 54676017Skris return (1); 5471556Srgrimes } 5481556Srgrimes 5491556Srgrimes if (chown(krbtkfile, uid, -1) < 0) { 5501556Srgrimes warn("chown"); 5511556Srgrimes (void)unlink(krbtkfile); 5521556Srgrimes return (1); 5531556Srgrimes } 5541556Srgrimes 5551556Srgrimes (void)setpriority(PRIO_PROCESS, 0, -2); 5561556Srgrimes 5571556Srgrimes if (gethostname(hostname, sizeof(hostname)) == -1) { 5581556Srgrimes warn("gethostname"); 5591556Srgrimes dest_tkt(); 5601556Srgrimes return (1); 5611556Srgrimes } 5621556Srgrimes 5631556Srgrimes (void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost)); 5641556Srgrimes savehost[sizeof(savehost) - 1] = '\0'; 5651556Srgrimes 5661556Srgrimes kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33); 5671556Srgrimes 5681556Srgrimes if (kerno == KDC_PR_UNKNOWN) { 5691556Srgrimes warnx("Warning: TGT not verified."); 5701556Srgrimes syslog(LOG_NOTICE|LOG_AUTH, 5711556Srgrimes "%s to %s%s, TGT not verified (%s); %s.%s not registered?", 5721556Srgrimes username, user, ontty(), krb_err_txt[kerno], 5738855Srgrimes "rcmd", savehost); 57476017Skris } else if (kerno != KSUCCESS) { 5751556Srgrimes warnx("Unable to use TGT: %s", krb_err_txt[kerno]); 5761556Srgrimes syslog(LOG_NOTICE|LOG_AUTH, "failed su: %s to %s%s: %s", 5771556Srgrimes username, user, ontty(), krb_err_txt[kerno]); 5781556Srgrimes dest_tkt(); 5791556Srgrimes return (1); 5801556Srgrimes } else { 5811556Srgrimes if (!(hp = gethostbyname(hostname))) { 5821556Srgrimes warnx("can't get addr of %s", hostname); 5831556Srgrimes dest_tkt(); 58476017Skris return (1); 5851556Srgrimes } 5861556Srgrimes memmove((char *)&faddr, (char *)hp->h_addr, sizeof(faddr)); 5871556Srgrimes 5881556Srgrimes if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr, 5891556Srgrimes &authdata, "")) != KSUCCESS) { 5901556Srgrimes warnx("kerberos: unable to verify rcmd ticket: %s\n", 5911556Srgrimes krb_err_txt[kerno]); 5921556Srgrimes syslog(LOG_NOTICE|LOG_AUTH, 5931556Srgrimes "failed su: %s to %s%s: %s", username, 5941556Srgrimes user, ontty(), krb_err_txt[kerno]); 5951556Srgrimes dest_tkt(); 5961556Srgrimes return (1); 5971556Srgrimes } 5981556Srgrimes } 5991556Srgrimes return (0); 6001556Srgrimes} 6011556Srgrimes 6021556Srgrimesint 6031556Srgrimeskoktologin(name, toname) 60476017Skris char *name, *toname; 6051556Srgrimes{ 6061556Srgrimes AUTH_DAT *kdata; 6071556Srgrimes AUTH_DAT kdata_st; 6081556Srgrimes char realm[REALM_SZ]; 6091556Srgrimes 6101556Srgrimes if (krb_get_lrealm(realm, 1) != KSUCCESS) 6111556Srgrimes return (1); 6121556Srgrimes kdata = &kdata_st; 6131556Srgrimes memset((char *)kdata, 0, sizeof(*kdata)); 6141556Srgrimes (void)strncpy(kdata->pname, name, sizeof kdata->pname - 1); 6151556Srgrimes (void)strncpy(kdata->pinst, 6161556Srgrimes ((strcmp(toname, "root") == 0) ? "root" : ""), sizeof kdata->pinst - 1); 6171556Srgrimes (void)strncpy(kdata->prealm, realm, sizeof kdata->prealm - 1); 6181556Srgrimes return (kuserok(kdata, toname)); 6191556Srgrimes} 6201556Srgrimes#endif 6211556Srgrimes