AUTHORIZE , A request for an alias & a new function .

Everything related to the OpenVMS security model, system access, system and data protection, and security auditing.

Topic author
babydr
Valued Contributor
Posts: 52
Joined: Thu Dec 23, 2021 8:02 pm
Reputation: 0
Location: Fairbanks , AK.
Status: Offline

AUTHORIZE , A request for an alias & a new function .

Post by babydr » Thu Nov 16, 2023 9:00 pm

Hello All , at the [url]https://wiki.vmssoftware.com/AUTHORIZE[/url] I was re-introduced to the LIST command within AUTHORIZE , The name of this function is in my opinion a mis-use . It should be EXPORT . Thus I request that EXPORT be added as an alias for LIST .

Now , That leads to my New Function request , IMPORT .

Tia , JimL

User avatar

arne_v
Master
Posts: 347
Joined: Fri Apr 17, 2020 7:31 pm
Reputation: 0
Location: Rhode Island, USA
Status: Online
Contact:

Re: AUTHORIZE , A request for an alias & a new function .

Post by arne_v » Fri Nov 17, 2023 9:44 am

I don't consider it an EXPORT more of a SHOW_WITH_OUTPUT_TO_FILE.

Because the output is not really suitable for an IMPORT.

The right dump format for import is to write the actual CREATE statements necessary to create the users.

Such a utility could be written using SYS$GETUAI.

Maybe it already has.

Note that passwords can not be dumped as they only exist in hashed form.
Arne
arne@vajhoej.dk
VMS user since 1986


Topic author
babydr
Valued Contributor
Posts: 52
Joined: Thu Dec 23, 2021 8:02 pm
Reputation: 0
Location: Fairbanks , AK.
Status: Offline

Re: AUTHORIZE , A request for an alias & a new function .

Post by babydr » Fri Nov 17, 2023 9:02 pm

@Arne , from the first reference in the url above ...

LIST ... "Use the /FULL qualifier to create a full report of all the information (except user passwords) contained within the UAF."

IIRC; The /FULL will output the complete list of all permissions,... for that UID/User , Atm my VMS system is on extended restoritive vacation , So I am unable to verify my statement except from memory . And from memory , I With that info taken from another system I was able recreate that users account , Yes minus the password .

This still seems to me to be an EXPORT not just a show (tho show /full did/does show the , iirc , the same data .)

SYS$GETUAI; I'd have to look up that function to see what I could do with it . Even if I'd played with it, It's Been too many years .

I'd Still like to see import for the output of list or export /full . Would have saved me a whole bunch of typing .

Just my $.02
Tia , JimL

User avatar

arne_v
Master
Posts: 347
Joined: Fri Apr 17, 2020 7:31 pm
Reputation: 0
Location: Rhode Island, USA
Status: Online
Contact:

Re: AUTHORIZE , A request for an alias & a new function .

Post by arne_v » Fri Nov 17, 2023 10:51 pm

SYS$GETUAI can retrieve info for SYSUAF from a program.

I probably have an example. Any preference for language?
Arne
arne@vajhoej.dk
VMS user since 1986


Topic author
babydr
Valued Contributor
Posts: 52
Joined: Thu Dec 23, 2021 8:02 pm
Reputation: 0
Location: Fairbanks , AK.
Status: Offline

Re: AUTHORIZE , A request for an alias & a new function .

Post by babydr » Mon Nov 20, 2023 9:39 pm

@Arne , My preference is 'C' , Tho an example in fortran might tickle the brain too ;-) , Tia , JimL


hein
Active Contributor
Posts: 41
Joined: Fri Dec 25, 2020 5:20 pm
Reputation: 0
Status: Offline

Re: AUTHORIZE , A request for an alias & a new function .

Post by hein » Mon Nov 20, 2023 11:11 pm

I have a very coarse C sample usage for SYS$GETUAI mixing C formatting and FAO

Sample usage showing CSV output for wildcard ending usernames:

Code: Select all

