/* REXX */
/* CLS2REXXed by FSOX001 on 23 May 2017 at 14:59:56  */
/*trace ?r*/
Signal On NoValue
Call On Error
Signal On Failure
Signal On Syntax
Parse source opsys . exec_name .
Address ISREDIT
 
"MACRO"               /* CARM0420 EDIT TEMP5(*)  */
/*********************************************************************/
/* Creates SENSITVE(rpts and PDIs) for RACF dataset automation.      */
/* 05/25/2004 JL.NELSON CHANGED TO DISPLAY NEW FINDINGS.             */
/* 06/15/2004 JL.NELSON ADDED EXIT CODE.                             */
/* 07/19/2004 JL.Nelson Changed DISA Standard to STIG requirement.   */
/* 11/09/2004 JL.NELSON Added code for Authorized users.             */
/* 12/06/2004 JL.NELSON Changed STIG message to match AUUACC.        */
/* 12/22/2004 JL.NELSON Adjusted access levels/                      */
/* 01/13/2005 JL.NELSON Made AULOG and AUUACC fixed length.          */
/* 01/20/2005 JL.NELSON Drop users in GROUPs if also as USERIDs.     */
/* 02/04/2005 JL.NELSON Added check for AUDIT(ALL(...)) level.       */
/* 02/25/2005 JL.NELSON Changed constants to variables.              */
/* 03/09/2005 JL.NELSON Changed LMMREP to LMMADD/LMMREP to avoid     */
/*            errors.                                                */
/* 03/22/2005 JL.NELSON PDI member maybe blank, old cact0001.        */
/* 04/21/2005 JL.NELSON Changed Logging default to NONE.             */
/* 06/03/2005 JL.Nelson Changed STIG requirement to DISA             */
/*            recommendation.                                        */
/* 06/09/2005 JL.NELSON Pass MAXCC in ZISPFRC variable.              */
/* 07/08/2005 JL.NELSON Added period after "For complete details     */
/*            ..."  statement.                                       */
/* 10/23/2006 CL.FENTON Chgd test for which accesses to ignore to    */
/*            use AUUACC_LVL over access in record.                  */
/* 09/10/2007 CL.Fenton Separated SRR data from Sensitve to          */
/*            TEMP6.                                                 */
/* 11/30/2007 CL.Fenton Removed commented line commands.             */
/* 01/31/2008 CL.Fenton Removed DUP_USERS variable.                  */
/* 04/29/2008 CL.Fenton Changes in the evaluation of audit           */
/*            logging.                                               */
/* 05/20/2009 CL.Fenton Changes to bypass GENERIC testing.           */
/* 05/30/2012 CL.FENTON Chgs to allow use of AUACCESS for            */
/*            authorized users list to prevent the possible          */
/*            "IKJ56548I INSUFFICIENT STORAGE FOR CLIST TO           */
/*            CONTINUE" message from occurring when a DIALOG user    */
/*            group contains an excessive number of user,            */
/*            CSD-AR003400969.                                       */
/* 03/31/2016 CL.Fenton Changes to not specify empty groups in       */
/*            finding details, STS-013692.                           */
/* 04/04/2016 CL.Fenton Changes to ensure UACC(NONE) is specified    */
/*            and testing to review GENERIC, *, access,              */
/*            STS-013858.                                            */
/* 05/23/2017 CL.FENTON Converted script from CLIST to REXX.         */
/*            Also added GROUPID user list processing (CARM0005),    */
/*            STS-017060.                                            */
/* 02/16/2018 CL.FENTON Trimmed statements in processing records     */
/*            and verified permissions of GENERIC where requirements */
/*            specified NONE, STS-019208 and STS-019211              */
/* 10/26/2018 CL.FENTON Corrected issue when user is directly        */
/*            permitted and permitted through a group to ignore the  */
/*            group permission, STS-020788.                          */
/* 07/16/2019 CL.FENTON Corrected issue when all user are authorized */
/*            and GENERIC (*) is a finding for the vulnerability,    */
/*            STS-022850.                                            */
/* 07/19/2019 CL.FENTON Changes include a limit of 1000 userids      */
/*            being extracted until all userids are collected for    */
/*            groups with excessive number of userids to avoid an    */
/*            error on variable LIDLIST, STS-022967.                 */
/*                                                                   */
/*                                                                   */
/*                                                                   */
/*********************************************************************/
pgmname = "CARM0420 07/19/19"
sysprompt = "OFF"                /* CONTROL NOPROMPT          */
sysflush = "OFF"                /* CONTROL NOFLUSH           */
sysasis = "ON"                 /* CONTROL ASIS - caps off   */
Address ISPEXEC "CONTROL NONDISPL ENTER"
Address ISPEXEC "CONTROL ERRORS RETURN"
 
