/* REXX */
/* CLS2REXXed by UMLA01S on 7 Aug 2019 at 19:01:44  */
/*trace r?*/
Signal On NoValue
Call On Error
Signal On Failure
Signal On Syntax
Parse source opsys . exec_name .
Address ISREDIT
 
"MACRO"               /* CARM000A EDIT PDI(*)  */
/*********************************************************************/
/* 03/24/2004 JL Nelson Changed to display NO FINDING text.          */
/* 04/23/2004 JL Nelson Added code for DISA standards text.          */
/* 06/15/2004 JL Nelson Added EXIT code.                             */
/* 07/15/2004 JL Nelson Changed DISA Standard to STIG requirement.   */
/* 02/23/2005 JL Nelson Changed constants to variables before        */
/*            rename.                                                */
/* 04/08/2005 JL Nelson Made RACF0300 a Manual Review per Charles.   */
/* 04/18/2005 JL Nelson Added TEST(MOD) to use input test file.      */
/* 06/03/2005 JL Nelson Changed STIG requirement to DISA             */
/*            recommendation.                                        */
/* 06/03/2005 JL Nelson Suppress TEXT not found msgs for FSO         */
/*            auditors.                                              */
/* 06/03/2005 JL Nelson Suppress recommendation msgs for FSO         */
/*            auditors.                                              */
/* 06/06/2005 JL Nelson Changed checks for RACF0360, 440, 470        */
/*            and 480.                                               */
/* 06/09/2005 JL Nelson Pass MAXCC in ZISPFRC variable.              */
/* 06/30/2005 JL Nelson Modified check for RACF0300 when NOERASE.    */
/* 07/08/2005 JL Nelson Changed RACF0555 to RACF0330 per Charles.    */
/* 07/25/2005 JL Nelson Added SETROPTS to RACF0300 per Charles.      */
/* 03/07/2006 JL Nelson Made changes to avoid abend 920/932.         */
/* 06/28/2007 CL Fenton Made changes in evaluation of data.          */
/* 07/09/2007 CL Fenton Resolved several rc 20 error on ISREDIT      */
/*            cmds.  Changed evaluation of RACF0300 to review        */
/*            CLASS.                                                 */
/* 08/07/2007 CL Fenton Corrected RACF0300 Classified settings       */
/*            check.                                                 */
/* 07/16/2009 CL Fenton Changed analysis on password rule            */
/*            RACF0460 to include MIXEDCASE and rules with mixed     */
/*            numeric and a national character.                      */
/* 10/09/2009 CL Fenton Changed analysis on password revoke          */
/*            setting.                                               */
/* 03/15/2011 CL Fenton Chgd RACF0360 test from 35 to 30 days.       */
/* 05/25/2011 CL Fenton Reverted RACF0360 test from 30 to 35 days.   */
/* 12/21/2012 CL Fenton Added RACF0445 for PASSWORD(MINCHANGE).      */
/* 09/24/2013 CL Fenton Chgd RACF0300 for All systems to specify     */
/*            ERASE(ALL), STS-003180.                                */
/* 01/30/2015 CL Fenton Chgd RACF0460 to bypass evaluation until     */
/*            able to verify new configuration settings within       */
/*            REXX using MODIFY AXR command, STS-004529.             */
/* 04/10/2015 CL Fenton Added eval of PASSWORD settings for          */
/*            RACF0462.  Evaluation includes ensuring RACF           */
/*            security exit (ICHPWX01) is available, RACF System     */
/*            REXX (IRRPWREX) is used, as well as settings for       */
/*            variables that are set in the RACF System REXX,        */
/*            STS-009990.                                            */
/* 07/21/2017 CL Fenton Added automation for ZUSSR050 to evaluate    */
/*            BPX.UNIQUE.USER resource definition, STS-017964.       */
/* 05/22/2018 CL Fenton Added "Not Reviewed" to RACF0300 and         */
/*            RACF0480 for vuls that require additional analysis,    */
/*            STS-019713.                                            */
/* 08/07/2019 CL Fenton Converted script from CLIST to REXX.         */
/* 07/02/2021 CL Fenton Chgs to remove automation for RACF0280,      */
/*            RACF0330, RACF0370, and RACF0470, STS-026846.          */
/*                                                                   */
/*                                                                   */
/*                                                                   */
/*                                                                   */
/*********************************************************************/
pgmname = "CARM000A 07/02/21"
sysprompt = "OFF"                /* CONTROL NOPROMPT          */
sysflush = "OFF"                 /* CONTROL NOFLUSH           */
sysasis = "ON"                   /* CONTROL ASIS - caps off   */
return_code = 0
maxcc = 0
zerrsm = ""
Address ISPEXEC "CONTROL NONDISPL ENTER"
Address ISPEXEC "CONTROL ERRORS RETURN"
return_code = 0   /* SET RETURN CODE TO 0 */
 