$ define sysuaf sys$login:sysuaf.tmp
$ mcr sys$login:getuai vande  USERNAME DEFDEV DEFDIR DEF_PRIV
USERNAME,DEFDEV,DEFDIR,DEF_PRIV
VANDENBROUCK,DISK_USER:,[DECUSERVE_USER.VANDENBROUCK],00108000
VANDERMERWE,DISK_USER:,[DECUSERVE_USER.VANDERMERWE],00108000
VANDERZAND,DISK_USER:,[DECUSERVE_USER.VANDERZAND],00108000
Left as exercise:
- change output format to "ADD <username> /x=x_val/y=y_val ...
- change bitmasks like DEF_PRIV to token list
- add default field list
- change to username list param
- only wildcard lookup when username ends in <*> ?
- true wildcard matching?

Hope this helps some,
Hein

getuai.c - help text

Code: Select all

$ mcr sys$login:getuai

Usage:
 $MCR disk:[dir]GETUAI username [uai field list (space seperated)]

 RMS generic match for username. Use * for all users.
 Symbols:
        USERNAME        ACCOUNT ASTLM   BATCH_ACCESS_P  BATCH_ACCESS_S
        BIOLM   BYTLM   CLITABLES       CPUTIM  DEFCLI
        DEFDEV  DEFDIR  DEF_PRIV        DFWSCNT DIALUP_ACCESS_P
        DIALUP_ACCESS_S DIOLM   ENQLM   EXPIRATION      FILLM
        FLAGS   GRP     JTQUOTA LASTLOGIN_I     LASTLOGIN_N
        LGICMD  LOCAL_ACCESS_P  LOCAL_ACCESS_S  LOGFAILS        MAXACCTJOBS
        MAXDETACH       MAXJOBS MEM     NETWORK_ACCESS_P        NETWORK_ACCESS_S
        OWNER   PBYTLM  PGFLQUOTA       PRCCNT  PRI
        PRIMEDAYS       PRIV    PWD_DATE        PWD_LENGTH      PWD_LIFETIME
        QUEPRI  REMOTE_ACCESS_P REMOTE_ACCESS_S SHRFILLM        TQCNT
        UIC     WSEXTENT        WSQUOTA
getuai.c

Code: Select all

#include <descrip>
#include <uaidef>
#include <string>
#include <stdio>
#include <ctype>
#include <RMS>


/*  GETUAI.C,   Hein van den Heuvel, September 1997
**
**  Test program to extract SYSUAF data into comma seperated value (CSV) list.
**  Only tested using VAXC, the fao_param list use will need fixing for Alpha.
**  - update - works on Eisner - Alpha - 2023.
*/

int     SYS$OPEN(), SYS$CONNECT(), SYS$FIND(), SYS$GET();
int     SYS$GETUAI(), SYS$FAOL(), LIB$PUT_OUTPUT();

typedef struct { short size, code; void *buf; short *len; } item;
typedef struct { short size, code; char *format, *name ;} field;
char *out_p, *fao_p, username[64];
$DESCRIPTOR     (username_d, username);

void setup_field ( field *f, item *i, char *buffer, void **fao_param )
{
    out_p += sprintf (out_p, "%s,",f->name);

    i->size =  f->size;
    i->code =  f->code;
    i->len =  NULL;
    strcpy (fao_p,   f->format);
    fao_p += strlen( f->format);

    if (f->size <= 4) {
        i->buf = (void *) fao_param;
        *fao_param = 0;
    } else {
        i->buf = buffer;
        *fao_param = buffer;
        memset ( buffer, 0, 8);
        if (f->code == UAI$_USERNAME) *fao_param = &username_d;
    }
}