/*******************************************/
/* VARIABLES ARE PASSED TO THIS MACRO      */
/*******************************************/
maxcc = 0
return_code = 0
Address ISPEXEC "VGET (CONSLIST COMLIST SYMLIST TERMMSGS",
  "AUACCESS SENSITVE TEMP6 RPTMBR TITLE PDIMBR ODSNAME TBLUSR",
  "RACFRPT CARM0005 LISTGRP) ASIS"
rm20vget = return_code
If return_code <> 0 then do
  Say pgmname "VGET RC =" return_code zerrsm
  Say pgmname "CONSLIST/"conslist "COMLIST/"comlist,
    "SYMLIST/"symlist "TERMMSGS/"termmsgs
  Say pgmname "AUACCESS/"auaccess "SENSITVE/"sensitve,
    "TEMP6/"temp6 "RPTMBR/"rptmbr "TITLE/"title "PDIMBR/"pdimbr,
    "ODSNAME/"odsname "TBLUSR/"tblusr
  Say pgmname "RACFRPT/"racfrpt "CARM0005/"carm0005 "LISTGRP/"listgrp
  return_code = return_code + 16
  SIGNAL ERR_EXIT
  end
 
If CONSLIST = "ON" | COMLIST = "ON" | SYMLIST = "ON" ,
  then Trace ?r
 
return_code = 0
 
/*******************************************/
/* SET MESSAGES                            */
/*******************************************/
syssymlist = symlist          /* CONTROL SYMLIST/NOSYMLIST */
sysconlist = conslist         /* CONTROL CONLIST/NOCONLIST */
syslist = comlist          /* CONTROL LIST/NOLIST       */
sysmsg = termmsgs         /* CONTROL MSG/NOMSG         */
return_code = 0
sortsw = "D"
 
 
/*******************************************/
/* Expand GROUPIDs                         */
/*******************************************/
"CURSOR = 1 0"
return_code = 0
do until return_code > 0
  lidrc = 0
  lidline = 1
  "FIND 'GROUPID(' NX"
  If return_code > 0 then leave
  "(CURLINE) = LINENUM .ZCSR"
  "(DATA) = LINE" curline
  parse var data . "GROUPID(" uzid ")" .
  do until lidrc > 0
    Address ISPEXEC "VPUT (UZID SORTSW LIDRC LIDLINE) ASIS"
    Address ISPEXEC "EDIT DATAID("racfrpt") MACRO("carm0005")",
      "MEMBER("listgrp")"
    Address ISPEXEC "VGET (LIDLIST LIDRC LIDLINE) ASIS"
    Call Process_groupid
    lidline = lidline + 1
    end
  "EXCLUDE 'GROUPID("left(uzid,8)")' ALL"
  end
 
"RESET"
 
"(MEMBER) = MEMBER"
"(DSNAME) = DATASET"
"(ENDER) = LINENUM .ZLAST"
omember = pdimbr
headlin2 = left(" ",130,"=")
If pdimbr <> "" then,
  Call Process_pdimbr
 
 
/*******************************************/
/* COPY REPORT                             */
/*******************************************/
 
 
COPY_REPORT:
return_code = 0
omember = rptmbr
headline = "                    "title
ac = headline
Address ISPEXEC "LMPUT DATAID("sensitve") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
ac = headlin2       /* ==== */
Address ISPEXEC "LMPUT DATAID("sensitve") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
ac = " "
Address ISPEXEC "LMPUT DATAID("sensitve") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
grplist = ""
uzid = ""
Do CURLINE = 1 to ender
  "(AC) = LINE" curline
  if pos("GROUPID("left(uzid,8)")",ac) = 0 &,
     uzid <> "" then,
    grplist = grplist left(uzid,8)
  parse var ac . "GROUPID(" uzid ")" .
  if pos("GROUPID(",ac) > 0 & pos("USER=",ac) > 0 &,
     wordpos(uzid,grplist) > 0 then iterate
  Address ISPEXEC "LMPUT DATAID("sensitve") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  end
