[comp.sources.x] v03i100: patches/additions to provide extra security in X, Part01/01

argv@island.uu.net (Dan Heller) (05/04/89)

Submitted-by: Mike Rowan <mtr@mentor.cc.purdue.edu>
Posting-number: Volume 3, Issue 100
Archive-name: secure/part01

[ I didn't apply the patch or test this stuff, sorry.  I did read the README
  and it seems like a great idea.  --argv ]

#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	AUTHOR
#	Patch.authorize
#	README
#	XAuthorize.c
# This archive created: Wed May  3 11:17:57 1989
# By:	Michael Rowan (Unix Groupie)
cat << \SHAR_EOF > AUTHOR
Mike Rowan, mtr@mentor.cc.purdue.edu
Unix Group Systems Programmer
Purdue University Computing Center
SHAR_EOF
cat << \SHAR_EOF > Patch.authorize
*** /tmp/,RCSt1024408	Tue May  2 21:46:41 1989
--- ./lib/X/XConnDis.c	Thu Jan 12 15:59:19 1989
***************
*** 406,411 ****
--- 406,414 ----
  
          int bytes=0;
  
+ #ifdef PUCC
+ 	_XAuthorizeClient(&auth_proto, &auth_string);
+ #endif
          auth_length = strlen(auth_proto);
          auth_strlen = strlen(auth_string);
          client->nbytesAuthProto = auth_length;
*** /tmp/,RCSt1024461	Tue May  2 21:47:56 1989
--- server/os/4.2bsd/connection.c	Thu Jan 12 22:07:20 1989
***************
*** 122,127 ****
--- 122,131 ----
  
  extern ConnectionInput inputBuffers[];
  
+ #ifdef PUCC
+ extern char	*ServerReadAuthString;
+ #endif /* PUCC */
+ 
  int swappedClients[MAXSOCKS];
  
  extern int AutoResetServer();
***************
*** 505,510 ****
--- 509,532 ----
  #undef STR
  	}
      auth_string[slen] = '\0';
+ 
+ #ifdef PUCC
+ 	/*
+ 	 * Check the password sent in auth_string 
+  	 */
+ 	if(ServerReadAuthString != NULL && strcmp(auth_string, ServerReadAuthString)) {
+ #define STR "Invalid Authorization Code (PUCC localism)"
+ 		static int iNumberOfRejects = 0;
+ 
+ 		*reason = (char *) xalloc(sizeof(STR));
+ 		strcpy(*reason, STR);
+ 		if(iNumberOfRejects++ >= 3) {
+ 			fprintf(stderr,"XAUTH: 3 denied requests.\n");
+ 		}
+ 		return 0;
+ #undef STR
+ 	}
+ #endif /* PUCC */
  
      /* At this point, if the client is authorized to change the access control
       * list, we should getpeername() information, and add the client to
*** /tmp/,RCSt1024466	Tue May  2 21:48:19 1989
--- server/os/4.2bsd/osinit.c	Thu Jan 19 20:43:34 1989
***************
*** 44,49 ****
--- 44,54 ----
  int	havergb = 0;
  extern char *display;
  
+ #ifdef PUCC
+ char	*ServerReadAuthString;
+ int	ReadUsersAuthFile();
+ #endif /* PUCC */
+ 
  OsInit()
  {
      static Bool been_here = FALSE;
***************
*** 88,91 ****
--- 93,178 ----
  	    havergb = 1;
          else
  	    ErrorF( "Couldn't open RGB_DB '%s'\n", rgbPath );
+ 
+ #ifdef PUCC
+ 	if(!ReadUsersAuthFile(&ServerReadAuthString)) {
+ 		ServerReadAuthString = NULL;
+ 	}
+ #endif /* PUCC */
  }