main(int argc, char *argv[])
{
static    field fields[] = {

    32, UAI$_USERNAME, "!AS,", "USERNAME",      /* username                         */
    36, UAI$_ACCOUNT, "!AZ,", "ACCOUNT",        /* account name (fake zero)         */
     2, UAI$_ASTLM, "!UW,", "ASTLM",            /* AST queue limit                  */
     3, UAI$_BATCH_ACCESS_P, "!XL,", "BATCH_ACCESS_P",  /* hourly batch access, primary     */
     3, UAI$_BATCH_ACCESS_S, "!XL,", "BATCH_ACCESS_S",  /* hourly batch access, secondary   */
     2, UAI$_BIOLM, "!UW,", "BIOLM",            /* buffered I/O limit               */
     4, UAI$_BYTLM, "!UL,", "BYTLM",            /* buffered I/O byte count limit    */
    32, UAI$_CLITABLES, "!AC,", "CLITABLES",    /* user CLI tables                  */
     4, UAI$_CPUTIM, "!UL,", "CPUTIM",          /* CPU time quota                   */
    32, UAI$_DEFCLI, "!AC,", "DEFCLI",          /* default command interpreter      */
    32, UAI$_DEFDEV, "!AC,", "DEFDEV",          /* default device                   */
    64, UAI$_DEFDIR, "!AC,", "DEFDIR",          /* default directory                */
     8, UAI$_DEF_PRIV, "!@XL,", "DEF_PRIV",     /* default process privileges       */
     4, UAI$_DFWSCNT, "!UL,", "DFWSCNT",        /* default working set size         */
     3, UAI$_DIALUP_ACCESS_P, "!UW,", "DIALUP_ACCESS_P",        /* hourly dialup access, primary    */
     3, UAI$_DIALUP_ACCESS_S, "!UW,", "DIALUP_ACCESS_S",        /* hourly dialup access, secondary  */
     2, UAI$_DIOLM, "!UW,", "DIOLM",            /* direct I/O limit                 */
/*     4, UAI$_ENCRYPT, "!@XL,", "ENCRYPT",        encryption algorithm             */
/*     4, UAI$_ENCRYPT2, "!@XL,", "ENCRYPT2",      encryption algorithm for 2nd pwd */
     2, UAI$_ENQLM, "!UW,", "ENQLM",            /* enqueue limit                    */
     8, UAI$_EXPIRATION, "!%D,", "EXPIRATION",  /* expiration date for account      */
     2, UAI$_FILLM, "!UW,", "FILLM",            /* open file limit                  */
     4, UAI$_FLAGS, "!XL,", "FLAGS",            /* user flags longword              */
     2, UAI$_GRP, "!OW,", "GRP",                /* group subfield                   */
     2, UAI$_JTQUOTA, "!UW,", "JTQUOTA",        /* job-wide logical name table creation quota */
     8, UAI$_LASTLOGIN_I, "!%D,", "LASTLOGIN_I", /* date of last interactive login   */
     8, UAI$_LASTLOGIN_N, "!%D,", "LASTLOGIN_N", /* date of last non-interactive login */
     64, UAI$_LGICMD, "!AC,", "LGICMD",                 /* login command file               */
     3, UAI$_LOCAL_ACCESS_P, "!XW,", "LOCAL_ACCESS_P",  /* hourly local access, primary     */
     3, UAI$_LOCAL_ACCESS_S, "!XW,", "LOCAL_ACCESS_S",  /* hourly local access, secondary   */
     2, UAI$_LOGFAILS, "!UW,", "LOGFAILS",      /* count of login failures          */
     2, UAI$_MAXACCTJOBS, "!UW,", "MAXACCTJOBS", /* maximum jobs for account allowed */
     2, UAI$_MAXDETACH, "!UW,", "MAXDETACH",    /* maximum detached processes for UIC */
     2, UAI$_MAXJOBS, "!UW,", "MAXJOBS",        /* maximum jobs for UIC allowed     */
/*   2, UAI$_MAX_CLASS, "!UW,", "MAX_CLASS",       maximum security class           */
     2, UAI$_MEM, "!OW,", "MEM",                /* member subfield                  */
/*   2, UAI$_MIN_CLASS, "!UW,", "MIN_CLASS",       minimum security class           */
     3, UAI$_NETWORK_ACCESS_P,  "!XW,", "NETWORK_ACCESS_P", /* hourly network access, primary   */
     3, UAI$_NETWORK_ACCESS_S,  "!XW,", "NETWORK_ACCESS_S", /* hourly network access, secondary */
    32, UAI$_OWNER, "!AC,", "OWNER",            /* owner's name                     */
/*   4, UAI$_PARENT_ID, "!XL,", "PARENT_ID",       identifier of owner of this account */
     4, UAI$_PBYTLM, "!UL,", "PBYTLM",          /* paged buffer I/O byte count limit */
     4, UAI$_PGFLQUOTA, "!UL,", "PGFLQUOTA",    /* page file quota                  */
     4, UAI$_PRCCNT, "!UL,", "PRCCNT",          /* subprocess creation limit        */
     1, UAI$_PRI, "!UB,", "PRI",                /* base process priority            */
     4, UAI$_PRIMEDAYS, "!XL,", "PRIMEDAYS",    /* bits representing primary days   */
     8, UAI$_PRIV, "!@XL,", "PRIV",             /* process privilege vector         */
/*     1, UAI$_PROXIES, "!UW,", "PROXIES",         number of proxies granted        */
/*     1, UAI$_PROXY_LIM, "!UW,", "PROXY_LIM",     number of proxies user can grant */
/*     1, UAI$_PWD, "!UW,", "PWD",                 hashed password                  */
/*     1, UAI$_PWD2, "!UW,", "PWD2",               second password                  */
/*     1, UAI$_PWD2_DATE, "!UW,", "PWD2_DATE",     date of 2nd password change      */
     8, UAI$_PWD_DATE, "!%D,", "PWD_DATE",      /* date of password change          */
     1, UAI$_PWD_LENGTH, "!UB,", "PWD_LENGTH",  /* minimum password length          */
     8, UAI$_PWD_LIFETIME,  "!%D,", "PWD_LIFETIME", /* password lifetime                */
     1, UAI$_QUEPRI, "!UB,", "QUEPRI",          /* maximum job queuing priority     */
     3, UAI$_REMOTE_ACCESS_P, "!XL,", "REMOTE_ACCESS_P",        /* hourly remote access, primary    */
     3, UAI$_REMOTE_ACCESS_S, "!XL,", "REMOTE_ACCESS_S",        /* hourly remote access, secondary  */
/*     1, UAI$_RTYPE, "!UW,", "RTYPE",             UAF record type                  */
/*     1, UAI$_SALT, "!UW,", "SALT",               random password salt             */
     2, UAI$_SHRFILLM, "!UW,", "SHRFILLM",      /* shared file limit                */
/*     1, UAI$_SUB_ID, "!UW,", "SUB_ID",           user sub-identifier              */
     2, UAI$_TQCNT, "!UW,", "TQCNT",            /* timer queue entry limit          */
     4, UAI$_UIC, "!XL,", "UIC",                /* user ID code                     */
/*     1,  UAI$_USERNAME_TAG, "!UW,", "USERNAME_TAG", tag to differentiate records     */
/*     1, UAI$_USRDATOFF, "!UW,", "USRDATOFF",     offset of counted string of user data */
/*     1, UAI$_VERSION, "!UW,", "VERSION",         UAF format version               */
     4, UAI$_WSEXTENT, "!UL,", "WSEXTENT",      /* working set size limit           */
     4, UAI$_WSQUOTA, "!UL,", "WSQUOTA"} ;      /* working set size quota           */

#define FIELDS sizeof ( fields ) / sizeof ( field )
















    struct FAB  fab;
    struct RAB  rab;
    struct XABKEY       key;

    char    fao[512], out[1024], buffers[FIELDS][64], keybuf[32];
    int     fao_params[FIELDS], i, j, k, l, s, context = -1, match;
    item    items[FIELDS + 1];

    $DESCRIPTOR (out_d, out);
    $DESCRIPTOR (fao_d, fao);

    fab = cc$rms_fab;
    rab = cc$rms_rab;
    key = cc$rms_xabkey;

    fab.fab$b_shr = FAB$M_SHRPUT;
    fab.fab$b_fac = FAB$M_GET;
    fab.fab$l_fna = "SYSUAF";
    fab.fab$b_fns = 6;
    fab.fab$l_dna = "SYS$SYSTEM:.DAT";
    fab.fab$b_dns = strlen (fab.fab$l_dna);
    fab.fab$l_xab = (void *) &key;

    rab.rab$l_fab = &fab;
    rab.rab$l_ubf = (char *) &out;
    rab.rab$w_usz = sizeof (out);
    rab.rab$l_kbf = keybuf;
    rab.rab$b_rac = RAB$C_KEY;

    out_p = out;
    fao_p = fao;
    k = 0;

    if (argc < 2) {
        printf ("\nUsage:\n");
        printf (" $MCR disk:[dir]GETUAI username [uai field list (space seperated)]\n");
        printf ("\n RMS generic match for username. Use * for all users.\n");
//        printf (" DCL Symbol GETUAI_VALUE defined with last values.\n\n");
        printf (" Symbols:\n");
        for (i = 0; i<(sizeof fields / sizeof (field));) {
          printf ("\t%s", fields[i++].name);
          if (!(i%5)) printf ("\n");
        }
        if (i%5) printf ("\n");
        return 1;
        }

    k = 0;
    if (argc > 2) {
        for     (i = 2; i < argc; i++) {
            match = 1;
            for (j = 0; j < strlen(argv[i]); j++) argv[i][j]=_toupper(argv[i][j]);
            for (j = 0; (j < FIELDS) && (match != 0); j++)
                match = strncmp(argv[i],fields[j].name,strlen(argv[i]));
            j--;            /* probably my programming bug. needed on VAXC. */
            if (match == 0) {
                setup_field ( &fields[j], &items[k] , buffers[k], (void *) &fao_params[k] );
                k++;
            } else printf ("NO match found for %s\n", argv[i]);
        }
    } else {
        for (; k < FIELDS; k++)
            setup_field ( &fields[k], &items[k] , buffers[k], (void *) &fao_params[k] );
    }
    *(--out_p) = 0;
    printf ("%s\n", out);
    items[k].size =  0;
    items[k].code =  0;
    fao_d.dsc$w_length = fao_p - fao - 1; /* strip last comma */


    l = strlen(argv[1]);
    for (j = 0; j < l; j++) keybuf[j]=_toupper(argv[1][j]);
    rab.rab$b_ksz = l;

    s = SYS$OPEN ( &fab );
    if (!(s&1)) return s;
    s = SYS$CONNECT ( &rab );
    if (keybuf[0] == '*') {
        rab.rab$b_rac = RAB$C_SEQ;
        if (s & 1) s = SYS$FIND ( &rab );   /* skip password rec */
        }
    if (s & 1) s = SYS$FIND ( &rab );
    rab.rab$b_rac = RAB$C_SEQ;
    while (s & 1) {
        s = SYS$GET ( &rab );
        memcpy (username, &out[key.xab$w_pos0], 32);
        for (i = 0; !(isspace(username[i])); i++);
        username_d.dsc$w_length = i;
        if ( (keybuf[0] != '*') &&
             strncmp(keybuf,username,strlen(keybuf)) != 0) break;
        out_d.dsc$w_length = sizeof ( out );
        if (s & 1) s = SYS$GETUAI ( 0, &context, &username_d,  &items, 0, 0, 0);
        if (s & 1) s = SYS$FAOL ( &fao_d, &out_d, &out_d, fao_params );
        if (s & 1) s = LIB$PUT_OUTPUT ( &out_d );
    }
    if (s==RMS$_EOF) s=1;
    return s ;
}
Last edited by hein on Tue Nov 21, 2023 11:09 am, edited 2 times in total.