return_code = 0
Address ISPEXEC "LMMADD DATAID("sensitve") MEMBER("omember")"
If return_code = 4 then do
  return_code = 0
  Address ISPEXEC "LMMREP DATAID("sensitve") MEMBER("omember")"
  If return_code <> 0 then,
    Say pgmname "LMMREP_SENSITVE_RC =" return_code omember zerrsm
  end
Else do
  If return_code <> 0 then,
    Say pgmname "LMMADD_SENSITVE_RC =" return_code omember zerrsm
  end
 
 
END_EDIT:
return_code = 0
 
 
ERR_EXIT:
If maxcc >= 16 | return_code > 0 then do
  Address ISPEXEC "VGET (ZISPFRC) SHARED"
  If maxcc > zispfrc then
    zispfrc = maxcc
  Else,
    zispfrc = return_code
  Address ISPEXEC "VPUT (ZISPFRC) SHARED"
  Say pgmname "ZISPFRC =" zispfrc
  end
rm420rc = return_code
Address ISPEXEC "VPUT (RM20VGET RM420RC) ASIS"
"CANCEL"
Exit 0
 
 
Process_pdimbr:
auuacc_lvl = 0
auuacc = "NONE    "
x = pos("UACC",tblusr)
If x > 0 then do
  auuacc_lvl = substr(tblusr,x+8,1)
  Select
    When auuacc_lvl = 0 then auuacc = "NONE    "
    When auuacc_lvl = 1 then auuacc = "EXECUTE "
    When auuacc_lvl = 3 then auuacc = "READ    "
    When auuacc_lvl = 5 then auuacc = "UPDATE  "
    When auuacc_lvl = 6 then auuacc = "CONTROL "
    When auuacc_lvl = 9 then auuacc = "ALTER   "
    Otherwise nop
    end
  end
aulog_lvl = 0
aulog = "NONE    "
x = pos("LOGGING ",tblusr)
If x > 0 then do
  aulog_lvl = substr(tblusr,x+8,1)
  Select
    When aulog_lvl = 0 then aulog = "NONE    "
    When aulog_lvl = 1 then aulog = "EXECUTE "
    When aulog_lvl = 3 then aulog = "READ    "
    When aulog_lvl = 5 then aulog = "UPDATE  "
    When aulog_lvl = 6 then aulog = "CONTROL "
    When aulog_lvl = 9 then aulog = "ALTER   "
    Otherwise nop
    end
  end
return_code = 0
 
/*******************************************/
/* PUT HEADINGS OUT                        */
/*******************************************/
headline = "                    "title
ac = headline
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
ac = headlin2       /* ==== */
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
ac = " "
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
headline = "SRR START      AULOG =" aulog"  AUUACC =" auuacc
ac = headline
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
 
/*****************/
/* CHECK ERRORS  */
/*****************/
"CURSOR = 1 0"
std_error = "N"
std_notap = "N"
 
 
NEXT_ERROR:
return_code = 0
do until return_code > 0
  return_code = 0
  "FIND 'SRR ' 1"
  If return_code <> 0 then leave
  "(CURLINE) = LINENUM .ZCSR"
  "(DATA) = LINE" curline
  ac = data
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  If pos(data,"YES") = 5 then std_error = "Y"
  If pos(data,"N/A") = 5 then std_notap = "Y"
  end
 
 
END_ERROR:
return_code = 0
If std_error = "Y" then do
  ac = "SRR STD0 DISA recommendation ADDSD -"
  ac = ac" All system datasets should be protected"
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  end
 
Call Auth_user_check
 
 
END_USER:
return_code = 0
If std_user = "Y" then do
  ac2 = "ALTER"
  If auuacc_lvl < 5 then,
    ac2 = "UPDATE and/or" ac2
  If auuacc_lvl < 3 then,
    ac2 = "READ," ac2
  If auuacc_lvl = 0 then,
    ac2 = "EXECUTE," ac2
  ac = "SRR STD1 DISA recommendation USERID -"
  ac = ac" Users and Started tasks should be in the"
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  ac = "SRR STD1   authorized user list for ACCESS of" ac2
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  end
 
