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