Files
Arquivotheca.AIX-4.1.3/bos/usr/bin/usrck/usrshell.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

152 lines
3.4 KiB
C

static char sccsid[] = "@(#)75 1.5.1.1 src/bos/usr/bin/usrck/usrshell.c, cmdsadm, bos411, 9428A410j 3/24/93 13:55:27";
/*
* COMPONENT_NAME: CMDSADM
*
* FUNCTIONS: ck_shell
*
*
* ORIGINS: 27
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
*
* (C) COPYRIGHT International Business Machines Corp. 1989,1993
* All Rights Reserved
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#include <sys/types.h>
#include <sys/access.h>
#include <sys/priv.h>
#include <sys/audit.h>
#include <sys/signal.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <usersec.h>
#include "usrck_msg.h"
#include "usrck.h"
#define PRIV_ALL (PRIV_BEQUEATH|PRIV_EFFECTIVE|PRIV_INHERITED|PRIV_MAXIMUM)
/*
* Global data
*/
int fixit; /* indicates fixes are to be made always */
int verbose; /* indicates error messages are displayed */
/*
* NAME: ck_shell
*
* FUNCTION: Check user's login shell for execute permission.
*
* EXECUTION ENVIRONMENT:
*
* User process. This function forks.
*
* NOTES:
* This function tests a user's login shell for execute
* permission. The shell is tested using the user's credentials.
*
* RETURNS: Zero if the user's shell exists and can be executed by
* the user.
*/
int
ck_shell (char *name)
{
char *shell;
int status;
pid_t pid;
pid_t waitpid;
priv_t priv;
/*
* Get the user's login shell
*/
if (getuserattr (name, S_SHELL, (void *) &shell, 0)
|| shell == 0 || ! *shell)
shell = "/usr/bin/sh";
/*
* Fork off a child and wait. The child will set its process
* credentials to those of the user and test for execute
* permission on the login shell.
*/
signal (SIGCLD, SIG_DFL);
fflush (stderr);
if ((pid = fork ()) == 0) {
/*
* Set the credentials to be the same as those for
* the user being checked. This shouldn't fail ...
*/
privilege (PRIV_ACQUIRE);
if (setpcred (name, (char **) 0)) {
msg1 (MSGSTR (M_CREDFAIL, DEF_CREDFAIL), name);
fflush (stderr);
_exit (EPERM);
}
/*
* Must turn off ALL privileges prior to testing
* for access. Test for access then exit with the
* success or failure of the access call. PRIV_DROP
* can't be used since the inherited privilege set
* may be non-empty.
*/
memset (&priv, 0, sizeof priv);
if (setpriv (PRIV_SET|PRIV_ALL, &priv, sizeof priv)) {
perror ("usrck: setpriv");
_exit (errno);
}
if (accessx (shell, ACC_INVOKER, X_ACC))
_exit (errno);
_exit (0);
} else if (pid != -1) {
/*
* Spin waiting for the child to exit. Catch the
* process with the same process ID as the child, or
* stop when no children remain [ there really must
* be at least one ... ]
*/
while ((waitpid = wait (&status)) != pid && waitpid != -1)
;
} else {
/*
* This shouldn't really happen, but I want to at
* least mention that it did. Really shouldn't return
* an error since that would cause the account to be
* disabled when it might be valid!
*/
perror ("usrck: fork");
return 0;
}
/*
* Examine the return status and see what's up. The high
* eight bits give the exit code, the low eight bits give the
* signal number. If the entire thing is zero then it exited
* OK.
*/
if (status)
msg2 (MSGSTR (M_NOSHELL, DEF_NOSHELL), name, shell);
return status != 0;
}