/*********************************************************************/
/* This EDIT macro provides the finding details for RACF SETROPTS.   */
/*********************************************************************/
/*******************************************/
/* VARIABLES ARE PASSED TO THIS MACRO      */
/* CONSLIST                                */
/* COMLIST                                 */
/* SYMLIST                                 */
/* TERMMSGS                                */
/*******************************************/
return_code = 0
Address ISPEXEC "VGET (CONSLIST COMLIST SYMLIST TERMMSGS FINDRC",
  "PDITEXT DISATXT FINDTXT8 ACPVERS TYPERUN) ASIS"
rm0avget = 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 "FINDRC/"findrc
  Say pgmname "PDITEXT/"pditext "DISATXT/"disatxt,
    "FINDTXT8/"findtxt8 "ACPVERS/"acpvers "TYPERUN/"typerun
  return_code = return_code + 16
  SIGNAL ERR_EXIT
  end
 
If CONSLIST = "ON" | COMLIST = "ON" | SYMLIST = "ON",
  then Trace r
 
/*******************************************/
/* TURN ON MESSAGES                        */
/*******************************************/
syssymlist = symlist           /* CONTROL SYMLIST/NOSYMLIST */
sysconlist = conslist          /* CONTROL CONLIST/NOCONLIST */
syslist = comlist              /* CONTROL LIST/NOLIST       */
sysmsg = termmsgs              /* CONTROL MSG/NOMSG         */
/*******************************************/
/* MAIN PROCESS                            */
/*******************************************/
row = 0
"(PDINUM) = MEMBER"
"CAPS = OFF"
"STATS = OFF"
"(ROW) = LINENUM .ZLAST"
If row > 0 then,
  "DELETE .ZFIRST .ZLAST"
return_code = 0
xf = pos("#",pditext) + 1
xl = pos("@",pditext,xf) - 1
parse var pditext pditext1 "#" pditext2 "@"
If xf = 1 then,
  SIGNAL NOT_FOUND
If left(pditext1,1) <> 1 then do
  If findrc = 0 then,
    SIGNAL NOT_A_FINDING
  SIGNAL A_FINDING
  end
 
 
ADDITIONAL_CHK:
return_code = 0
 
If pdinum <> "RACF0420" &,
   pdinum <> "RACF0520" &,
   pdinum <> "RACF0560" then,
  SIGNAL BYPASS_RACF0420
 
If pdinum = "RACF0420" then do
  o1 = pos("OPERAUDIT ",pditext2)
  If o1 = 0 then,
    SIGNAL NOT_FOUND
  Else,
    o2 = pos(" ",pditext2,o1)
  end
 
If pdinum = "RACF0520" then do
  o1 = pos("SAUDIT ",pditext2)
  If o1 = 0 then,
    SIGNAL NOT_FOUND
  Else,
    o2 = pos(" ",pditext2,o1)
  end
 
If pdinum = "RACF0560" then do
  o1 = pos("WHEN(PROGRAM",pditext2)
  If o1 = 0 then,
    SIGNAL NOT_FOUND
  Else,
    o2 = pos(") ",pditext2,o1) + 1
  end
 
If o2 < o1 then,
  o2 = length(pditext2)
parse var pditext2 pditext2a +12 . =(o1) pditext2b =(o2) .
pditext2 = pditext2a pditext2b
xl = length(pditext)
If findrc = 0 then,
  SIGNAL NOT_A_FINDING
SIGNAL A_FINDING
 
 
BYPASS_RACF0420:
return_code = 0
If pdinum <> "RACF0300" then,
  SIGNAL BYPASS_RACF0300
