1 /* 2 * $Id: bsd-cray.c,v 1.8 2002/09/26 00:38:51 tim Exp $ 3 * 4 * bsd-cray.c 5 * 6 * Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>) 7 * Significant portions provided by 8 * Wayne Schroeder, SDSC <schroeder@sdsc.edu> 9 * William Jones, UTexas <jones@tacc.utexas.edu> 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Created: Apr 22 16.34:00 2002 wp 32 * 33 * This file contains functions required for proper execution 34 * on UNICOS systems. 35 * 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 #include "includes.h" 41 42 #ifdef _UNICOS 43 44 #include <udb.h> 45 #include <tmpdir.h> 46 #include <unistd.h> 47 #include <sys/category.h> 48 #include <utmp.h> 49 #include <sys/jtab.h> 50 #include <signal.h> 51 #include <sys/priv.h> 52 #include <sys/secparm.h> 53 #include <sys/tfm.h> 54 #include <sys/usrv.h> 55 #include <sys/sysv.h> 56 #include <sys/sectab.h> 57 #include <sys/secstat.h> 58 #include <sys/stat.h> 59 #include <sys/session.h> 60 #include <stdlib.h> 61 #include <pwd.h> 62 #include <fcntl.h> 63 #include <errno.h> 64 #include <ia.h> 65 #include <urm.h> 66 #include "ssh.h" 67 #include "log.h" 68 #include "servconf.h" 69 #include "bsd-cray.h" 70 71 #define MAXACID 80 72 73 extern ServerOptions options; 74 75 char cray_tmpdir[TPATHSIZ+1]; /* job TMPDIR path */ 76 77 struct sysv sysv; /* system security structure */ 78 struct usrv usrv; /* user security structure */ 79 80 /* 81 * Functions. 82 */ 83 void cray_retain_utmp(struct utmp *, int); 84 void cray_delete_tmpdir(char *, int, uid_t); 85 void cray_init_job(struct passwd *); 86 void cray_set_tmpdir(struct utmp *); 87 void cray_login_failure(char *, int); 88 int cray_setup(uid_t, char *, const char *); 89 int cray_access_denied(char *); 90 91 void 92 cray_login_failure(char *username, int errcode) 93 { 94 struct udb *ueptr; /* UDB pointer for username */ 95 ia_failure_t fsent; /* ia_failure structure */ 96 ia_failure_ret_t fret; /* ia_failure return stuff */ 97 struct jtab jtab; /* job table structure */ 98 int jid = 0; /* job id */ 99 100 if ((jid = getjtab(&jtab)) < 0) { 101 debug("cray_login_failure(): getjtab error"); 102 } 103 getsysudb(); 104 if ((ueptr = getudbnam(username)) == UDB_NULL) { 105 debug("cray_login_failure(): getudbname() returned NULL"); 106 } 107 endudb(); 108 fsent.revision = 0; 109 fsent.uname = username; 110 fsent.host = (char *)get_canonical_hostname(options.verify_reverse_mapping); 111 fsent.ttyn = "sshd"; 112 fsent.caller = IA_SSHD; 113 fsent.flags = IA_INTERACTIVE; 114 fsent.ueptr = ueptr; 115 fsent.jid = jid; 116 fsent.errcode = errcode; 117 fsent.pwdp = NULL; 118 fsent.exitcode = 0; /* dont exit in ia_failure() */ 119 120 fret.revision = 0; 121 fret.normal = 0; 122 123 /* 124 * Call ia_failure because of an login failure. 125 */ 126 ia_failure(&fsent,&fret); 127 } 128 129 /* 130 * Cray access denied 131 */ 132 int 133 cray_access_denied(char *username) 134 { 135 struct udb *ueptr; /* UDB pointer for username */ 136 int errcode; /* IA errorcode */ 137 138 errcode = 0; 139 getsysudb(); 140 if ((ueptr = getudbnam(username)) == UDB_NULL) { 141 debug("cray_login_failure(): getudbname() returned NULL"); 142 } 143 endudb(); 144 if (ueptr && ueptr->ue_disabled) 145 errcode = IA_DISABLED; 146 if (errcode) 147 cray_login_failure(username, errcode); 148 return (errcode); 149 } 150 151 int 152 cray_setup (uid_t uid, char *username, const char *command) 153 { 154 extern struct udb *getudb(); 155 extern char *setlimits(); 156 157 int err; /* error return */ 158 time_t system_time; /* current system clock */ 159 time_t expiration_time; /* password expiration time */ 160 int maxattempts; /* maximum no. of failed login attempts */ 161 int SecureSys; /* unicos security flag */ 162 int minslevel = 0; /* system minimum security level */ 163 int i, j; 164 int valid_acct = -1; /* flag for reading valid acct */ 165 char acct_name[MAXACID] = { "" }; /* used to read acct name */ 166 struct jtab jtab; /* Job table struct */ 167 struct udb ue; /* udb entry for logging-in user */ 168 struct udb *up; /* pointer to UDB entry */ 169 struct secstat secinfo; /* file security attributes */ 170 struct servprov init_info; /* used for sesscntl() call */ 171 int jid; /* job ID */ 172 int pid; /* process ID */ 173 char *sr; /* status return from setlimits() */ 174 char *ttyn = NULL; /* ttyname or command name*/ 175 char hostname[MAXHOSTNAMELEN]; 176 passwd_t pwdacm, 177 pwddialup, 178 pwdudb, 179 pwdwal, 180 pwddce; /* passwd stuff for ia_user */ 181 ia_user_ret_t uret; /* stuff returned from ia_user */ 182 ia_user_t usent; /* ia_user main structure */ 183 int ia_rcode; /* ia_user return code */ 184 ia_failure_t fsent; /* ia_failure structure */ 185 ia_failure_ret_t fret; /* ia_failure return stuff */ 186 ia_success_t ssent; /* ia_success structure */ 187 ia_success_ret_t sret; /* ia_success return stuff */ 188 int ia_mlsrcode; /* ia_mlsuser return code */ 189 int secstatrc; /* [f]secstat return code */ 190 191 if (SecureSys = (int)sysconf(_SC_CRAY_SECURE_SYS)) { 192 getsysv(&sysv, sizeof(struct sysv)); 193 minslevel = sysv.sy_minlvl; 194 if (getusrv(&usrv) < 0) { 195 debug("getusrv() failed, errno = %d",errno); 196 exit(1); 197 } 198 } 199 hostname[0] = '\0'; 200 strncpy(hostname, 201 (char *)get_canonical_hostname(options.verify_reverse_mapping), 202 MAXHOSTNAMELEN); 203 /* 204 * Fetch user's UDB entry. 205 */ 206 getsysudb(); 207 if ((up = getudbnam(username)) == UDB_NULL) { 208 debug("cannot fetch user's UDB entry"); 209 exit(1); 210 } 211 212 /* 213 * Prevent any possible fudging so perform a data 214 * safety check and compare the supplied uid against 215 * the udb's uid. 216 */ 217 if (up->ue_uid != uid) { 218 debug("IA uid missmatch"); 219 exit(1); 220 } 221 endudb(); 222 223 if ((jid = getjtab (&jtab)) < 0) { 224 debug("getjtab"); 225 return -1; 226 } 227 pid = getpid(); 228 ttyn = ttyname(0); 229 if (SecureSys) { 230 if (ttyn) { 231 secstatrc = secstat(ttyn, &secinfo); 232 } else { 233 secstatrc = fsecstat(1, &secinfo); 234 } 235 if (secstatrc == 0) { 236 debug("[f]secstat() successful"); 237 } else { 238 debug("[f]secstat() error, rc = %d", secstatrc); 239 exit(1); 240 } 241 } 242 if ((ttyn == NULL) && ((char *)command != NULL)) 243 ttyn = (char *)command; 244 /* 245 * Initialize all structures to call ia_user 246 */ 247 usent.revision = 0; 248 usent.uname = username; 249 usent.host = hostname; 250 usent.ttyn = ttyn; 251 usent.caller = IA_SSHD; 252 usent.pswdlist = &pwdacm; 253 usent.ueptr = &ue; 254 usent.flags = IA_INTERACTIVE | IA_FFLAG; 255 pwdacm.atype = IA_SECURID; 256 pwdacm.pwdp = NULL; 257 pwdacm.next = &pwdudb; 258 259 pwdudb.atype = IA_UDB; 260 pwdudb.pwdp = NULL; 261 pwdudb.next = &pwddce; 262 263 pwddce.atype = IA_DCE; 264 pwddce.pwdp = NULL; 265 pwddce.next = &pwddialup; 266 267 pwddialup.atype = IA_DIALUP; 268 pwddialup.pwdp = NULL; 269 /* pwddialup.next = &pwdwal; */ 270 pwddialup.next = NULL; 271 272 pwdwal.atype = IA_WAL; 273 pwdwal.pwdp = NULL; 274 pwdwal.next = NULL; 275 276 uret.revision = 0; 277 uret.pswd = NULL; 278 uret.normal = 0; 279 280 ia_rcode = ia_user(&usent, &uret); 281 282 switch (ia_rcode) { 283 /* 284 * These are acceptable return codes from ia_user() 285 */ 286 case IA_UDBWEEK: /* Password Expires in 1 week */ 287 expiration_time = ue.ue_pwage.time + ue.ue_pwage.maxage; 288 printf ("WARNING - your current password will expire %s\n", 289 ctime((const time_t *)&expiration_time)); 290 break; 291 case IA_UDBEXPIRED: 292 if (ttyname(0) != NULL) { 293 /* Force a password change */ 294 printf("Your password has expired; Choose a new one.\n"); 295 execl("/bin/passwd", "passwd", username, 0); 296 exit(9); 297 } 298 299 break; 300 case IA_NORMAL: /* Normal Return Code */ 301 break; 302 case IA_BACKDOOR: 303 strcpy(ue.ue_name, "root"); 304 strcpy(ue.ue_passwd, ""); 305 strcpy(ue.ue_dir, "/"); 306 strcpy(ue.ue_shell, "/bin/sh"); 307 strcpy(ue.ue_age, ""); 308 strcpy(ue.ue_comment, ""); 309 strcpy(ue.ue_loghost, ""); 310 strcpy(ue.ue_logline, ""); 311 ue.ue_uid=-1; 312 ue.ue_nice[UDBRC_INTER]=0; 313 for (i=0;i<MAXVIDS;i++) 314 ue.ue_gids[i]=0; 315 ue.ue_logfails=0; 316 ue.ue_minlvl=minslevel; 317 ue.ue_maxlvl=minslevel; 318 ue.ue_deflvl=minslevel; 319 ue.ue_defcomps=0; 320 ue.ue_comparts=0; 321 ue.ue_permits=0; 322 ue.ue_trap=0; 323 ue.ue_disabled=0; 324 ue.ue_logtime=0; 325 break; 326 case IA_CONSOLE: /* Superuser not from Console */ 327 case IA_TRUSTED: /* Trusted user */ 328 if (options.permit_root_login > PERMIT_NO) 329 break; /* Accept root login */ 330 default: 331 /* 332 * These are failed return codes from ia_user() 333 */ 334 switch (ia_rcode) 335 { 336 case IA_BADAUTH: 337 printf ("Bad authorization, access denied.\n"); 338 break; 339 case IA_DIALUPERR: 340 break; 341 case IA_DISABLED: 342 printf ("Your login has been disabled. Contact the system "); 343 printf ("administrator for assistance.\n"); 344 break; 345 case IA_GETSYSV: 346 printf ("getsysv() failed - errno = %d\n", errno); 347 break; 348 case IA_LOCALHOST: 349 break; 350 case IA_MAXLOGS: 351 printf ("Maximum number of failed login attempts exceeded.\n"); 352 printf ("Access denied.\n"); 353 break; 354 case IA_NOPASS: 355 break; 356 case IA_PUBLIC: 357 break; 358 case IA_SECURIDERR: 359 break; 360 case IA_CONSOLE: 361 break; 362 case IA_TRUSTED: 363 break; 364 case IA_UDBERR: 365 break; 366 case IA_UDBPWDNULL: 367 /* 368 * NULL password not allowed on MLS systems 369 */ 370 if (SecureSys) { 371 printf("NULL Password not allowed on MLS systems.\n"); 372 } 373 break; 374 case IA_UNKNOWN: 375 break; 376 case IA_UNKNOWNYP: 377 break; 378 case IA_WALERR: 379 break; 380 default: 381 /* nothing special */ 382 ; 383 } /* 2. switch (ia_rcode) */ 384 /* 385 * Authentication failed. 386 */ 387 printf("sshd: Login incorrect, (0%o)\n", 388 ia_rcode-IA_ERRORCODE); 389 390 /* 391 * Initialize structure for ia_failure 392 * which will exit. 393 */ 394 fsent.revision = 0; 395 fsent.uname = username; 396 fsent.host = hostname; 397 fsent.ttyn = ttyn; 398 fsent.caller = IA_SSHD; 399 fsent.flags = IA_INTERACTIVE; 400 fsent.ueptr = &ue; 401 fsent.jid = jid; 402 fsent.errcode = ia_rcode; 403 fsent.pwdp = uret.pswd; 404 fsent.exitcode = 1; 405 406 fret.revision = 0; 407 fret.normal = 0; 408 409 /* 410 * Call ia_failure because of an IA failure. 411 * There is no return because ia_failure exits. 412 */ 413 414 ia_failure(&fsent,&fret); 415 416 exit(1); 417 } /* 1. switch (ia_rcode) */ 418 ia_mlsrcode = IA_NORMAL; 419 if (SecureSys) { 420 debug("calling ia_mlsuser()"); 421 ia_mlsrcode = ia_mlsuser (&ue, &secinfo, &usrv, NULL, 0); 422 } 423 if (ia_mlsrcode != IA_NORMAL) { 424 printf("sshd: Login incorrect, (0%o)\n", 425 ia_mlsrcode-IA_ERRORCODE); 426 /* 427 * Initialize structure for ia_failure 428 * which will exit. 429 */ 430 fsent.revision = 0; 431 fsent.uname = username; 432 fsent.host = hostname; 433 fsent.ttyn = ttyn; 434 fsent.caller = IA_SSHD; 435 fsent.flags = IA_INTERACTIVE; 436 fsent.ueptr = &ue; 437 fsent.jid = jid; 438 fsent.errcode = ia_mlsrcode; 439 fsent.pwdp = uret.pswd; 440 fsent.exitcode = 1; 441 fret.revision = 0; 442 fret.normal = 0; 443 444 /* 445 * Call ia_failure because of an IA failure. 446 * There is no return because ia_failure exits. 447 */ 448 ia_failure(&fsent,&fret); 449 exit(1); 450 } 451 452 /* Provide login status information */ 453 if (options.print_lastlog && ue.ue_logtime != 0) { 454 printf("Last successful login was : %.*s ", 455 19, (char *)ctime(&ue.ue_logtime)); 456 457 if (*ue.ue_loghost != '\0') 458 printf("from %.*s\n", sizeof(ue.ue_loghost), ue.ue_loghost); 459 460 else printf("on %.*s\n", sizeof(ue.ue_logline), ue.ue_logline); 461 462 if ( SecureSys && (ue.ue_logfails != 0)) 463 printf(" followed by %d failed attempts\n", ue.ue_logfails); 464 } 465 466 467 /* 468 * Call ia_success to process successful I/A. 469 */ 470 ssent.revision = 0; 471 ssent.uname = username; 472 ssent.host = hostname; 473 ssent.ttyn = ttyn; 474 ssent.caller = IA_SSHD; 475 ssent.flags = IA_INTERACTIVE; 476 ssent.ueptr = &ue; 477 ssent.jid = jid; 478 ssent.errcode = ia_rcode; 479 ssent.us = NULL; 480 ssent.time = 1; /* Set ue_logtime */ 481 482 sret.revision = 0; 483 sret.normal = 0; 484 485 ia_success(&ssent,&sret); 486 487 /* 488 * Query for account, iff > 1 valid acid & askacid permbit 489 */ 490 if (((ue.ue_permbits & PERMBITS_ACCTID) || 491 (ue.ue_acids[0] >= 0) && (ue.ue_acids[1] >= 0)) && 492 ue.ue_permbits & PERMBITS_ASKACID) { 493 if (ttyname(0) != NULL) { 494 debug("cray_setup: ttyname true case, %.100s", ttyname); 495 while (valid_acct == -1) { 496 printf("Account (? for available accounts)" 497 " [%s]: ", acid2nam(ue.ue_acids[0])); 498 gets(acct_name); 499 switch (acct_name[0]) { 500 case EOF: 501 exit(0); 502 break; 503 case '\0': 504 valid_acct = ue.ue_acids[0]; 505 strcpy(acct_name, acid2nam(valid_acct)); 506 break; 507 case '?': 508 /* Print the list 3 wide */ 509 for (i = 0, j = 0; i < MAXVIDS; i++) { 510 if (ue.ue_acids[i] == -1) { 511 printf("\n"); 512 break; 513 } 514 if (++j == 4) { 515 j = 1; 516 printf("\n"); 517 } 518 printf(" %s", 519 acid2nam(ue.ue_acids[i])); 520 } 521 if (ue.ue_permbits & PERMBITS_ACCTID) 522 printf("\"acctid\" permbit also allows" 523 " you to select any valid " 524 "account name.\n"); 525 printf("\n"); 526 break; 527 default: 528 if ((valid_acct = nam2acid(acct_name)) == -1) printf("Account id not found for" 529 " account name \"%s\"\n\n", 530 acct_name); 531 break; 532 } 533 /* 534 * If an account was given, search the user's 535 * acids array to verify they can use this account. 536 */ 537 if ((valid_acct != -1) && 538 !(ue.ue_permbits & PERMBITS_ACCTID)) { 539 for (i = 0; i < MAXVIDS; i++) { 540 if (ue.ue_acids[i] == -1) 541 break; 542 if (valid_acct == ue.ue_acids[i]) 543 break; 544 } 545 if (i == MAXVIDS || 546 ue.ue_acids[i] == -1) { 547 fprintf(stderr, "Cannot set" 548 " account name to " 549 "\"%s\", permission " 550 "denied\n\n", acct_name); 551 valid_acct = -1; 552 } 553 } 554 } 555 } else { 556 /* 557 * The client isn't connected to a terminal and can't 558 * respond to an acid prompt. Use default acid. 559 */ 560 debug("cray_setup: ttyname false case, %.100s", ttyname); 561 valid_acct = ue.ue_acids[0]; 562 } 563 } else { 564 /* 565 * The user doesn't have the askacid permbit set or 566 * only has one valid account to use. 567 */ 568 valid_acct = ue.ue_acids[0]; 569 } 570 if (acctid(0, valid_acct) < 0) { 571 printf ("Bad account id: %d\n", valid_acct); 572 exit(1); 573 } 574 575 /* set up shares and quotas */ 576 /* Now set shares, quotas, limits, including CPU time for the (interactive) 577 * job and process, and set up permissions (for chown etc), etc. 578 */ 579 if (setshares(ue.ue_uid, valid_acct, printf, 0, 0)) { 580 printf("Unable to give %d shares to <%s>(%d/%d)\n", ue.ue_shares, ue.ue_name, ue.ue_uid, valid_acct); 581 exit(1); 582 } 583 584 sr = setlimits(username, C_PROC, pid, UDBRC_INTER); 585 if (sr != NULL) { 586 debug("%.200s", sr); 587 exit(1); 588 } 589 sr = setlimits(username, C_JOB, jid, UDBRC_INTER); 590 if (sr != NULL) { 591 debug("%.200s", sr); 592 exit(1); 593 } 594 /* 595 * Place the service provider information into 596 * the session table (Unicos) or job table (Unicos/mk). 597 * There exist double defines for the job/session table in 598 * unicos/mk (jtab.h) so no need for a compile time switch. 599 */ 600 bzero((char *)&init_info, sizeof(struct servprov)); 601 init_info.s_sessinit.si_id = URM_SPT_LOGIN; 602 init_info.s_sessinit.si_pid = getpid(); 603 init_info.s_sessinit.si_sid = jid; 604 init_info.s_routing.seqno = 0; 605 init_info.s_routing.iadrs = 0; 606 sesscntl(0, S_SETSERVPO, (int)&init_info); 607 608 /* 609 * Set user and controlling tty security attributes. 610 */ 611 if (SecureSys) { 612 if (setusrv(&usrv) == -1) { 613 debug("setusrv() failed, errno = %d",errno); 614 exit(1); 615 } 616 } 617 618 return(0); 619 } 620 621 /* 622 * The rc.* and /etc/sdaemon methods of starting a program on unicos/unicosmk 623 * can have pal privileges that sshd can inherit which 624 * could allow a user to su to root with out a password. 625 * This subroutine clears all privileges. 626 */ 627 void 628 drop_cray_privs() 629 { 630 #if defined(_SC_CRAY_PRIV_SU) 631 priv_proc_t* privstate; 632 int result; 633 extern int priv_set_proc(); 634 extern priv_proc_t* priv_init_proc(); 635 636 /* 637 * If ether of theses two flags are not set 638 * then don't allow this version of ssh to run. 639 */ 640 if (!sysconf(_SC_CRAY_PRIV_SU)) 641 fatal("Not PRIV_SU system."); 642 if (!sysconf(_SC_CRAY_POSIX_PRIV)) 643 fatal("Not POSIX_PRIV."); 644 645 debug("Setting MLS labels.");; 646 647 if (sysconf(_SC_CRAY_SECURE_MAC)) { 648 usrv.sv_minlvl = SYSLOW; 649 usrv.sv_actlvl = SYSHIGH; 650 usrv.sv_maxlvl = SYSHIGH; 651 } else { 652 usrv.sv_minlvl = sysv.sy_minlvl; 653 usrv.sv_actlvl = sysv.sy_minlvl; 654 usrv.sv_maxlvl = sysv.sy_maxlvl; 655 } 656 usrv.sv_actcmp = 0; 657 usrv.sv_valcmp = sysv.sy_valcmp; 658 659 usrv.sv_intcat = TFM_SYSTEM; 660 usrv.sv_valcat |= (TFM_SYSTEM | TFM_SYSFILE); 661 662 if (setusrv(&usrv) < 0) 663 fatal("%s(%d): setusrv(): %s", __FILE__, __LINE__, 664 strerror(errno)); 665 666 if ((privstate = priv_init_proc()) != NULL) { 667 result = priv_set_proc(privstate); 668 if (result != 0 ) 669 fatal("%s(%d): priv_set_proc(): %s", 670 __FILE__, __LINE__, strerror(errno)); 671 priv_free_proc(privstate); 672 } 673 debug ("Privileges should be cleared..."); 674 #else 675 /* XXX: do this differently */ 676 # error Cray systems must be run with _SC_CRAY_PRIV_SU on! 677 #endif 678 } 679 680 681 /* 682 * Retain utmp/wtmp information - used by cray accounting. 683 */ 684 void 685 cray_retain_utmp(struct utmp *ut, int pid) 686 { 687 int fd; 688 struct utmp utmp; 689 690 if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) { 691 while (read(fd, (char *)&utmp, sizeof(utmp)) == sizeof(utmp)) { 692 if (pid == utmp.ut_pid) { 693 ut->ut_jid = utmp.ut_jid; 694 strncpy(ut->ut_tpath, utmp.ut_tpath, sizeof(utmp.ut_tpath)); 695 strncpy(ut->ut_host, utmp.ut_host, sizeof(utmp.ut_host)); 696 strncpy(ut->ut_name, utmp.ut_name, sizeof(utmp.ut_name)); 697 break; 698 } 699 } 700 close(fd); 701 } 702 else 703 fatal("Unable to open utmp file"); 704 } 705 706 /* 707 * tmpdir support. 708 */ 709 710 /* 711 * find and delete jobs tmpdir. 712 */ 713 void 714 cray_delete_tmpdir(char *login, int jid, uid_t uid) 715 { 716 int child; 717 static char jtmp[TPATHSIZ]; 718 struct stat statbuf; 719 int c; 720 int wstat; 721 722 for (c = 'a'; c <= 'z'; c++) { 723 snprintf(jtmp, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c); 724 if (stat(jtmp, &statbuf) == 0 && statbuf.st_uid == uid) 725 break; 726 } 727 728 if (c > 'z') 729 return; 730 731 if ((child = fork()) == 0) { 732 execl(CLEANTMPCMD, CLEANTMPCMD, login, jtmp, (char *)NULL); 733 fatal("cray_delete_tmpdir: execl of CLEANTMPCMD failed"); 734 } 735 736 while (waitpid(child, &wstat, 0) == -1 && errno == EINTR) 737 ; 738 } 739 740 /* 741 * Remove tmpdir on job termination. 742 */ 743 void 744 cray_job_termination_handler(int sig) 745 { 746 int jid; 747 char *login = NULL; 748 struct jtab jtab; 749 750 debug("received signal %d",sig); 751 752 if ((jid = waitjob(&jtab)) == -1 || 753 (login = uid2nam(jtab.j_uid)) == NULL) 754 return; 755 756 cray_delete_tmpdir(login, jid, jtab.j_uid); 757 } 758 759 /* 760 * Set job id and create tmpdir directory. 761 */ 762 void 763 cray_init_job(struct passwd *pw) 764 { 765 int jid; 766 int c; 767 768 jid = setjob(pw->pw_uid, WJSIGNAL); 769 if (jid < 0) 770 fatal("System call setjob failure"); 771 772 for (c = 'a'; c <= 'z'; c++) { 773 snprintf(cray_tmpdir, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c); 774 if (mkdir(cray_tmpdir, JTMPMODE) != 0) 775 continue; 776 if (chown(cray_tmpdir, pw->pw_uid, pw->pw_gid) != 0) { 777 rmdir(cray_tmpdir); 778 continue; 779 } 780 break; 781 } 782 783 if (c > 'z') 784 cray_tmpdir[0] = '\0'; 785 } 786 787 void 788 cray_set_tmpdir(struct utmp *ut) 789 { 790 int jid; 791 struct jtab jbuf; 792 793 if ((jid = getjtab(&jbuf)) < 0) 794 return; 795 796 /* 797 * Set jid and tmpdir in utmp record. 798 */ 799 ut->ut_jid = jid; 800 strncpy(ut->ut_tpath, cray_tmpdir, TPATHSIZ); 801 } 802 #endif 803