/********************************/
/* Check for generic RACF rules */
/********************************/
"CURSOR = 1 0"
std_read = "N"
 
return_code = 0
If std_read = "Y" then do
  ac2 = "ALTER"
  If auuacc_lvl < 5 then,
    ac2 = "UPDATE and/or" ac2
  If auuacc_lvl < 3 then,
    ac2 = "READ," ac2
  If auuacc_lvl = 0 then,
    ac2 = "EXECUTE," ac2
  ac = "SRR STD2 DISA recommendation - GENERIC"
  ac = ac" USERID's should not be used."
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  ac = "SRR STD2   for ACCESS of" ac2
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  end
 
/*******************************************/
/* Check Auditing                          */
/*******************************************/
"CURSOR = 1 0"
std_audit = "N"
If aulog_lvl > 0 then do
 
 
NEXT_UACC3:
  do until return_code > 0
    return_code = 0
    "FIND 'UACC'          54"
    If return_code <> 0 then leave
    "(CURLINE) = LINENUM .ZCSR"
    "(DATA) = LINE" curline
    profile = left(data,44)
    audit = "  "
    pauds = "ER"
    paudf = "ER"
    If substr(data,76,5) = "AUDIT" then,
      audit = substr(data,76,42)
    si = pos("SUCCESS",audit)
    fi = pos("FAILURES",audit)
    ai = pos("ALL",audit)
    sx = "NONE"
    fx = "NONE"
    If si > 0 then do
      parse var audit . "SUCCESS(" sx ")" .
      end
    If fi > 0 then do
      parse var audit . "FAILURES(" fx ")" .
      end
    If ai > 0 then do
      parse var audit . "ALL(" sx ")" .
      fx = sx
      end
    Select
      When fx = "NONE    " then lvl = 0
      When fx = "EXECUTE " then lvl = 1
      When fx = "READ    " then lvl = 3
      When fx = "UPDATE  " then lvl = 5
      When fx = "CONTROL " then lvl = 6
      When fx = "ALTER   " then lvl = 9
      Otherwise do
        Say pgmname "Unknown access" fx "not found in list"
        lvl = 0
        end
      end
    If lvl <= aulog_lvl &  lvl <> 0 then,
      paudf = "OK"
    Select
      When sx = "NONE    " then lvl = 0
      When sx = "EXECUTE " then lvl = 1
      When sx = "READ    " then lvl = 3
      When sx = "UPDATE  " then lvl = 5
      When sx = "CONTROL " then lvl = 6
      When sx = "ALTER   " then lvl = 9
      Otherwise do
        Say pgmname "Unknown access" sx "not found in list"
        lvl = 0
        end
      end
    If lvl <= aulog_lvl &  lvl <> 0 then,
      pauds = "OK"
    If pauds <> "OK" | paudf <> "OK" then do
      ac = "SRR YES3" profile" "audit"             "
      Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
        "DATALEN("length(ac)") MEMBER("omember")"
      std_audit = "Y"
      end
    end
  end
 
 
END_UACC3:
return_code = 0
If std_audit = "Y" then do
  aulogt = aulog
  ac = "SRR STD3 DISA recommendation - AUDIT("
  ac = ac"SUCCESS("aulogt")FAILURES(READ))"
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  end
 
/**************************/
/* Check RACF Warn option */
/**************************/
"CURSOR = 1 0"
std_warn = "N"
 
 
NEXT_UACC4:
do until return_code > 0
  return_code = 0
  "FIND 'UACC'          54"
  If return_code <> 0 then leave
  "(CURLINE) = LINENUM .ZCSR"
  "(DATA) = LINE" curline
  profile = left(data,44)
  warn = substr(data,68,7)
  wi = pos("(N)",warn)
  If wi = 0 then do
    ac = "SRR YES4" profile warn
    Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
      "DATALEN("length(ac)") MEMBER("omember")"
    std_warn = "Y"
    end
  end
 
 
END_UACC4:
return_code = 0
If std_warn  = "Y" then do
  ac = "SRR STD4 DISA recommendation - WARN(N)"
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  end
 
