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