1 /* 2 * Copyright (c) 1988, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#) Copyright (c) 1988, 1993, 1994 The Regents of the University of California. All rights reserved. 34 * @(#)su.c 8.3 (Berkeley) 4/2/94 35 * $FreeBSD: src/usr.bin/su/su.c,v 1.34.2.4 2002/06/16 21:04:15 nectar Exp $ 36 * $DragonFly: src/usr.bin/su/su.c,v 1.2 2003/06/17 04:29:32 dillon Exp $ 37 */ 38 39 #include <sys/param.h> 40 #include <sys/time.h> 41 #include <sys/resource.h> 42 43 #include <err.h> 44 #include <errno.h> 45 #include <grp.h> 46 #include <paths.h> 47 #include <pwd.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <syslog.h> 52 #include <unistd.h> 53 #include <libutil.h> 54 55 #ifdef LOGIN_CAP 56 #include <login_cap.h> 57 #endif 58 59 #ifdef SKEY 60 #include <skey.h> 61 #endif 62 63 #ifdef KERBEROS5 64 #include <krb5.h> 65 66 static long get_su_principal(krb5_context context, const char *target_user, 67 const char *current_user, char **su_principal_name, 68 krb5_principal *su_principal); 69 static long kerberos5(krb5_context context, const char *current_user, 70 const char *target_user, krb5_principal su_principal, 71 const char *pass); 72 73 int use_kerberos5 = 1; 74 #endif 75 76 #ifdef KERBEROS4 77 #include <openssl/des.h> 78 #include <krb.h> 79 #include <netdb.h> 80 81 82 static int kerberos4(char *username, char *user, int uid, char *pword); 83 static int koktologin(char *name, char *toname); 84 85 int use_kerberos4 = 1; 86 #endif /* KERBEROS4 */ 87 88 #ifdef LOGIN_CAP 89 #define LOGIN_CAP_ARG(x) x 90 #else 91 #define LOGIN_CAP_ARG(x) 92 #endif 93 #if defined(KERBEROS4) || defined(KERBEROS5) 94 #define KERBEROS_ARG(x) x 95 #else 96 #define KERBEROS_ARG(x) 97 #endif 98 #define COMMON_ARG(x) x 99 #define ARGSTR "-" COMMON_ARG("flm") LOGIN_CAP_ARG("c:") KERBEROS_ARG("K") 100 101 char *ontty __P((void)); 102 int chshell __P((char *)); 103 static void usage __P((void)); 104 105 int 106 main(argc, argv) 107 int argc; 108 char **argv; 109 { 110 extern char **environ; 111 struct passwd *pwd; 112 #ifdef WHEELSU 113 char *targetpass; 114 int iswheelsu; 115 #endif /* WHEELSU */ 116 char *p, **g, *user, *shell=NULL, *username, **cleanenv, **nargv, **np; 117 struct group *gr; 118 uid_t ruid; 119 gid_t gid; 120 int asme, ch, asthem, fastlogin, prio, i; 121 enum { UNSET, YES, NO } iscsh = UNSET; 122 #ifdef LOGIN_CAP 123 login_cap_t *lc; 124 char *class=NULL; 125 int setwhat; 126 #endif 127 #if defined(KERBEROS4) || defined(KERBEROS5) 128 char *k; 129 #endif 130 #ifdef KERBEROS5 131 char *su_principal_name, *ccname; 132 krb5_context context; 133 krb5_principal su_principal; 134 #endif 135 char shellbuf[MAXPATHLEN]; 136 137 #ifdef WHEELSU 138 iswheelsu = 139 #endif /* WHEELSU */ 140 asme = asthem = fastlogin = 0; 141 user = "root"; 142 while((ch = getopt(argc, argv, ARGSTR)) != -1) 143 switch((char)ch) { 144 #if defined(KERBEROS4) || defined(KERBEROS5) 145 case 'K': 146 #ifdef KERBEROS4 147 use_kerberos4 = 0; 148 #endif 149 #ifdef KERBEROS5 150 use_kerberos5 = 0; 151 #endif 152 break; 153 #endif 154 case 'f': 155 fastlogin = 1; 156 break; 157 case '-': 158 case 'l': 159 asme = 0; 160 asthem = 1; 161 break; 162 case 'm': 163 asme = 1; 164 asthem = 0; 165 break; 166 #ifdef LOGIN_CAP 167 case 'c': 168 class = optarg; 169 break; 170 #endif 171 case '?': 172 default: 173 usage(); 174 } 175 176 if (optind < argc) 177 user = argv[optind++]; 178 179 if (strlen(user) > MAXLOGNAME - 1) { 180 (void)fprintf(stderr, "su: username too long.\n"); 181 exit(1); 182 } 183 184 if (user == NULL) 185 usage(); 186 187 if ((nargv = malloc (sizeof (char *) * (argc + 4))) == NULL) { 188 errx(1, "malloc failure"); 189 } 190 191 nargv[argc + 3] = NULL; 192 for (i = argc; i >= optind; i--) 193 nargv[i + 3] = argv[i]; 194 np = &nargv[i + 3]; 195 196 argv += optind; 197 198 #if defined(KERBEROS4) || defined(KERBEROS5) 199 k = auth_getval("auth_list"); 200 if (k && !strstr(k, "kerberos")) { 201 #ifdef KERBEROS4 202 use_kerberos4 = 0; 203 #endif 204 #ifdef KERBEROS5 205 use_kerberos5 = 0; 206 #endif 207 } 208 #endif 209 #ifdef KERBEROS5 210 su_principal_name = NULL; 211 su_principal = NULL; 212 if (krb5_init_context(&context) != 0) 213 use_kerberos5 = 0; 214 #endif 215 errno = 0; 216 prio = getpriority(PRIO_PROCESS, 0); 217 if (errno) 218 prio = 0; 219 (void)setpriority(PRIO_PROCESS, 0, -2); 220 openlog("su", LOG_CONS, 0); 221 222 /* get current login name and shell */ 223 ruid = getuid(); 224 username = getlogin(); 225 if (username == NULL || (pwd = getpwnam(username)) == NULL || 226 pwd->pw_uid != ruid) 227 pwd = getpwuid(ruid); 228 if (pwd == NULL) 229 errx(1, "who are you?"); 230 username = strdup(pwd->pw_name); 231 gid = pwd->pw_gid; 232 if (username == NULL) 233 err(1, NULL); 234 if (asme) { 235 if (pwd->pw_shell != NULL && *pwd->pw_shell != '\0') { 236 /* copy: pwd memory is recycled */ 237 shell = strncpy(shellbuf, pwd->pw_shell, sizeof shellbuf); 238 shellbuf[sizeof shellbuf - 1] = '\0'; 239 } else { 240 shell = _PATH_BSHELL; 241 iscsh = NO; 242 } 243 } 244 245 /* get target login information, default to root */ 246 if ((pwd = getpwnam(user)) == NULL) { 247 errx(1, "unknown login: %s", user); 248 } 249 #ifdef LOGIN_CAP 250 if (class==NULL) { 251 lc = login_getpwclass(pwd); 252 } else { 253 if (ruid) 254 errx(1, "only root may use -c"); 255 lc = login_getclass(class); 256 if (lc == NULL) 257 errx(1, "unknown class: %s", class); 258 } 259 #endif 260 261 #ifdef WHEELSU 262 targetpass = strdup(pwd->pw_passwd); 263 #endif /* WHEELSU */ 264 265 if (ruid) { 266 #ifdef KERBEROS4 267 if (use_kerberos4 && koktologin(username, user) 268 && !pwd->pw_uid) { 269 warnx("kerberos4: not in %s's ACL.", user); 270 use_kerberos4 = 0; 271 } 272 #endif 273 #ifdef KERBEROS5 274 if (use_kerberos5) { 275 if (get_su_principal(context, user, username, 276 &su_principal_name, &su_principal) != 0 || 277 !krb5_kuserok(context, su_principal, user)) { 278 warnx("kerberos5: not in %s's ACL.", user); 279 use_kerberos5 = 0; 280 } 281 } 282 #endif 283 { 284 /* 285 * Only allow those with pw_gid==0 or those listed in 286 * group zero to su to root. If group zero entry is 287 * missing or empty, then allow anyone to su to root. 288 * iswheelsu will only be set if the user is EXPLICITLY 289 * listed in group zero. 290 */ 291 if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0)) && 292 gr->gr_mem && *(gr->gr_mem)) 293 for (g = gr->gr_mem;; ++g) { 294 if (!*g) { 295 if (gid == 0) 296 break; 297 else 298 errx(1, 299 "you are not in the correct group (%s) to su %s.", 300 gr->gr_name, 301 user); 302 } 303 if (strcmp(username, *g) == 0) { 304 #ifdef WHEELSU 305 iswheelsu = 1; 306 #endif /* WHEELSU */ 307 break; 308 } 309 } 310 } 311 /* if target requires a password, verify it */ 312 if (*pwd->pw_passwd) { 313 #ifdef SKEY 314 #ifdef WHEELSU 315 if (iswheelsu) { 316 pwd = getpwnam(username); 317 } 318 #endif /* WHEELSU */ 319 p = skey_getpass("Password:", pwd, 1); 320 if (!(!strcmp(pwd->pw_passwd, skey_crypt(p, pwd->pw_passwd, pwd, 1)) 321 #ifdef WHEELSU 322 || (iswheelsu && !strcmp(targetpass, crypt(p,targetpass))) 323 #endif /* WHEELSU */ 324 )) { 325 #else 326 p = getpass("Password:"); 327 if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) { 328 #endif 329 #ifdef KERBEROS4 330 if (use_kerberos4 && kerberos4(username, user, 331 pwd->pw_uid, p) == 0) 332 goto authok; 333 #endif 334 #ifdef KERBEROS5 335 if (use_kerberos5 && kerberos5(context, 336 username, user, su_principal, p) == 0) 337 goto authok; 338 #endif 339 fprintf(stderr, "Sorry\n"); 340 syslog(LOG_AUTH|LOG_WARNING, 341 "BAD SU %s to %s%s", username, user, 342 ontty()); 343 exit(1); 344 } 345 #if defined(KERBEROS4) || defined(KERBEROS5) 346 authok: 347 #endif 348 #ifdef WHEELSU 349 if (iswheelsu) { 350 pwd = getpwnam(user); 351 } 352 #endif /* WHEELSU */ 353 } 354 if (pwd->pw_expire && time(NULL) >= pwd->pw_expire) { 355 fprintf(stderr, "Sorry - account expired\n"); 356 syslog(LOG_AUTH|LOG_WARNING, 357 "BAD SU %s to %s%s", username, 358 user, ontty()); 359 exit(1); 360 } 361 } 362 363 if (asme) { 364 /* if asme and non-standard target shell, must be root */ 365 if (!chshell(pwd->pw_shell) && ruid) 366 errx(1, "permission denied (shell)."); 367 } else if (pwd->pw_shell && *pwd->pw_shell) { 368 shell = pwd->pw_shell; 369 iscsh = UNSET; 370 } else { 371 shell = _PATH_BSHELL; 372 iscsh = NO; 373 } 374 375 /* if we're forking a csh, we want to slightly muck the args */ 376 if (iscsh == UNSET) { 377 p = strrchr(shell, '/'); 378 if (p) 379 ++p; 380 else 381 p = shell; 382 if ((iscsh = strcmp(p, "csh") ? NO : YES) == NO) 383 iscsh = strcmp(p, "tcsh") ? NO : YES; 384 } 385 386 (void)setpriority(PRIO_PROCESS, 0, prio); 387 388 #ifdef LOGIN_CAP 389 /* Set everything now except the environment & umask */ 390 setwhat = LOGIN_SETUSER|LOGIN_SETGROUP|LOGIN_SETRESOURCES|LOGIN_SETPRIORITY; 391 /* 392 * Don't touch resource/priority settings if -m has been 393 * used or -l and -c hasn't, and we're not su'ing to root. 394 */ 395 if ((asme || (!asthem && class == NULL)) && pwd->pw_uid) 396 setwhat &= ~(LOGIN_SETPRIORITY|LOGIN_SETRESOURCES); 397 if (setusercontext(lc, pwd, pwd->pw_uid, setwhat) < 0) 398 err(1, "setusercontext"); 399 #else 400 /* set permissions */ 401 if (setgid(pwd->pw_gid) < 0) 402 err(1, "setgid"); 403 if (initgroups(user, pwd->pw_gid)) 404 errx(1, "initgroups failed"); 405 if (setuid(pwd->pw_uid) < 0) 406 err(1, "setuid"); 407 #endif 408 409 if (!asme) { 410 if (asthem) { 411 p = getenv("TERM"); 412 #ifdef KERBEROS4 413 k = getenv("KRBTKFILE"); 414 #endif 415 #ifdef KERBEROS5 416 ccname = getenv("KRB5CCNAME"); 417 #endif 418 if ((cleanenv = calloc(20, sizeof(char*))) == NULL) 419 errx(1, "calloc"); 420 cleanenv[0] = NULL; 421 environ = cleanenv; 422 #ifdef LOGIN_CAP 423 /* set the su'd user's environment & umask */ 424 setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH|LOGIN_SETUMASK|LOGIN_SETENV); 425 #else 426 (void)setenv("PATH", _PATH_DEFPATH, 1); 427 #endif 428 if (p) 429 (void)setenv("TERM", p, 1); 430 #ifdef KERBEROS4 431 if (k) 432 (void)setenv("KRBTKFILE", k, 1); 433 #endif 434 #ifdef KERBEROS5 435 if (ccname) 436 (void)setenv("KRB5CCNAME", ccname, 1); 437 #endif 438 if (chdir(pwd->pw_dir) < 0) 439 errx(1, "no directory"); 440 } 441 if (asthem || pwd->pw_uid) 442 (void)setenv("USER", pwd->pw_name, 1); 443 (void)setenv("HOME", pwd->pw_dir, 1); 444 (void)setenv("SHELL", shell, 1); 445 } 446 if (iscsh == YES) { 447 if (fastlogin) 448 *np-- = "-f"; 449 if (asme) 450 *np-- = "-m"; 451 } 452 453 /* csh strips the first character... */ 454 *np = asthem ? "-su" : iscsh == YES ? "_su" : "su"; 455 456 if (ruid != 0) 457 syslog(LOG_NOTICE|LOG_AUTH, "%s to %s%s", 458 username, user, ontty()); 459 460 #ifdef LOGIN_CAP 461 login_close(lc); 462 #endif 463 464 execv(shell, np); 465 err(1, "%s", shell); 466 } 467 468 static void 469 usage() 470 { 471 (void)fprintf(stderr, "usage: su [-] [-%s] %s[login [args]]\n", 472 KERBEROS_ARG("K") COMMON_ARG("flm"), 473 #ifdef LOGIN_CAP 474 "[-c class] " 475 #else 476 "" 477 #endif 478 ); 479 exit(1); 480 } 481 482 int 483 chshell(sh) 484 char *sh; 485 { 486 int r = 0; 487 char *cp; 488 489 setusershell(); 490 while (!r && (cp = getusershell()) != NULL) 491 r = strcmp(cp, sh) == 0; 492 endusershell(); 493 return r; 494 } 495 496 char * 497 ontty() 498 { 499 char *p; 500 static char buf[MAXPATHLEN + 4]; 501 502 buf[0] = 0; 503 p = ttyname(STDERR_FILENO); 504 if (p) 505 snprintf(buf, sizeof(buf), " on %s", p); 506 return (buf); 507 } 508 509 #ifdef KERBEROS5 510 const char superuser[] = "root"; 511 512 /* Authenticate using Kerberos 5. 513 * context -- An initialized krb5_context. 514 * current_user -- The current username. 515 * target_user -- The target account name. 516 * su_principal -- The target krb5_principal. 517 * pass -- The user's password. 518 * Note that a valid keytab in the default location with a host entry 519 * must be available. 520 * Returns 0 if authentication was successful, or a com_err error code if 521 * it was not. 522 */ 523 static long 524 kerberos5(krb5_context context, const char *current_user, 525 const char *target_user, krb5_principal su_principal, 526 const char *pass) 527 { 528 krb5_creds creds; 529 krb5_get_init_creds_opt gic_opt; 530 krb5_verify_init_creds_opt vic_opt; 531 long rv; 532 533 krb5_get_init_creds_opt_init(&gic_opt); 534 krb5_verify_init_creds_opt_init(&vic_opt); 535 rv = krb5_get_init_creds_password(context, &creds, su_principal, 536 pass, NULL, NULL, 0, NULL, &gic_opt); 537 if (rv != 0) { 538 syslog(LOG_NOTICE|LOG_AUTH, "BAD Kerberos5 SU: %s to %s%s: %s", 539 current_user, target_user, ontty(), 540 krb5_get_err_text(context, rv)); 541 return (rv); 542 } 543 krb5_verify_init_creds_opt_set_ap_req_nofail(&vic_opt, 1); 544 rv = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, 545 &vic_opt); 546 krb5_free_cred_contents(context, &creds); 547 if (rv != 0) { 548 syslog(LOG_NOTICE|LOG_AUTH, "BAD Kerberos5 SU: %s to %s%s: %s", 549 current_user, target_user, ontty(), 550 krb5_get_err_text(context, rv)); 551 return (rv); 552 } 553 return (0); 554 } 555 556 /* Determine the target principal given the current user and the target user. 557 * context -- An initialized krb5_context. 558 * target_user -- The target username. 559 * current_user -- The current username. 560 * su_principal_name -- (out) The target principal name. 561 * su_principal -- (out) The target krb5_principal. 562 * 563 * When target_user is `root', the su_principal will be a `root 564 * instance', e.g. `luser/root@REA.LM'. Otherwise, the su_principal 565 * will simply be the current user's default principal name. Note that 566 * in any case, if KRB5CCNAME is set and a credentials cache exists, the 567 * principal name found there will be the `starting point', rather than 568 * the current_user parameter. 569 * 570 * Returns 0 for success, or a com_err error code on failure. 571 */ 572 static long 573 get_su_principal(krb5_context context, const char *target_user, 574 const char *current_user, char **su_principal_name, 575 krb5_principal *su_principal) 576 { 577 krb5_principal default_principal; 578 krb5_ccache ccache; 579 char *principal_name, *ccname, *p; 580 long rv; 581 uid_t euid, ruid; 582 583 *su_principal = NULL; 584 default_principal = NULL; 585 /* Lower privs while messing about with the credentials 586 * cache. 587 */ 588 ruid = getuid(); 589 euid = geteuid(); 590 rv = seteuid(getuid()); 591 if (rv != 0) 592 return (errno); 593 p = getenv("KRB5CCNAME"); 594 if (p != NULL) 595 ccname = strdup(p); 596 else 597 (void)asprintf(&ccname, "%s%lu", KRB5_DEFAULT_CCROOT, 598 (unsigned long)ruid); 599 if (ccname == NULL) 600 return (errno); 601 rv = krb5_cc_resolve(context, ccname, &ccache); 602 free(ccname); 603 if (rv == 0) { 604 rv = krb5_cc_get_principal(context, ccache, 605 &default_principal); 606 krb5_cc_close(context, ccache); 607 if (rv != 0) 608 default_principal = NULL; /* just to be safe */ 609 } 610 rv = seteuid(euid); 611 if (rv != 0) 612 return (errno); 613 if (default_principal == NULL) { 614 rv = krb5_make_principal(context, &default_principal, NULL, 615 current_user, NULL); 616 if (rv != 0) { 617 warnx("Could not determine default principal name."); 618 return (rv); 619 } 620 } 621 /* Now that we have some principal, if the target account is 622 * `root', then transform it into a `root' instance, e.g. 623 * `user@REA.LM' -> `user/root@REA.LM'. 624 */ 625 rv = krb5_unparse_name(context, default_principal, &principal_name); 626 krb5_free_principal(context, default_principal); 627 if (rv != 0) { 628 warnx("krb5_unparse_name: %s", krb5_get_err_text(context, rv)); 629 return (rv); 630 } 631 if (strcmp(target_user, superuser) == 0) { 632 p = strrchr(principal_name, '@'); 633 if (p == NULL) { 634 warnx("malformed principal name `%s'", principal_name); 635 free(principal_name); 636 return (rv); 637 } 638 *p++ = '\0'; 639 (void)asprintf(su_principal_name, "%s/%s@%s", principal_name, 640 superuser, p); 641 free(principal_name); 642 } else 643 *su_principal_name = principal_name; 644 if (*su_principal_name == NULL) 645 return errno; 646 rv = krb5_parse_name(context, *su_principal_name, &default_principal); 647 if (rv != 0) { 648 warnx("krb5_parse_name `%s': %s", *su_principal_name, 649 krb5_get_err_text(context, rv)); 650 free(*su_principal_name); 651 return (rv); 652 } 653 *su_principal = default_principal; 654 return 0; 655 } 656 657 #endif 658 659 #ifdef KERBEROS4 660 int 661 kerberos4(username, user, uid, pword) 662 char *username, *user; 663 int uid; 664 char *pword; 665 { 666 KTEXT_ST ticket; 667 AUTH_DAT authdata; 668 int kerno; 669 u_long faddr; 670 char lrealm[REALM_SZ], krbtkfile[MAXPATHLEN]; 671 char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN]; 672 char *krb_get_phost(); 673 struct hostent *hp; 674 675 if (krb_get_lrealm(lrealm, 1) != KSUCCESS) 676 return (1); 677 (void)sprintf(krbtkfile, "%s_%s_%lu", TKT_ROOT, user, 678 (unsigned long)getuid()); 679 680 (void)setenv("KRBTKFILE", krbtkfile, 1); 681 (void)krb_set_tkt_string(krbtkfile); 682 /* 683 * Set real as well as effective ID to 0 for the moment, 684 * to make the kerberos library do the right thing. 685 */ 686 if (setuid(0) < 0) { 687 warn("setuid"); 688 return (1); 689 } 690 691 /* 692 * Little trick here -- if we are su'ing to root, 693 * we need to get a ticket for "xxx.root", where xxx represents 694 * the name of the person su'ing. Otherwise (non-root case), 695 * we need to get a ticket for "yyy.", where yyy represents 696 * the name of the person being su'd to, and the instance is null 697 * 698 * We should have a way to set the ticket lifetime, 699 * with a system default for root. 700 */ 701 kerno = krb_get_pw_in_tkt((uid == 0 ? username : user), 702 (uid == 0 ? "root" : ""), lrealm, 703 "krbtgt", lrealm, DEFAULT_TKT_LIFE, pword); 704 705 if (kerno != KSUCCESS) { 706 if (kerno == KDC_PR_UNKNOWN) { 707 warnx("kerberos4: principal unknown: %s.%s@%s", 708 (uid == 0 ? username : user), 709 (uid == 0 ? "root" : ""), lrealm); 710 return (1); 711 } 712 warnx("kerberos4: unable to su: %s", krb_err_txt[kerno]); 713 syslog(LOG_NOTICE|LOG_AUTH, 714 "BAD Kerberos4 SU: %s to %s%s: %s", 715 username, user, ontty(), krb_err_txt[kerno]); 716 return (1); 717 } 718 719 if (chown(krbtkfile, uid, -1) < 0) { 720 warn("chown"); 721 (void)unlink(krbtkfile); 722 return (1); 723 } 724 725 (void)setpriority(PRIO_PROCESS, 0, -2); 726 727 if (gethostname(hostname, sizeof(hostname)) == -1) { 728 warn("gethostname"); 729 dest_tkt(); 730 return (1); 731 } 732 733 (void)strncpy(savehost, krb_get_phost(hostname), sizeof(savehost)); 734 savehost[sizeof(savehost) - 1] = '\0'; 735 736 kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33); 737 738 if (kerno == KDC_PR_UNKNOWN) { 739 warnx("Warning: TGT not verified."); 740 syslog(LOG_NOTICE|LOG_AUTH, 741 "%s to %s%s, TGT not verified (%s); %s.%s not registered?", 742 username, user, ontty(), krb_err_txt[kerno], 743 "rcmd", savehost); 744 } else if (kerno != KSUCCESS) { 745 warnx("Unable to use TGT: %s", krb_err_txt[kerno]); 746 syslog(LOG_NOTICE|LOG_AUTH, "failed su: %s to %s%s: %s", 747 username, user, ontty(), krb_err_txt[kerno]); 748 dest_tkt(); 749 return (1); 750 } else { 751 if (!(hp = gethostbyname(hostname))) { 752 warnx("can't get addr of %s", hostname); 753 dest_tkt(); 754 return (1); 755 } 756 memmove((char *)&faddr, (char *)hp->h_addr, sizeof(faddr)); 757 758 if ((kerno = krb_rd_req(&ticket, "rcmd", savehost, faddr, 759 &authdata, "")) != KSUCCESS) { 760 warnx("kerberos4: unable to verify rcmd ticket: %s\n", 761 krb_err_txt[kerno]); 762 syslog(LOG_NOTICE|LOG_AUTH, 763 "failed su: %s to %s%s: %s", username, 764 user, ontty(), krb_err_txt[kerno]); 765 dest_tkt(); 766 return (1); 767 } 768 } 769 return (0); 770 } 771 772 int 773 koktologin(name, toname) 774 char *name, *toname; 775 { 776 AUTH_DAT *kdata; 777 AUTH_DAT kdata_st; 778 char realm[REALM_SZ]; 779 780 if (krb_get_lrealm(realm, 1) != KSUCCESS) 781 return (1); 782 kdata = &kdata_st; 783 memset((char *)kdata, 0, sizeof(*kdata)); 784 (void)strncpy(kdata->pname, name, sizeof kdata->pname - 1); 785 (void)strncpy(kdata->pinst, 786 ((strcmp(toname, "root") == 0) ? "root" : ""), sizeof kdata->pinst - 1); 787 (void)strncpy(kdata->prealm, realm, sizeof kdata->prealm - 1); 788 return (kuserok(kdata, toname)); 789 } 790 #endif 791