ac = "Not Reviewed"
"FIND FIRST '"ac"'"
If return_code <> 0 then,
  "LINE_AFTER .ZFIRST = DATALINE (AC)"
SIGNAL A_FINDING
 
 
BYPASS_RACF0300:
return_code = 0
If pdinum <> "RACF0360" then,
  SIGNAL BYPASS_RACF0360
If pos(" NOT ",pditext2) > 0 then,
  SIGNAL A_FINDING
x = pos(" DAYS",pditext2)
If x > 3 then do
  parse var pditext2 days " DAYS." .
  days = right(days,3)
  end
Else,
  days = 0
/* chgd to reflect range of 1 to 35 */
If days > 0 & days <= 35 then,
  SIGNAL NOT_A_FINDING
SIGNAL A_FINDING
 
 
BYPASS_RACF0360:
return_code = 0
If pdinum <> "RACF0430" then,
  SIGNAL BYPASS_RACF0430
x = pos(" GENERATIONS",pditext2)
If x > 3 then,
  parse var pditext2 cnt " GENERATIONS" .
Else,
  cnt = 0
/* chgd to reflect 10 or more */
If cnt >= 10 then,
  SIGNAL NOT_A_FINDING
SIGNAL A_FINDING
 
 
BYPASS_RACF0430:
return_code = 0
If pdinum <> "RACF0440" then,
  SIGNAL BYPASS_RACF0440
x = pos(" DAYS",pditext2)
If x > 3 then do
  parse var pditext2 days " DAYS." .
  days = right(days,3)
  end
Else,
  days = 0
/* chgd from 90 to 60 by DoD policy */
If days >= 1 & days <= 60 then,
  SIGNAL NOT_A_FINDING
SIGNAL A_FINDING
 
 
BYPASS_RACF0440:
return_code = 0
If pdinum <> "RACF0445" then,
  SIGNAL BYPASS_RACF0445
x = pos(" DAYS",pditext2)
If x > 3 then do
  parse var pditext2 days " DAYS." .
  days = right(days,3)
  end
Else,
  days = 0
If days >= 1 & days < 60 then,
  SIGNAL NOT_A_FINDING
SIGNAL A_FINDING
 
 
BYPASS_RACF0445:
return_code = 0
If pdinum <> "RACF0450" then,
  SIGNAL BYPASS_RACF0450
parse var pditext2 cnt " CONSECUTIVE" .
cnt = right(cnt,3)
If cnt < 3 & cnt > 0 then,
  SIGNAL NOT_A_FINDING
SIGNAL A_FINDING
 
 
BYPASS_RACF0450:
return_code = 0
If pdinum <> "RACF0460" then,
  SIGNAL BYPASS_RACF0460
e0 = pos("MIXED CASE PASSWORD SUPPORT IS IN EFFECT",pditext)
e00 = pos("SPECIAL CHARACTERS" ,pditext)
e01 = pos("SPECIAL CHARACTERS ARE ALLOWED.",pditext)
e1 = pos("LENGTH(8)",pditext)
e2 = pos("LENGTH(8:8)",pditext)
e3 = 0
mix = "$mmmmmmm"
Do X = 1 to 8
  If pos(" "mix" ",pditext2) > 0 then,
    e3 = e3 + 1
  mix = right(mix,1)left(mix,7)
  end
e3 = pos(" xxxxxxxx ",pditext)
If e0 > 0 &,
   e01 > 0 &,
   (e1 > 0 | e2 > 0) &,
   (e3 > 0) then,
  SIGNAL NOT_A_FINDING
If e00 = 0 then do
  ac = "The PTF UA90720 or UA90721 is not applied."
  "LINE_AFTER .ZLAST = DATALINE (AC)"
  SIGNAL DISA_REQ
  end
SIGNAL A_FINDING
 
 
BYPASS_RACF0460:
return_code = 0
If pdinum <> "RACF0462" then,
  SIGNAL BYPASS_RACF0462
