From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 19-JUL-1990 23:17:40.62
To:	MRGATE::"ARISIA::EVERHART"
CC:	
Subj:	Re: Cluster Authorization

Received:  by crdgw1.ge.com (5.57/GE 1.70)
	 id AA15741; Thu, 19 Jul 90 22:07:26 EDT
Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Thu, 19 JUL 90 14:03:51 PDT
Received: by ucbvax.Berkeley.EDU (5.63/1.41)
	id AA15827; Thu, 19 Jul 90 12:47:27 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 19 Jul 90 16:10:27 GMT
From: mcsun!ukc!strath-cs!ctssuk!VERKADE@uunet.uu.net  (Herman Verkade)
Organization: CompuThoughts Software Solutions (UK) Ltd, Glasgow, Scotland, UK
Subject: Re: Cluster Authorization
Message-Id: <900719171027.00000D57@MARVIN.CTSS.CO.UK>
References: <9007111639.AA01892@ucbvax.Berkeley.EDU>, <67052D64C89F606945@grove.iup.edu>, MJSTRAW@IUP.BITNET
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

In article <9007111639.AA01892@ucbvax.Berkeley.EDU>,
  canellis%creek.decnet@HQHSD.BROOKS.AF.MIL ("CREEK::CANELLIS") writes:
>	I have just clustered three (Vaxen, Vaxes), and now find I have to
>disallow certain users from specific nodes in the cluster.  Can rightslist
>identifiers be used to get the job done?  If so, has anyone done this and
>care to share code fragments or give me some hints, tips or traps.

In article <67052D64C89F606945@grove.iup.edu>, MJSTRAW@IUP.BITNET
  (Mark J Strawcutter) writes:
>We have a rightslist identifier SA$service-name for each service.  One or
>more of them is granted to each username.
.
.
>Would be really nice if there were a DCL
>lexical to check if the user holds a given id...

I wrote a similar thing many years ago, but without a file and/or ACLs. Just a
little program that checks whether the user holds an identifier representing
access to the local system. The sources are below. Here is a DEC-style,
how-to-install :-)

1. Extract the two files below into CLUSTER_ACCESS.C and CLUACCMSG.MSG and
   compile:

        $ CC CLUSTER_ACCESS
        $ MESSAGE CLUACCMSG
        $ LINK CLUSTER_ACCESS,CLUACCMSG,SYS$INPUT/OPT
        SYS$LIBRARY:VAXCRTL/SHARE
        <CTRL/Z>
        
2. Create an identifier for each node in the cluster:

	$ MC AUTHORIZE
	UAF> ADD/IDENTIFIER ACCESS_NODEA
	UAF> ADD/IDENTIFIER ACCESS_NODEB
	UAF> ADD/IDENTIFIER ACCESS_NODEC

3. Grant one of more if the identifiers to each user, representing which node
   each user has access to:

	$ MC AUTHORIZE
	UAF> GRANT/IDENTIFIER ACCESS_NODEA PIETJE
	UAF> GRANT/IDENTIFIER ACCESS_NODEB PIETJE
	UAF> GRANT/IDENTIFIER ACCESS_NODEC JANJE

4. Put CLUSTER_ACCESS.EXE in SYS$COMMON:[SYSMGR]. Make sure it has
   World:Execute access 

5. Add the folowing commands to the start of SYLOGIN.COM:

$ ON ERROR THEN LOGOUT
$ RUN SYS$MANAGER:CLUSTER_ACCESS
$ ON ERROR THEN EXIT ! or whatever else you want to happen on errors

The program consists mainly of pre-initialised data structures plus a few
system calls. It seems to work pretty fast, even better when installed. At one
time I had the code patched into LOGINOUT.EXE to make sure it always runs, but
that was V4.3 or so. (Don't flame about patching LOGINOUT, please. I will only
laugh at those replies).

I gave out this program with a chat at DECUS in the Netherlands back in '87 and
a friend of mine in the Netherlands got it mailed last year from a collegue of
his in Atlanta :-) It still seems to be in use in some places.

There are off course many other ways of accomplishing this. The most horrible I
have ever seen, was to put a copy of DCL.EXE in each SYS$SPECIFIC protected by
an appropriate ACL.

Herman Verkade
email: VERKADE@CTSS.CO.UK
Voice: +44 41 334 8396
--------------------------------------------------------------------------------
/*
 *	Module:		CLUSTER_ACCESS.C
 *	Description:	Check access rights for a user on a cluster
 *
 *	Author:		Herman Verkade
 *
 *	Revision history:
 *
 *	000	16-jan-1987	- Created
 */

#include stdio
#include ssdef
#include syidef
#include jpidef
#include descrip

typedef unsigned int LONGWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef void *POINTER;