/***********************************/
/* Check RACF UACC univeral access */
/***********************************/
"CURSOR = 1 0"
std_uacc = "N"
 
 
NEXT_UACC5:
do until return_code > 0
  return_code = 0
  "FIND 'UACC'          54"
  If return_code <> 0 then leave
  "(DATA) = LINE .ZCSR"
  parse var data profile 45 . 54 uacc .
  parse var data . "UACC(" uacc_txt ")" .
  If pos("NONE",uacc) > 0 then iterate
  Select
    When uacc_txt = "NONE    " then lvl = 0
    When uacc_txt = "EXECUTE " then lvl = 1
    When uacc_txt = "READ    " then lvl = 3
    When uacc_txt = "UPDATE  " then lvl = 5
    When uacc_txt = "CONTROL " then lvl = 6
    When uacc_txt = "ALTER   " then lvl = 9
    Otherwise do
      Say pgmname "Unknown access" access "not found in list"
      lvl = 9
      end
    end
  ac = "SRR YES5" profile" "uacc
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  std_uacc = "Y"
  end
 
 
END_UACC5:
return_code = 0
If std_uacc  = "Y" then do
  ac = "SRR STD5 DISA recommendation - UACC(NONE)"
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  end
headline = "SRR END"
ac = headline
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
ac = headlin2       /* ==== */
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
ac = " "
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
 
/*************************************/
/* Copy Update only entries for PDIs */
/*************************************/
cnt = 0
Do curline = 1 to ender
  "(AC) = LINE" curline
  If left(ac,7) = "SRR N/A" then iterate
  If pos(" ACCESS(",ac) = 22 then do
    parse var ac . " ACCESS(" access ")" .
    Select
      When access = "NONE    " then lvl = 0
      When access = "EXECUTE " then lvl = 1
      When access = "READ    " then lvl = 3
      When access = "UPDATE  " then lvl = 5
      When access = "CONTROL " then lvl = 6
      When access = "ALTER   " then lvl = 9
      Otherwise do
        Say pgmname "Unknown access" access "not found in list"
        lvl = 0
        end
      end
    If lvl <= auuacc_lvl | substr(ac,30,2) = " " |,
      (pos("GROUP",ac) = 5 & pos("USER=",ac) = 40) then iterate
    end
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  cnt = cnt + 1
  If cnt > 25 then leave
  end
 
 
CLOSE_SRR:
return_code = 0
ac = " "
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
ac = "For complete details see" odsname"("rptmbr")."
Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
  "DATALEN("length(ac)") MEMBER("omember")"
return_code = 0
Address ISPEXEC "LMMADD DATAID("temp6") MEMBER("omember")"
If return_code = 4 then do
  return_code = 0
  Address ISPEXEC "LMMREP DATAID("temp6") MEMBER("omember")"
  If return_code <> 0 then,
    Say pgmname "LMMREP_TEMP6_RC =" return_code omember zerrsm
  end
Else do
  If return_code <> 0 then,
    Say pgmname "LMMADD_TEMP6_RC =" return_code omember zerrsm
  end
return_code = 0
Return 0
 
 
/*******************************************/
/* Authorized user checks                  */
/*******************************************/
Auth_user_check:
Address ISPEXEC "LMMFIND DATAID("auaccess") MEMBER("rptmbr")"
If return_code > 0 then Return 0
std_user = "N"
 
 
READ_AUACCESS:
do until return_code > 0
  return_code = 0
  Address ISPEXEC "LMGET DATAID("auaccess") MODE(INVAR)",
    "DATALOC(AUREC) DATALEN(LRECL) MAXLEN(255)"
  If return_code = 8 then do
    "EXCLUDE 'USER=Empty*' ALL 40"
    return_code = 0
    "CURSOR = 1 0"
    scmd = "'USER=' 40"
    Call USERID_NOTAUTH
    Return 0
    end
  If return_code > 4 then do
    Say pgmname "LMGET_AUACCESS_RC =" return_code zerrsm
    return_code = return_code + 16
    Return 0
    end
  return_code = 0
  If left(aurec,8) = "*" then,
    "FIND ALL 'GENERIC("left(aurec,8)"' 5 NX"
  Else,
    "FIND ALL 'USER="left(aurec,8)"' 40 NX"
  If return_code <> 0 then do
    return_code = 0
    iterate
    end
  aulid = substr(aurec,1,8)
  aulvl = substr(aurec,9,1)
  "CURSOR = 1 0"
  return_code = 0
 
 