+ 
+ #ifdef PUCC
+ 
+ #include <sys/stat.h>
+ #include <sys/file.h>
+ 
+ #define XENVAUTHFILE	"/.xauth"
+ #define OTHERANDGROUP	07777700
+ #define	MAXPASSWORDLEN	99
+ 
+ 
+ int
+ ReadUsersAuthFile(ppchAuthString)
+ 	char	**ppchAuthString;
+ {
+ 	char	*pchAuthFilename = NULL,
+ 		*pchUsersHome = NULL,
+ 		sbBuffer[MAXPASSWORDLEN + 1];
+ 	extern  char 	*getenv();
+ 	static  char	*gethomedir();
+ 	FILE	*pFauthfile;
+ 	struct stat StatBuf;
+ 	int	iFlaglocal = 0;
+ 
+ 	if(NULL == (pchAuthFilename = getenv(XENVAUTHFILE))) {
+ 		if(NULL == (pchUsersHome = getenv("HOME"))) {
+ 			pchUsersHome = gethomedir();
+ 		}
+ 		pchAuthFilename = (char *)xalloc(strlen(pchUsersHome) + 
+ 					sizeof(XENVAUTHFILE) + 1);
+ 		strcpy(pchAuthFilename, pchUsersHome);
+ 		strcat(pchAuthFilename, XENVAUTHFILE);
+ 	} else {
+ 		iFlaglocal++;
+ 	}
+ 	if(-1 != access(pchAuthFilename, R_OK)) {
+ 		if((FILE *) NULL == (pFauthfile = fopen(pchAuthFilename,"r"))) {
+ 			return 0;
+ 		}
+ 		if(!fstat(fileno(pFauthfile), &StatBuf)) {
+ 			if(((StatBuf.st_mode & S_IFMT) == S_IFLNK) || 
+ 					StatBuf.st_mode != 
+ 					(StatBuf.st_mode & OTHERANDGROUP)) {
+ 				fprintf(stderr,"XAuth: XAUTH file (%s) is publicly readable or is a symbolic link - authorizations turned off\n",pchAuthFilename);
+ 				(void) fclose(pFauthfile);
+ 				return 0;
+ 			}
+ 		} else {
+ 			(void) fclose(pFauthfile);
+ 			return 0;
+ 		}
+ 		if(NULL == fgets(sbBuffer, MAXPASSWORDLEN, pFauthfile)) {
+ 			return 0;
+ 		}
+ 		(void) fclose(pFauthfile);
+ 		*ppchAuthString = (char *) xalloc(strlen(sbBuffer) + 1);
+ 		strcpy(*ppchAuthString, sbBuffer);
+ 		return 1;
+ 	}
+ 	if(iFlaglocal) {
+ 		fprintf(stderr,"XAuth: XAUTH file (%s) is not readable or does not exist!\n");
+ 	}	
+ 	return 0;
+ }
+ 
+ #include <pwd.h>
+ 
+ static char	*
+ gethomedir()
+ {
+ 	struct passwd	*pwsLocal;
+ 
+ 	pwsLocal = getpwuid(getuid());
+ 	return pwsLocal->pw_dir;
+ }
+ #endif /* PUCC */
*** /tmp/,RCSt1024491	Tue May  2 21:49:16 1989
--- ./lib/X/Imakefile	Sun Apr  9 09:57:42 1989
***************
*** 20,25 ****
--- 20,26 ----
  	XAllCells.o \
  	XAllPlanes.o \
  	XAllowEv.o \
+ 	XAuthorize.o \
  	XAutoRep.o \
  	XBackgnd.o \
  	XBdrWidth.o \
SHAR_EOF
cat << \SHAR_EOF > README

This is a simple addition to the X server and library to allow
user level authentication.   The hooks were already there, I just
added some pretty simplistic code - this all depends on the
unix file system for security.  

You need to add a "-DPUCC" to your imake config files.  The
XAuthorize.c file goes into ./lib/X, and there is a patch file
rooted at $TOP.  

When the consortium comes out with its version of finer-than-host
authentication - you can just undef PUCC from the imake files, and
you are done.

------
Here is how it works:

checks either the file $HOME/.xauth or the filename contained in the
$XAUTH enviorment variable.  If this file does not have its other and
group modes set to 0 - the file is ignored and the user warned.

The server reads in the first line of this file and keeps it as a passwd.

Each client reads in the first line of this file and sends it in the 
connecction request packet.  If it matches the servers version, the connection
is ok'ed (as long as the other requirments like xhost stuff are meet)

The user needs to create a .xauth file (~/.xauth actually) and put a 
password or some phrase in it via his favorite editor.  It can be up
to 99 characters or so.  chmod it to something like 600 or 400.  then
rdist it to all the hosts that he will run x applications on.  All done!

He can then run xhost + allowing all hosts to talk to him since we are running
a user based password thingie.

If you make any improvments or fixes, send them to me please!

Mike Rowan
mtr@mentor.cc.purdue.edu
SHAR_EOF
cat << \SHAR_EOF > XAuthorize.c
#ifdef PUCC
 
#include <stdio.h>
#include <X11/Xos.h>
#include "Xlibint.h"
#include <sys/stat.h>

#define XENVAUTHFILE	"XAUTH"
#define XAUTHFILE	"/.xauth"
#define OTHERANDGROUP	07777700
#define	MAXPASSWORDLEN	99

int 
_XAuthorizeClient (ppchAuthProto, ppchAuthString)
    char 	**ppchAuthProto;
    char 	**ppchAuthString;
{
	char	*pchAuthFilename = NULL,
		*pchUsersHome = NULL,
		sbBuffer[MAXPASSWORDLEN + 1];
	extern  char 	*getenv();
	static  char	*gethomedir();
	FILE	*pFauthfile;
	struct stat	StatBuf;
	int	iFlaglocal = 0;

	if(NULL == (pchAuthFilename = getenv(XENVAUTHFILE))) {
		iFlaglocal++;
#ifndef SYSV
		if(NULL == (pchUsersHome = getenv("HOME"))) {
#else /* SYSV */
		if(NULL == (pchUsersHome = getenv("HOME"))) {
#endif /* SYSV */
			pchUsersHome = gethomedir();
		}
		pchAuthFilename = (char *)Xmalloc(strlen(pchUsersHome) + 
					sizeof(XAUTHFILE) + 1);
		strcpy(pchAuthFilename, pchUsersHome);
		strcat(pchAuthFilename, XAUTHFILE);
	}
	if(-1 != access(pchAuthFilename, R_OK)) {
		if((FILE *) NULL == (pFauthfile = fopen(pchAuthFilename,"r"))) {
			perror("fopen");
			return 0;
		}
		if(!fstat(fileno(pFauthfile), &StatBuf)) {
			if(((StatBuf.st_mode & S_IFMT) == S_IFLNK) || 
					StatBuf.st_mode != 
					(StatBuf.st_mode & OTHERANDGROUP)) {
				fprintf(stderr,"XAuth: XAUTH file (%s) is publicly readable or is a symbolic link - passwd ignored\n",pchAuthFilename);
				(void) fclose(pFauthfile);
				return 0;
			}
		} else {
			perror("fstat:");
			(void) fclose(pFauthfile);
			return 0;
		}
		if(NULL == fgets(sbBuffer, MAXPASSWORDLEN, pFauthfile)) {
			return 0;
		}
		(void) fclose(pFauthfile);
		*ppchAuthString = (char *) Xmalloc(strlen(sbBuffer) + 1);
		strcpy(*ppchAuthString, sbBuffer);
		return 1;
	}
	/* now only bitch if he set his XAUTH enviroment var */
	if(!iFlaglocal) {
		fprintf(stderr,"XAuth: XAUTH file (%s) is not readable or does not exist!\n",pchAuthFilename);
	}
	return 0;
}

#include <pwd.h> 

static char	*
gethomedir()
{
	struct passwd	*pwsLocal;

	pwsLocal = getpwuid(getuid());
	return pwsLocal->pw_dir;
}

#endif PUCC
SHAR_EOF
#	End of shell archive
exit 0