User avatar

arne_v
Master
Posts: 347
Joined: Fri Apr 17, 2020 7:31 pm
Reputation: 0
Location: Rhode Island, USA
Status: Online
Contact:

Re: AUTHORIZE , A request for an alias & a new function .

Post by arne_v » Tue Nov 21, 2023 6:49 pm

My example is not nearly is good as Hein's. But I do have the same code in both C and Fortran.

The example gets page file quota for all usernames.

Code: Select all

#include <stdio.h>

#include <prvdef.h>
#include <uaidef.h>
#include <descrip.h>
#include <starlet.h>

struct itemlist {
                short buflen,code;
                long *bufadr,*retlenadr;
                };

int main()
{
   long stat,id,resid,cntx,pgflq;
   short unl;
   char un[33];
   $DESCRIPTOR(undesc,un);
   long priv[2] = { PRV$M_SYSPRV,0 };
   struct itemlist uailist[2] = { {sizeof(pgflq),UAI$_PGFLQUOTA,&pgflq,0} ,
                                  {0,0,0,0} };
   stat = sys$setprv(1,priv,0,0);
   id = -1;
   cntx = 0;
   while (1) {
      undesc.dsc$w_length = sizeof(un);
      stat = sys$idtoasc(id,&unl,&undesc,&resid,0,&cntx);
      if ((stat&1)!=1) break;
      un[unl] = '\0';
      if (resid>0) {
         undesc.dsc$w_length = unl;
         stat = sys$getuai(0,0,&undesc,uailist,0,0,0);
         if ((stat&1)==1) printf("%s %d\n",un,pgflq);
      }
   }
}

