1
0
Files
irix-657m-src/eoe/cmd/newlabel/newlabel.c
2022-09-29 17:59:04 +03:00

411 lines
9.6 KiB
C

/*
* COPYRIGHT NOTICE
* Copyright 1990, Silicon Graphics, Inc. All Rights Reserved.
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*
*/
/*
* newlabel - create a new process at the requested label
*
* E don't close and reopen stderr
* F don't close and reopen stderr,in,out
* I don't close and reopen stdin
* O don't close and reopen stdout
* a all subdir labels for a moldy dir
* e reopen stderr as next arg
* f reopen stderr,in,out as next arg
* h all non-equal subdir labels for a moldy dir
* i reopen stdin as next arg
* o reopen stdout as next arg
* m change label to moldy
* t change label to TCSEC
*
*/
#ident "$Revision: 1.13 $"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <dirent.h>
#include <stdio.h>
#include <pwd.h>
#include <ia.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <strings.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/mac.h>
#include <sys/mac_label.h>
#include <clearance.h>
static mac_label read_mold = {MSEN_MLD_HIGH_LABEL, MINT_EQUAL_LABEL, };
static char namebuf_in[MAXPATHLEN] = "/dev/null"; /* new stdin */
static char namebuf_out[MAXPATHLEN] = "/dev/null"; /* new stdout */
static char namebuf_err[MAXPATHLEN] = "/dev/null"; /* new stderr */
int
main(int argc, char *argv[], char **envp)
{
int c; /* For use by getopt(3) */
int label_gotten = 0; /* set if label is computed */
mac_t plabel; /* original process label value */
mac_t lp; /* The desired label value */
struct clearance *clp; /* user clearance */
struct passwd *pwd; /* passwd entry */
int do_equals = 0; /* differentiate -a and -h */
char *ttyis; /* return from ttyname(3) */
char *molddir = NULL; /* target dir for -a and -h */
char *shell = NULL; /* user's preferred shell */
char *program = argv[0]; /* program name saved */
char *toopen_in = namebuf_in; /* what to reopen stdin as */
char *toopen_out = namebuf_out; /* what to reopen stdout as */
char *toopen_err = namebuf_err; /* what to reopen stderr as */
char *lsc_msg = "%s: Label specification conflict\n";
char *EIO_msg = "newlabel -%c requires super-user privilege\n";
char *lbl_msg = "newlabel: cannot get process label\n";
/*
* The desired label may be a deviant of the current
* label. Fetch it.
*/
plabel = mac_get_proc();
lp = mac_get_proc();
if (plabel == (mac_t) NULL || lp == (mac_t) NULL) {
printf(lbl_msg);
return(1);
}
/*
* Parse command line arguments
*/
while ((c = getopt(argc, argv, "EFIOa:e:f:h:i:mo:t")) != -1) {
switch (c) {
case 'E':
if (getuid() != 0) {
printf(EIO_msg, c);
exit(1);
}
toopen_err = NULL;
break;
case 'F':
if (getuid() != 0) {
printf(EIO_msg, c);
exit(1);
}
toopen_err = NULL;
toopen_in = NULL;
toopen_out = NULL;
break;
case 'I':
if (getuid() != 0) {
printf(EIO_msg, c);
exit(1);
}
toopen_in = NULL;
break;
case 'O':
if (getuid() != 0) {
printf(EIO_msg, c);
exit(1);
}
toopen_out = NULL;
break;
case 'a':
do_equals = 1;
/* NO BREAK */
case 'h':
if (getuid() != 0) {
printf(EIO_msg, c);
exit(1);
}
molddir = optarg;
break;
case 'e':
toopen_err = optarg;
break;
case 'f':
toopen_err = optarg;
toopen_in = optarg;
toopen_out = optarg;
break;
case 'i':
toopen_in = optarg;
break;
case 'm':
if (label_gotten++) {
printf(lsc_msg, c);
exit(1);
}
switch(lp->ml_msen_type) {
case MSEN_TCSEC_LABEL:
lp->ml_msen_type = MSEN_MLD_LABEL;
break;
case MSEN_LOW_LABEL:
lp->ml_msen_type = MSEN_MLD_LOW_LABEL;
break;
case MSEN_HIGH_LABEL:
lp->ml_msen_type = MSEN_MLD_HIGH_LABEL;
break;
}
break;
case 'o':
toopen_out = optarg;
break;
case 't':
if (label_gotten++) {
printf(lsc_msg, c);
exit(1);
}
switch (lp->ml_msen_type) {
case MSEN_MLD_LABEL:
lp->ml_msen_type = MSEN_TCSEC_LABEL;
break;
case MSEN_MLD_LOW_LABEL:
lp->ml_msen_type = MSEN_LOW_LABEL;
break;
case MSEN_MLD_HIGH_LABEL:
lp->ml_msen_type = MSEN_HIGH_LABEL;
break;
}
break;
case '?':
default:
printf("newlabel: unknown option\n");
exit(1);
}
}
if (molddir != NULL) {
DIR *dp; /* dir pointer */
struct dirent *dep; /* dir entry */
struct stat statbuf; /* for stat */
char path[MAXPATHLEN]; /* to form full path */
/*
* Make this process able to read the specified
* moldy directory. Note that the superuser check
* has already been made.
*/
if (mac_set_proc(&read_mold) == -1) {
printf("%s: Label change failure.\n", program);
exit(1);
}
if ((dp = opendir(molddir)) == NULL) {
printf("%s: Directory open failure.\n", program);
exit(1);
}
while ((dep = readdir(dp)) != NULL) {
if (strcmp(dep->d_name, ".") == 0)
continue;
if (strcmp(dep->d_name, "..") == 0)
continue;
sprintf(path, "%s/%s", molddir, dep->d_name);
if (stat(path, &statbuf) < 0) {
/* Very Strange! */
continue;
}
if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
continue;
mac_free(lp);
if ((lp = mac_get_file(path)) == NULL) {
/* Very Strange! */
continue;
}
if (do_equals == 0 &&
(lp->ml_msen_type == MSEN_EQUAL_LABEL ||
lp->ml_mint_type == MINT_EQUAL_LABEL))
continue;
if (fork() == 0) {
closedir(dp);
label_gotten = 1;
break;
}
(void) wait(&c);
}
/*
* Exit gracefully from the parent.
*/
if (!label_gotten) {
exit(0);
}
}
if ((pwd = getpwuid(getuid())) == NULL) {
printf("%s: User data is unobtainable\n", program);
exit(1);
}
if ((clp = sgi_getclearancebyname(pwd->pw_name)) == NULL) {
printf("%s: Clearance is unobtainable\n", program);
exit(1);
}
if (!label_gotten) {
int state;
/*
* Get the label from the command line.
*/
if (optind >= argc) {
printf("%s: No label specified\n", program);
exit(1);
}
if ((state = mac_cleared(clp,argv[optind]))!=MAC_CLEARED) {
char *message;
/*
* A few custom messages.
*/
switch (state) {
case MAC_LBL_TOO_LOW:
message =
"requested label is below your allowed range";
break;
case MAC_LBL_TOO_HIGH:
message =
"requested label is above your allowed range";
break;
case MAC_INCOMPARABLE:
message =
"requested label is outside your allowed range";
break;
default:
message = mac_clearance_error(state);
}
printf("%s: %s: %s.\n", program, argv[optind],
message);
exit(1);
}
lp = mac_from_text(argv[optind]);
optind++;
}
/*
* Verify that the new label dominates the old.
* superuser is exempt.
*/
if (getuid() != 0 && mac_dominate(lp, plabel) == 0) {
printf("%s: requested label doesn't dominate current label.\n",
program);
exit(1);
}
/*
* Find name of currently open std in, out, & err
*/
if (ttyis = ttyname(0))
strcpy(namebuf_in, ttyis);
if (ttyis = ttyname(1))
strcpy(namebuf_out, ttyis);
if (ttyis = ttyname(2))
strcpy(namebuf_err, ttyis);
/*
* Reset process label.
* Do this before closing so that errors can be reported.
*/
if (mac_set_proc(lp) == -1) {
perror("newlabel: cannot change label");
exit(1);
}
/*
* Shut down all open files, except those which which must remain
* for the super-user.
*/
for (c = getdtablesize(); c >= 3; c--)
close(c);
if (toopen_err)
close(2);
if (toopen_out)
close(1);
if (toopen_in)
close(0);
/*
* Reset process attributes. Do this with communication to the
* outside world closed down.
*/
if (setuid(getuid()) < 0)
exit(1);
/*
* Attempt to reopen stdin, stdout, and stderr.
* If this fails (probably due to MAC policy) open /dev/null
* instead. If that fails accept the fact and continue in
* hopes that all will be for the best.
*/
if (toopen_in && open(toopen_in, O_RDONLY) < 0)
(void)open("/dev/null", O_RDWR);
if (toopen_out && open(toopen_out, O_RDWR|O_CREAT|O_APPEND, 0600) < 0)
(void)open("/dev/null", O_RDWR);
if (toopen_err && open(toopen_err, O_RDWR|O_CREAT|O_APPEND, 0600) < 0)
(void)open("/dev/null", O_RDWR);
/*
* Find the user's preferred shell
*/
if (pwd->pw_shell) {
shell = strrchr(pwd->pw_shell, (int)'/');
if (shell)
shell++;
else
shell = pwd->pw_shell;
}
/*
* If no program is specified invoke a shell
*/
if (argc == optind) {
if (shell)
execl(pwd->pw_shell, shell, NULL);
execl("/bin/csh", "csh", NULL);
execl("/bin/sh", "sh", NULL);
execl("/bin/echo", "/bin/echo", "newlabel: No Shell", NULL);
exit(1);
}
else {
/*
* build an argument string (code borrowed from rsh)
* then exec sh -c "command arguments"
*/
int len;
char **argp;
char *cp, *args;
len = 0;
for (argp = argv + optind; *argp; argp++)
len += strlen(*argp) + 1;
cp = args = malloc(len);
for (argp = argv + optind; *argp; argp++) {
strcpy(cp, *argp);
while (*cp)
cp++;
if (argp[1])
*cp++ = ' ';
}
if (shell)
execl(pwd->pw_shell, shell, "-c", args, NULL);
execl("/bin/sh", "sh", "-c", args, NULL);
execl("/bin/echo", "/bin/echo", "newlabel: No Shell", NULL);
exit(1);
}
return(0);
}