globalvalue LONGWORD CLUACC_NORMAL;
globalvalue LONGWORD CLUACC_NOACCESS;

#define		PREFIX			"ACCESS_"
#define		PREFIX_LENGTH		(sizeof(PREFIX) - 1)
#define		NODENAME_LENGTH		15

main()
{
    LONGWORD status;			/* Status field for system services */
    static WORD nodename_length;	/* Returned by sys$getsyi */
    static LONGWORD id_value;		/* Returned by sys$asctoid */
    static struct {			/* Structure to pass to sys$find_held */
	LONGWORD uic;			/* UIC of current process */
	LONGWORD null;			/* Must be zero */
    } holder = { 0, 0};
    static WORD uic_length;		/* Returned by sys$getjpi */
    static LONGWORD contxt = 0;		/* For use with sys$find_held */
    static LONGWORD id_found;		/* Returned by sys$find_held */

/*
 * Structure to build the name of the identifier in
 */
    static struct {
	BYTE prefix[PREFIX_LENGTH];
	BYTE nodename[NODENAME_LENGTH + 1];
    } identifier_name = { PREFIX } ;

/*
 * Descriptor for identifier_name to pass to sys$asctoid
 */
    static struct dsc$descriptor dsc_identifier = { 
	sizeof(identifier_name),
	DSC$K_DTYPE_T,
	DSC$K_CLASS_S,
	&identifier_name
    };

/*
 * Descriptor for nodename to pass to lib$signal
 */
    static struct dsc$descriptor dsc_nodename = { 
	sizeof(identifier_name.nodename),
	DSC$K_DTYPE_T,
	DSC$K_CLASS_S,
	&identifier_name.nodename
    };

/*
 * Itemlist structure for sys$getsyi
 */
    static struct SYI {
	struct {
	    WORD syi_buffer_length;
	    WORD syi_item_code;
	    POINTER syi_buffer;
	    WORD *syi_return_length;
	} syi_item[1];
	LONGWORD syi_null;
    } syi_itemlist = {
	{
	    {
		NODENAME_LENGTH,
		SYI$_NODENAME,
		identifier_name.nodename,
		&nodename_length
	    }
	},
	0
    };

/*
 * Itemlist structure for sys$getjpi
 */
    static struct JPI {
	struct {
	    WORD jpi_buffer_length;
	    WORD jpi_item_code;
	    POINTER jpi_buffer;
	    WORD *jpi_return_length;
	} jpi_item[1];
	LONGWORD jpi_null;
    } jpi_itemlist = {
	{
	    {
		sizeof(holder.uic),
		JPI$_UIC,
		&holder.uic,
		&uic_length
	    }
	},
	0
    };

/*
 * IO status block for sys$getsyi ans sys$getjpi
 */
    struct IOSB {
	LONGWORD io_status;
	LONGWORD io_reserved;
    } iosb;


		/* Start of code for main() */


/*
 * Get the nodename for this node
 */
    status = sys$getsyiw(0, 0, 0, &syi_itemlist, &iosb, 0, 0);
    if (!(status & 1)) lib$signal(status);
    if (!(iosb.io_status & 1)) lib$signal(iosb.io_status);
    dsc_identifier.dsc$w_length = PREFIX_LENGTH + nodename_length;

/*
 * Get the identifier value
 */
    status = sys$asctoid(&dsc_identifier, &id_value, 0);
    if (!(status & 1)) lib$signal(status);

/*
 * Get the UIC of the current user
 */
    status = sys$getjpiw(0, 0, 0, &jpi_itemlist, &iosb, 0, 0);
    if (!(status & 1)) lib$signal(status);
    if (!(iosb.io_status & 1)) lib$signal(iosb.io_status);

/*
 * See whether identifier is held by this user
 */
    while ((status = sys$find_held(&holder, &id_found, 0, &contxt)) != SS$_NOSUCHID) {
	if (!(status & 1)) lib$signal(status);
	if (id_found == id_value) {
	    exit(CLUACC_NORMAL);
	}
    }
    dsc_nodename.dsc$w_length = nodename_length;
    lib$stop(CLUACC_NOACCESS, 1, &dsc_nodename);
}    
--------------------------------------------------------------------------------
!
!	Module:		CLUACCMSG.MSG
!	Author:		Herman Verkade
!
!	Revision History:
!
!	000	16-jan-1987	Created
!
	.TITLE		Status messages for CLUSTER_ACCESS
	.IDENT		'V1.0-000'
	.FACILITY	CLUACC,107
	.SEVERITY	SUCCES
NORMAL		<Normal succesfull completion>
	.SEVERITY	FATAL
NOACCESS	<You are not authorized to use node !AS>
	.END