Code: Select all

      PROGRAM SYSUAF_SUP
      INCLUDE '($PRVDEF)'
      INCLUDE '($UAIDEF)'
      STRUCTURE /ITEMLIST/
        INTEGER*2 BUFLEN,CODE
        INTEGER*4 BUFADR,RETLENADR
      ENDSTRUCTURE
      INTEGER*4 STAT,ID,RESID,CNTX,PGFLQ
      INTEGER*2 UNL
      CHARACTER*32 UN
      INTEGER*4 PRIV(2)
      RECORD /ITEMLIST/UAILIST(2)
      INTEGER*4 SYS$SETPRV,SYS$IDTOASC,SYS$GETUAI
      DATA PRIV/PRV$M_SYSPRV,0/
      UAILIST(1).BUFLEN=4
      UAILIST(1).CODE=UAI$_PGFLQUOTA
      UAILIST(1).BUFADR=%LOC(PGFLQ)
      UAILIST(1).RETLENADR=0
      UAILIST(2).BUFLEN=0
      UAILIST(2).CODE=0
      UAILIST(2).BUFADR=0
      UAILIST(2).RETLENADR=0
      STAT=SYS$SETPRV(%VAL(1),PRIV,,)
      ID=-1
      CNTX=0
100   STAT=SYS$IDTOASC(%VAL(ID),UNL,UN,RESID,,CNTX)
      IF((STAT.AND.1).NE.1) GOTO 200
      IF(RESID.GT.0) THEN
        STAT=SYS$GETUAI(,,UN(1:UNL),UAILIST,,,)
        IF((STAT.AND.1).EQ.1) WRITE(6,'(1X,A,1X,I)') UN(1:UNL),PGFLQ
      ENDIF
      GOTO 100
