bsd-cray.c revision 98937
198937Sdes/*
298937Sdes * $Id: bsd-cray.c,v 1.6 2002/05/15 16:39:51 mouring Exp $
398937Sdes *
498937Sdes * bsd-cray.c
598937Sdes *
698937Sdes * Copyright (c) 2002, Cray Inc.  (Wendy Palm <wendyp@cray.com>)
798937Sdes * Significant portions provided by
898937Sdes *          Wayne Schroeder, SDSC <schroeder@sdsc.edu>
998937Sdes *          William Jones, UTexas <jones@tacc.utexas.edu>
1098937Sdes *
1198937Sdes * Redistribution and use in source and binary forms, with or without
1298937Sdes * modification, are permitted provided that the following conditions
1398937Sdes * are met:
1498937Sdes * 1. Redistributions of source code must retain the above copyright
1598937Sdes *    notice, this list of conditions and the following disclaimer.
1698937Sdes * 2. Redistributions in binary form must reproduce the above copyright
1798937Sdes *    notice, this list of conditions and the following disclaimer in the
1898937Sdes *    documentation and/or other materials provided with the distribution.
1998937Sdes *
2098937Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2198937Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2298937Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2398937Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2498937Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2598937Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2698937Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2798937Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2898937Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2998937Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3098937Sdes *
3198937Sdes * Created: Apr 22 16.34:00 2002 wp
3298937Sdes *
3398937Sdes * This file contains functions required for proper execution
3498937Sdes * on UNICOS systems.
3598937Sdes *
3698937Sdes */
3798937Sdes
3898937Sdes#ifdef _CRAY
3998937Sdes#include <udb.h>
4098937Sdes#include <tmpdir.h>
4198937Sdes#include <unistd.h>
4298937Sdes#include <sys/category.h>
4398937Sdes#include <utmp.h>
4498937Sdes#include <sys/jtab.h>
4598937Sdes#include <signal.h>
4698937Sdes#include <sys/priv.h>
4798937Sdes#include <sys/secparm.h>
4898937Sdes#include <sys/usrv.h>
4998937Sdes#include <sys/sysv.h>
5098937Sdes#include <sys/sectab.h>
5198937Sdes#include <sys/stat.h>
5298937Sdes#include <stdlib.h>
5398937Sdes#include <pwd.h>
5498937Sdes#include <fcntl.h>
5598937Sdes#include <errno.h>
5698937Sdes
5798937Sdes#include "bsd-cray.h"
5898937Sdes
5998937Sdeschar cray_tmpdir[TPATHSIZ+1];		    /* job TMPDIR path */
6098937Sdes
6198937Sdes/*
6298937Sdes * Functions.
6398937Sdes */
6498937Sdesvoid cray_retain_utmp(struct utmp *, int);
6598937Sdesvoid cray_delete_tmpdir(char *, int, uid_t);
6698937Sdesvoid cray_init_job(struct passwd *);
6798937Sdesvoid cray_set_tmpdir(struct utmp *);
6898937Sdes
6998937Sdes
7098937Sdes/*
7198937Sdes * Orignal written by:
7298937Sdes *     Wayne Schroeder
7398937Sdes *     San Diego Supercomputer Center
7498937Sdes *     schroeder@sdsc.edu
7598937Sdes*/
7698937Sdesvoid
7798937Sdescray_setup(uid_t uid, char *username)
7898937Sdes{
7998937Sdes	struct udb *p;
8098937Sdes	extern char *setlimits();
8198937Sdes	int i, j;
8298937Sdes	int accts[MAXVIDS];
8398937Sdes	int naccts;
8498937Sdes	int err;
8598937Sdes	char *sr;
8698937Sdes	int pid;
8798937Sdes	struct jtab jbuf;
8898937Sdes	int jid;
8998937Sdes
9098937Sdes	if ((jid = getjtab(&jbuf)) < 0)
9198937Sdes		fatal("getjtab: no jid");
9298937Sdes
9398937Sdes	err = setudb();	   /* open and rewind the Cray User DataBase */
9498937Sdes	if (err != 0)
9598937Sdes		fatal("UDB open failure");
9698937Sdes	naccts = 0;
9798937Sdes	p = getudbnam(username);
9898937Sdes	if (p == NULL)
9998937Sdes		fatal("No UDB entry for %.100s", username);
10098937Sdes	if (uid != p->ue_uid)
10198937Sdes		fatal("UDB entry %.100s uid(%d) does not match uid %d",
10298937Sdes		    username, (int) p->ue_uid, (int) uid);
10398937Sdes	for (j = 0; p->ue_acids[j] != -1 && j < MAXVIDS; j++) {
10498937Sdes		accts[naccts] = p->ue_acids[j];
10598937Sdes		naccts++;
10698937Sdes	}
10798937Sdes	endudb();	 /* close the udb */
10898937Sdes
10998937Sdes	if (naccts != 0) {
11098937Sdes		/* Perhaps someday we'll prompt users who have multiple accounts
11198937Sdes		   to let them pick one (like CRI's login does), but for now just set
11298937Sdes		   the account to the first entry. */
11398937Sdes		if (acctid(0, accts[0]) < 0)
11498937Sdes			fatal("System call acctid failed, accts[0]=%d", accts[0]);
11598937Sdes	}
11698937Sdes
11798937Sdes	/* Now set limits, including CPU time for the (interactive) job and process,
11898937Sdes	   and set up permissions (for chown etc), etc.	 This is via an internal CRI
11998937Sdes	   routine, setlimits, used by CRI's login. */
12098937Sdes
12198937Sdes	pid = getpid();
12298937Sdes	sr = setlimits(username, C_PROC, pid, UDBRC_INTER);
12398937Sdes	if (sr != NULL)
12498937Sdes		fatal("%.200s", sr);
12598937Sdes
12698937Sdes	sr = setlimits(username, C_JOB, jid, UDBRC_INTER);
12798937Sdes	if (sr != NULL)
12898937Sdes		fatal("%.200s", sr);
12998937Sdes
13098937Sdes}
13198937Sdes
13298937Sdes/*
13398937Sdes * The rc.* and /etc/sdaemon methods of starting a program on unicos/unicosmk
13498937Sdes * can have pal privileges that sshd can inherit which
13598937Sdes * could allow a user to su to root with out a password.
13698937Sdes * This subroutine clears all privileges.
13798937Sdes */
13898937Sdesvoid
13998937Sdesdrop_cray_privs()
14098937Sdes{
14198937Sdes#if defined(_SC_CRAY_PRIV_SU)
14298937Sdes	priv_proc_t*		  privstate;
14398937Sdes	int			  result;
14498937Sdes	extern	    int		  priv_set_proc();
14598937Sdes	extern	    priv_proc_t*  priv_init_proc();
14698937Sdes	struct	    usrv	  usrv;
14798937Sdes
14898937Sdes	/*
14998937Sdes	 * If ether of theses two flags are not set
15098937Sdes	 * then don't allow this version of ssh to run.
15198937Sdes	 */
15298937Sdes	if (!sysconf(_SC_CRAY_PRIV_SU))
15398937Sdes		fatal("Not PRIV_SU system.");
15498937Sdes	if (!sysconf(_SC_CRAY_POSIX_PRIV))
15598937Sdes		fatal("Not POSIX_PRIV.");
15698937Sdes
15798937Sdes	debug("Dropping privileges.");
15898937Sdes
15998937Sdes	memset(&usrv, 0, sizeof(usrv));
16098937Sdes	if (setusrv(&usrv) < 0)
16198937Sdes		fatal("%s(%d): setusrv(): %s", __FILE__, __LINE__,
16298937Sdes		    strerror(errno));
16398937Sdes
16498937Sdes	if ((privstate = priv_init_proc()) != NULL) {
16598937Sdes		result = priv_set_proc(privstate);
16698937Sdes		if (result != 0 )
16798937Sdes			fatal("%s(%d): priv_set_proc(): %s",
16898937Sdes			    __FILE__, __LINE__, strerror(errno));
16998937Sdes		priv_free_proc(privstate);
17098937Sdes	}
17198937Sdes	debug ("Privileges should be cleared...");
17298937Sdes#else
17398937Sdes	/* XXX: do this differently */
17498937Sdes#	error Cray systems must be run with _SC_CRAY_PRIV_SU on!
17598937Sdes#endif
17698937Sdes}
17798937Sdes
17898937Sdes
17998937Sdes/*
18098937Sdes *  Retain utmp/wtmp information - used by cray accounting.
18198937Sdes */
18298937Sdesvoid
18398937Sdescray_retain_utmp(struct utmp *ut, int pid)
18498937Sdes{
18598937Sdes	int fd;
18698937Sdes	struct utmp utmp;
18798937Sdes
18898937Sdes	if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) {
18998937Sdes		while (read(fd, (char *)&utmp, sizeof(utmp)) == sizeof(utmp)) {
19098937Sdes			if (pid == utmp.ut_pid) {
19198937Sdes				ut->ut_jid = utmp.ut_jid;
19298937Sdes				/* XXX: MIN_SIZEOF here? can this go in loginrec? */
19398937Sdes				strncpy(ut->ut_tpath, utmp.ut_tpath, sizeof(utmp.ut_tpath));
19498937Sdes				strncpy(ut->ut_host, utmp.ut_host, sizeof(utmp.ut_host));
19598937Sdes				strncpy(ut->ut_name, utmp.ut_name, sizeof(utmp.ut_name));
19698937Sdes				break;
19798937Sdes			}
19898937Sdes		}
19998937Sdes		close(fd);
20098937Sdes	}
20198937Sdes	/* XXX: error message? */
20298937Sdes}
20398937Sdes
20498937Sdes/*
20598937Sdes * tmpdir support.
20698937Sdes */
20798937Sdes
20898937Sdes/*
20998937Sdes * find and delete jobs tmpdir.
21098937Sdes */
21198937Sdesvoid
21298937Sdescray_delete_tmpdir(char *login, int jid, uid_t uid)
21398937Sdes{
21498937Sdes	int child;
21598937Sdes	static char jtmp[TPATHSIZ];
21698937Sdes	struct stat statbuf;
21798937Sdes	int c;
21898937Sdes	int wstat;
21998937Sdes
22098937Sdes	for (c = 'a'; c <= 'z'; c++) {
22198937Sdes		snprintf(jtmp, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c);
22298937Sdes		if (stat(jtmp, &statbuf) == 0 && statbuf.st_uid == uid)
22398937Sdes			break;
22498937Sdes	}
22598937Sdes
22698937Sdes	if (c > 'z')
22798937Sdes		return;
22898937Sdes
22998937Sdes	if ((child = fork()) == 0) {
23098937Sdes		execl(CLEANTMPCMD, CLEANTMPCMD, login, jtmp, (char *)NULL);
23198937Sdes		fatal("cray_delete_tmpdir: execl of CLEANTMPCMD failed");
23298937Sdes	}
23398937Sdes
23498937Sdes	while (waitpid(child, &wstat, 0) == -1 && errno == EINTR)
23598937Sdes		;
23698937Sdes}
23798937Sdes
23898937Sdes/*
23998937Sdes * Remove tmpdir on job termination.
24098937Sdes */
24198937Sdesvoid
24298937Sdescray_job_termination_handler(int sig)
24398937Sdes{
24498937Sdes	int jid;
24598937Sdes	char *login = NULL;
24698937Sdes	struct jtab jtab;
24798937Sdes
24898937Sdes	debug("Received SIG JOB.");
24998937Sdes
25098937Sdes	if ((jid = waitjob(&jtab)) == -1 ||
25198937Sdes	    (login = uid2nam(jtab.j_uid)) == NULL)
25298937Sdes		return;
25398937Sdes
25498937Sdes	cray_delete_tmpdir(login, jid, jtab.j_uid);
25598937Sdes}
25698937Sdes
25798937Sdes/*
25898937Sdes * Set job id and create tmpdir directory.
25998937Sdes */
26098937Sdesvoid
26198937Sdescray_init_job(struct passwd *pw)
26298937Sdes{
26398937Sdes	int jid;
26498937Sdes	int c;
26598937Sdes
26698937Sdes	jid = setjob(pw->pw_uid, WJSIGNAL);
26798937Sdes	if (jid < 0)
26898937Sdes		fatal("System call setjob failure");
26998937Sdes
27098937Sdes	for (c = 'a'; c <= 'z'; c++) {
27198937Sdes		snprintf(cray_tmpdir, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c);
27298937Sdes		if (mkdir(cray_tmpdir, JTMPMODE) != 0)
27398937Sdes			continue;
27498937Sdes		if (chown(cray_tmpdir,	pw->pw_uid, pw->pw_gid) != 0) {
27598937Sdes			rmdir(cray_tmpdir);
27698937Sdes			continue;
27798937Sdes		}
27898937Sdes		break;
27998937Sdes	}
28098937Sdes
28198937Sdes	if (c > 'z')
28298937Sdes		cray_tmpdir[0] = '\0';
28398937Sdes}
28498937Sdes
28598937Sdesvoid
28698937Sdescray_set_tmpdir(struct utmp *ut)
28798937Sdes{
28898937Sdes	int jid;
28998937Sdes	struct jtab jbuf;
29098937Sdes
29198937Sdes	if ((jid = getjtab(&jbuf)) < 0)
29298937Sdes		return;
29398937Sdes
29498937Sdes	/*
29598937Sdes	 * Set jid and tmpdir in utmp record.
29698937Sdes	 */
29798937Sdes	ut->ut_jid = jid;
29898937Sdes	strncpy(ut->ut_tpath, cray_tmpdir, TPATHSIZ);
29998937Sdes}
30098937Sdes#endif
301