/* 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