200   CONTINUE
      END
Added in 3 minutes 55 seconds:
There are also some known freeware examples.

C:

https://vms.process.com/scripts/fileser ... com?GETUAI

https://vms.process.com/scripts/fileser ... W-USERINFO

https://vms.process.com/scripts/fileser ... rv.com?UAF

Fortran:

https://vms.process.com/scripts/fileser ... om?PROFILE

https://vms.process.com/scripts/fileser ... om?SCANUAF
Arne
arne@vajhoej.dk
VMS user since 1986


sodjan
Active Contributor
Posts: 40
Joined: Mon Apr 24, 2023 3:51 am
Reputation: 0
Status: Offline

Re: AUTHORIZE , A request for an alias & a new function .

Post by sodjan » Wed Nov 22, 2023 7:51 am

Att last one Python port also had/have an interface against the UAF file. Probably shorter code in Python than the C examples.

User avatar

arne_v
Master
Posts: 347
Joined: Fri Apr 17, 2020 7:31 pm
Reputation: 0
Location: Rhode Island, USA
Status: Online
Contact:

Re: AUTHORIZE , A request for an alias & a new function .

Post by arne_v » Wed Nov 22, 2023 10:47 am

A lot shorter!

:-)

Starting point:

Code: Select all

from vms.sysuaf import SYSUAF

uaf = SYSUAF('sys$system:sysuaf.dat')
for usr in uaf.fetchall(0):
    print('add %s /uic=[%o,%o] /dev=%s /dir=%s /wsext=%d /pgflq=%d' % (usr.username, usr.grp, usr.mem, usr.defdev, usr.defdir, usr.wsextent, usr.pgflquota))
Added in 1 minute 33 seconds:
One point though. That Python modules does not use the supported SYS$GETUAI system service, but use the unsupported reading of SYSUAF.DAT as an index-sequential file. I would not worry - I am sure JFP got it right.
Last edited by arne_v on Wed Nov 22, 2023 11:07 am, edited 1 time in total.
Arne
arne@vajhoej.dk
VMS user since 1986


Topic author
babydr
Valued Contributor
Posts: 52
Joined: Thu Dec 23, 2021 8:02 pm
Reputation: 0
Location: Fairbanks , AK.
Status: Offline

Re: AUTHORIZE , A request for an alias & a new function .

Post by babydr » Sat Nov 25, 2023 9:37 pm

@All , Thank You All , The coding & style brings back memories . THank You Agn . JimL

Post Reply