[comp.emacs] "turning on" root privileges in a running emacs

lakin@csli.stanford.edu (Fred Lakin) (01/12/91)

Sometimes in the middle of a session I want to read or modify a file
requiring root privs. At the moment, I have to go to a shell, become
su, and start another emacs. Is there some to momentarily enable (and
later "turn back off") su privs in an emacs started by a regular
user??

tnx, f
starnet!bass!lakin@apple.com

hollen@megatek (Dion Hollenbeck) (01/14/91)

In article <LAKIN.91Jan11160003@csli.stanford.edu> lakin@csli.stanford.edu (Fred Lakin) writes:
> Sometimes in the middle of a session I want to read or modify a file
> requiring root privs. At the moment, I have to go to a shell, become
> su, and start another emacs. Is there some to momentarily enable (and
> later "turn back off") su privs in an emacs started by a regular
> user??
> 
The answer is not merely for emacs, but for getting root privs
in general on a single command.  

1)	You do NOT want a shell script to have root priv (even
	setuid).

2)	You do want an executable to have root priv via setuid.


Here is a program which I compile into an executable named "-".
When I want to do just a single command as root, I do something
like this:

	- mkdir /foo

This program will make sure you are you, and will make sure
that it is it before executing the command you pass to it as
root

-------------------------- cut here  ----------------------
/* 
 * doasroot.c
 *
 *	Program to run commands as root
 *
 *		After it has been compiled, rename to - and chown to
 *		root and setuid as root
 *
 *	$Log:	doasroot.c,v $
 * Revision 1.4  90/09/01  10:40:42  hollen
 * fixed envp
 * 
 * Revision 1.3  90/08/30  07:28:18  hollen
 * fixed invocation with absolute path to pass correct args
 * 
 * Revision 1.2  90/08/28  06:51:26  hollen
 * added code to make sure regular file and executable
 * made exit messages for valid user a little more helpful
 * 
 * Revision 1.1  90/08/27  14:33:51  hollen
 * Initial revision
 * 
 *
 */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

extern	char *getenv() ;
extern	char *findfileinpath() ;

#define MASTER 740
#define PROGRAM "-"

#define BAILOUT \
{fprintf(stderr, "Unauthorized use not allowed\n") ; exit(1);}

#define FALSE	0
#define	TRUE	!FALSE



main( argc, argv, envp )
int	argc ;
char	*argv[] ;
char	*envp[] ;
{
	char *execpath;
	struct stat stbuf;
	
	if ( argc < 2 )
		BAILOUT ;

	/* only valid if on path an invoked exactly as program name 	*/
	if ( strcmp(argv[0], PROGRAM) != NULL  )
		BAILOUT ;

	/* only valid if invoked by proper user				*/
	 if (MASTER != getuid())
	 {
		(void)printf( "Bad UID %d\n", getuid()) ;
		BAILOUT ;
	 }

	/* program is valid, user is valid, find exececutable */

	/* if there is a '/' in name see if the file exists and use it */
	if ( strrchr(argv[1], '/') != 0 )
	{
		if ( stat(argv[1], &stbuf) != 0 )
		{
			BAILOUT ;
		}
		else
		{
			if (execve( argv[1], &argv[1], envp ) == -1 )
			{
				perror("exec failed") ;
				exit(1) ;
			}
		}
		/*NOTREACHED*/
		exit(0) ;
	}
	
	/* no '/' in name, search user path for it */
	if ( (execpath = findfileinpath(argv[1])) == NULL )
	{
		(void)fprintf(stderr, "Command not found\n") ;
		exit(1) ;
	}

	/* replace program name pointer with full path name pointer */
	argv[1] = execpath ;
	if (execve( execpath, &argv[1], envp ) == -1 )
	{
		perror("exec failed") ;
		exit(1) ;
	}
	/*NOTREACHED*/
}


char *
findfileinpath( fname )
char *fname ;
{
	char	*foundpath ;
	char 	*mypath ;
	char	*ptr ;
	struct 	stat stbuf;
	int	found = FALSE;

	if ( (mypath = getenv( "PATH" )) == NULL)
		return(NULL);
	if ( (foundpath = (char *)malloc(strlen(mypath))) == NULL )
		return(NULL) ;

	ptr = strtok(mypath, ":");
	while(!found && ptr)
	{
		strcpy(foundpath, ptr) ;
		strcat(foundpath, "/") ;
		strcat(foundpath, fname) ;
		if ( stat(foundpath, &stbuf) == 0 )
		{
			if( (stbuf.st_mode & (S_IFREG|S_IEXEC)) ==
			   (S_IFREG|S_IEXEC))
				found = TRUE ;
			else
				(void)fprintf(stderr, 
				  "Found match %s, but not executable\n",
					      foundpath);
		}
		ptr = strtok((char *)NULL, ":");
	}

	/*  foundpath is purposely not freed  here */
	if ( !found )
		return(NULL) ;
	else
		return(foundpath) ;
}



---------------------- cut here  -------------------------

Hope this does the trick.

dion
--
-----
	Dion Hollenbeck             (619) 455-5590 x2814
	Megatek Corporation, 9645 Scranton Road, San Diego, CA  92121
        uunet!megatek!hollen       or  hollen@megatek.uucp

marc@arnor.uucp (01/16/91)

This could be implemented if someone wanted to by the following
scheme.  You start emacs with root privs.  It sets its effective
uid/gid back to the user's.  Then, commands which wanted temporary
root privs could switch the process to root, do there thing, and
switch back.

My solution is to run a seperate emacs, normally iconified, started
from root.  The window is white on a red background, so I won't
accidently use it.
--


Marc Auslander       <marc@ibm.com>