x = outtrap("LINE.")
Address TSO "CARC1000 PASSWORD"
reccnt = 0
err_data = ""
ind = "OFF"
VICHPWX01 = ""
VIRRPWREX = ""
Do x = 1 to line.0
  line = strip(line.x,"T")
  If line = "Start of Data" then do
    ind = "ON"
    iterate
    end
  If line = "End of Data" then do
    ind = "OFF"
    iterate
    end
  If ind = "OFF" then,
    iterate
  If left(line,1) <> " " then do
    data = line
    If line = "Start of Data" then do
      ind = "ON"
      iterate
      end
    If line = "End of Data" then do
      ind = "OFF"
      iterate
      end
    a = pos(":",line)
    b = length(line)
    If a > 0 then do
      reccnt = reccnt + 1
      parse var line var ":" val .
      If pos(var,"ICHPWX01 IRRPWREX") > 0 then do
        interpret "V"var "= '"val"'"
        iterate
        end
      Else,
        data = var "=" "'"val"'"
      end
    err_data = err_data""data"#"
    end
  end
e00 = pos("SPECIAL CHARACTERS ",pditext)
 
Select
  When e00 = 0 then do
    ac = "The PTF UA90720 or UA90721 is not applied."
    xf = 0
    end
  When vichpwx01 = "NO" then do
    ac = "The ICHPWX01 RACF security exit is not installed."
    xf = 0
    end
  When virrpwrex = "NO" then do
    ac = "The IRRPWREX System REXX is not available."
    xf = 0
    end
  Otherwise nop
  end
 
If e00 = 0 |,
   vichpwx01 = "NO" |,
   virrpwrex = "NO" then do
  "LINE_AFTER .ZLAST = DATALINE (AC)"
  SIGNAL DISA_REQ
  end
 
If err_data = " " then,
  SIGNAL NOT_A_FINDING
pditext2 = err_data
SIGNAL A_FINDING
 
 
BYPASS_RACF0462:
return_code = 0
If pdinum <> "RACF0480" then,
  SIGNAL BYPASS_RACF0480
If pos("FAIL OPTION IS IN EFFECT",pditext) > 0 then,
  SIGNAL NOT_A_FINDING
If pos("PROTECT-ALL WARNING",pditext) > 0 then do
  ac = "Not Reviewed"
  "FIND FIRST '"ac"'"
  If "RETURN_CODE" <> 0 then,
    "LINE_AFTER .ZFIRST = DATALINE (AC)"
  SIGNAL NOT_A_FINDING
  end
SIGNAL A_FINDING
 
 
BYPASS_RACF0480:
return_code = 0
If pdinum <> "RACF0500" then,
  SIGNAL BYPASS_RACF0500
If findrc = 0 then,
  SIGNAL NOT_A_FINDING
SIGNAL A_FINDING
 
 
BYPASS_RACF0500:
return_code = 0
If pdinum <> "ZUSSR050" then,
  SIGNAL BYPASS_ZUSSR050
Address ISPEXEC "VGET (CLASS) ASIS"
If class = 2 then,
  SIGNAL NOT_APPLICABLE
x = outtrap("LINE.")
Address TSO "RLIST FACILITY BPX.UNIQUE.USER NOGENERIC"
lncnt = line.0
If return_code > 0 then do
  pditext = pditext1"#BPX.UNIQUE.USER is not defined.@"
  pditext2 = "BPX.UNIQUE.USER is not defined.#"
  xl = pos("@",pditext,xf) - 1
  SIGNAL NOT_A_FINDING
  end
pditext = pditext1"#BPX.UNIQUE.USER specifies NONE in the",
  "APPLICATION DATA field.@"
pditext2 = "BPX.UNIQUE.USER specifies NONE in the",
  "APPLICATION DATA field.#"
xl = pos("@",pditext,xf) - 1
 
Do X = 1 to lncnt
  line = strip(line.x,"T")
  Say pgmname line
  If line = "APPLICATION DATA" then do
    x = x + 2
    line = strip(line.x,"T")
    appldata = line
    x = lncnt
    end
  end
If appldata = "NONE" then,
  SIGNAL NOT_A_FINDING
 