NEXT_USER:
  do until return_code <> 0
    return_code = 0
    If left(aurec,1) = "*" then,
      "FIND 'GENERIC("aulid")' 5 NX"
    Else,
      "FIND 'USER="aulid"' 40 NX"
    If return_code <> 0 then leave
    "(DATA) = LINE .ZCSR"
    access = substr(data,30,8)
    Select
      When access = "NONE    " then alvl = 0
      When access = "EXECUTE " then alvl = 1
      When access = "READ    " then alvl = 3
      When access = "UPDATE  " then alvl = 5
      When access = "CONTROL " then alvl = 6
      When access = "ALTER   " then alvl = 9
      Otherwise do
        Say pgmname "Unknown access" access "not found in list"
        alvl = 9
        end
      end
 
/*******************************************/
/* CHECK USER IS AUTH                      */
/*******************************************/
    If alvl <= auuacc_lvl | alvl <= aulvl then,
      "XSTATUS .ZCSR = X"
    end
  return_code = 0
  end
 
 
USERID_NOTAUTH:
do until return_code <> 0
  return_code = 0
  "FIND" scmd "NX"
  If return_code <> 0 then do
    If scmd = "'USER=' 40" then do
      "CURSOR = 1 0"
      scmd = "'GENERIC(' 5"
      return_code = 0
      iterate
      end
    Return 0
    end
  "(DATA) = LINE .ZCSR"
  access = substr(data,30,8)
  Select
    When access = "NONE    " then alvl = 0
    When access = "EXECUTE " then alvl = 1
    When access = "READ    " then alvl = 3
    When access = "UPDATE  " then alvl = 5
    When access = "CONTROL " then alvl = 6
    When access = "ALTER   " then alvl = 9
    Otherwise do
      Say pgmname "Unknown access" access "not found in list"
      alvl = 9
      end
    end
  If alvl <= auuacc_lvl then iterate
/* Following information added to remove users in group if permitted directly*/
  If pos("GROUPID(",data) = 5 then do
    "(CURLN) = LINENUM .ZCSR"
    parse var data . 40 test
    parse var test "USER=" user .
    return_code = 0
    "SEEK '"test"' 40 ALL"
    If return_code = 0 then do
      "(DATA1) = LINE .ZCSR"
      "CURSOR =" curln 60
      If pos("USERID("left(user,8)")",data1) = 6 then,
        iterate
      end
    "CURSOR =" curln 60
    return_code = 0
    end
  parse var data . 5 detail 80 profile 124 .
  ac = "SRR YES1" profile" "detail
  Address ISPEXEC "LMPUT DATAID("temp6") MODE(INVAR) DATALOC(AC)",
    "DATALEN("length(ac)") MEMBER("omember")"
  std_user = "Y"
  end
 
 
Process_groupid:
return_code = 0
"FIND 'GROUPID("left(uzid,8)")' LAST"
If return_code > 0 then return
do until return_code <> 0
  "(DATA) = LINE .ZCSR"
  if pos("USER=",data) > 0 then,
    "FIND '"left(data,38)"    ' 1 PREV"
  data1 = left(data,38)
  "(CURLN) = LINENUM .ZCSR"
  "FIND 'UACC(' PREV 54"
  "(DATA) = LINE .ZCSR"
  parse var data profile 45 .
  do xx = 1 to length(lidlist) by 28
    parse var lidlist . =(xx) user +8 name +20 .
    ac = left(data1,38) "USER="user "NAME="name profile
    "LINE_AFTER" curln "= (AC)"
    end
  "CURSOR =" curln 0
  "FIND 'GROUPID("left(uzid,8)")' PREV NX"
  end
"EXCLUDE ') USER=' 38 ALL"
"CURSOR =" curline 50
return_code = 0
return
 
 
NoValue:
Failure:
Syntax:
say pgmname 'REXX error' rc 'in line' sigl':' strip(ERRORTEXT(rc))
say SOURCELINE(sigl)
SIGNAL ERR_EXIT
 
 
Error:
return_code = RC
if RC >= 16 then do
  say pgmname "LASTCC =" RC strip(zerrlm)
  say pgmname 'REXX error' rc 'in line' sigl':' strip(ERRORTEXT(rc))
  say SOURCELINE(sigl)
  end
if return_code > maxcc then
  maxcc = return_code
return
 
 
