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