ac = "The BPX.UNIQUE.USER resource is improperly defined:"
"LINE_AFTER .ZLAST = DATALINE (AC)"
"LINE_AFTER .ZLAST = DATALINE ' '"
ac = "     "appldata" is specified in the APPLICATION DATA field."
"LINE_AFTER .ZLAST = DATALINE (AC)"
 
 
BYPASS_ZUSSR050:
SIGNAL END_EDIT
 
 
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
rm00arc = return_code
Address ISPEXEC "VPUT (RM0AVGET RM00ARC) ASIS"
"SAVE"
"END"
Exit (0)
 
 
NOT_APPLICABLE:
ac = "Not Applicable"
"LINE_AFTER .ZLAST = DATALINE (AC)"
"LINE_AFTER .ZLAST = DATALINE ' '"
ac = "     RACF Version" acpvers
"LINE_AFTER .ZLAST = DATALINE (AC)"
SIGNAL DISA_REQ
 
 
A_FINDING:
return_code = 0
If pdinum = "RACF0462" then,
  ac = "The following variable value is improperly set:"
Else,
  ac = "The following SETROPTS value is improperly set:"
"LINE_AFTER .ZLAST = DATALINE (AC)"
"LINE_AFTER .ZLAST = DATALINE ' '"
If xf > 4 then do
  ac = "     "substr(pditext1,2)
  "LINE_AFTER .ZLAST = DATALINE (AC)"
  end
If xf > 0 & xf <= xl then do
  do until pditext2 = ""
    if left(pditext2,11) = "SPECIAL = '" then do
      parse var pditext2 pditext2a "'#" pditext2
      pditext2a = pditext2a"'"
      end
    Else,
      parse var pditext2 pditext2a "#" pditext2
    ac = "          "pditext2a
    "LINE_AFTER .ZLAST = DATALINE (AC)"
    end
  end
 
 
DISA_REQ:
return_code = 0
If typerun <> "SRRAUDIT" then,
  SIGNAL END_EDIT
"LINE_AFTER .ZLAST = DATALINE ' '"
disatxt = disatxt "#"
do until disatxt = ""
  parse disatxt ac "#" disatxt
  ac = "DISA recommendation:" ac
  "LINE_AFTER .ZLAST = DATALINE (AC)"
  end
SIGNAL END_EDIT
 
 
NOT_FOUND:
ac = "The following SETROPTS value is improperly set:"
"LINE_AFTER .ZLAST = DATALINE (AC)"
"LINE_AFTER .ZLAST = DATALINE ' '"
ac = "     "substr(pditext1,2)" is not defined."
"LINE_AFTER .ZLAST = DATALINE (AC)"
"LINE_AFTER .ZLAST = DATALINE ' '"
do until pos("#",findtxt8) = 0
  parse var findtxt8 findtxt81 "#" findtxt82
  if pos(".ZCSR",findtxt82) > 0 then,
    parse var findtxt82 findtxt82 ".ZCSR" .
  findtxt81 = strip(strip(findtxt81,"B","'"),"B")
  findtxt8 = findtxt81 findtxt82
  end
do until pos("'",findtxt8) = 0
  parse var findtxt8 findtxt81 "'" findtxt82
  findtxt81 = strip(strip(findtxt81,"B","'"),"B")
  findtxt8 = findtxt81""findtxt82
  end
findtxt8 = strip(findtxt8,"T")
if pos("(",findtxt8) > 0 &,
   right(findtxt8,1) <> ")" then,
  findtxt8 = findtxt8")"
ac = "     "findtxt8 "- Text not found"
"LINE_AFTER .ZLAST = DATALINE (AC)"
SIGNAL DISA_REQ
 
 
NOT_A_FINDING:
return_code = 0
ac = "Not a Finding"
"LINE_AFTER .ZLAST = DATALINE (AC)"
"LINE_AFTER .ZLAST = DATALINE ' '"
If xf > 0 & xf <= xl then do
  do until pditext2 = ""
    parse var pditext2 pditext2a "#" pditext2
    ac = "     "pditext2a
    "LINE_AFTER .ZLAST = DATALINE (AC)"
    end
  end
SIGNAL END_EDIT
 
 
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":" ERRORTEXT(rc)
  say SOURCELINE(sigl)
  end
if return_code > maxcc then
  maxcc = return_code
return
 
 
substrc: Procedure
 If arg(3) = '' then do
     s = Arg(1)
     l = 1
     v = arg(2)
     End
   Else do
     s = arg(1)
     l = arg(2)-arg(1)+1
     v = arg(3)
     End
  Return substr(v,s,l)
 
sysoutline: /*Procedure*/
  sysouttrap_Index = arg(1)
  Interpret 'sysouttrap_Result = 'OutTrap()sysouttrap_Index
  Return sysouttrap_Result
 
