/*REXX*/ /* */ /* AUTHOR: Charles Fenton */ /* */ /**************************************************************/ /* ITEM: CNTL(CACC0010) */ /* FUNCTION: REXX for OS/390 UNIX System Services */ /* data collection */ /* */ /* NOTES: - This member contains UNIX file names. */ /* - It MUST stay in mixed case. */ /* - It MUST NOT be numbered. */ /*********************************************************************/ /* Change summary: */ /* 07/07/2000 DCM Start */ /* 11/19/2009 CL Fenton Changes to allow for use of BPXWUNIX. */ /* 04/24/2012 CL Fenton initial creation of script copied from */ /* USSICOL1, CSD-AR003400262. */ /* 05/21/2015 CL Fenton Changed includes test for CSFTP, CSTCP, */ /* and WAS to stream line process, STS-008182. */ /* 08/11/2016 CL Fenton Cleaned up several unneccessary entries. */ /* 05/04/2018 CL Fenton Changed process to work from users HOME */ /* directory. If blank will use /tmp/(username) as */ /* directory, STS-019498. */ /* 02/31/2019 CL Fenton Changes to initialize CWD variable, */ /* STS-021618. */ /* 09/25/2019 CL Fenton Changes to check the value of CWD and the */ /* RETVAL from the getcwd commands to determine if the */ /* /tmp directory is to be used, STS-023237 and */ /* STS-023242. */ /* 11/08/2019 CL Fenton Added automation for IUTN0010 and IUTN0020, */ /* STS-023415 and STS-023417. */ /* 03/29/2021 CL Fenton Added evaluation for sntpd PDI ZUSS0037 for */ /* ACF2-OS-000150, RACF-OS-000190, and TSS0-OS-000280, */ /* STS-026250. */ /* 11/08/2022 CL Fenton Added automation for PDI ZUSS0015 for */ /* ACF2-US-000020, RACF-US-000050, and TSS0-US-000150, */ /* STS-029124. */ /* 11/10/2022 CL Fenton Added automation for PDI ZUSS0038 for */ /* ACF2-OS-000160, RACF-OS-000180, and TSS0-OS-000270, */ /* STS-029112. */ /* 02/22/2023 CL Fenton Added automation for PDIs ZSSH0010, */ /* ZSSH0020, ZSSH0030, ZSSH0040, and ZSSH0050 for */ /* ACF2-SH-000010, RACF-SH-000010, TSS0-SS-000010, */ /* ACF2-SH-000030, RACF-SH-000040, TSS0-SS-000040, */ /* ACF2-SH-000040, RACF-SH-000050, TSS0-SH-000030, */ /* ACF2-SH-000050, RACF-SH-000020, TSS0-SH-000020, */ /* ACF2-OS-000330, RACF-SH-000060, and TSS0-ES-000100, */ /* STS-029286, STS-029287, STS-029288, STS-029289, and */ /* STS-029334. */ /* 01/22/2024 CL Fenton Added automation for IUTN0020 for */ /* ACF2-UT-000050, RACF-UT-000050, and TSS0-UT-000050, */ /* SCTASK0074636. */ /* 01/22/2024 CL Fenton Added automation for IUTN0021 for */ /* ACF2-UT-000040, RACF-UT-000040, and TSS0-UT-000040, */ /* SCTASK0074631. */ /* 06/05/2024 CL Fenton Added automation for ZUSS0014 for */ /* ACF2-US-000180, RACF-US-000180, and TSS0-US-000180, */ /* SCTASK0133769. */ /* 06/05/2024 CL Fenton Added automation for ZUSS0013 for */ /* ACF2-US-000150, RACF-US-000170, and TSS0-US-000010, */ /* SCTASK0133761. */ /* */ /* */ /* */ /* */ /*********************************************************************/ /* Setup variables for copying report files */ /* */ /* PARSE UPPER ARG VDSNNODE . */ /*********************************************************************/ PGMNAME = 'CACC0010 01/22/24' TERMMSGS = 'OFF' COMLIST = 'OFF' CONSLIST = 'OFF' SYMLIST = 'OFF' TERMPRO = 'OFF' lc = 'abcdefghijklmnopqrstuvwxyz' uc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' username = translate(userid(),lc,uc) Arg OPTION OPTION = translate(OPTION,'=;','()') interpret OPTION if TRACE = 'ON' then do TERMMSGS = 'ON' COMLIST = 'ON' CONSLIST = 'ON' SYMLIST = 'ON' TERMPRO = 'ON' end Address ISPEXEC "CONTROL NONDISPL ENTER" "CONTROL ERRORS RETURN" "VPUT (CONSLIST COMLIST SYMLIST TERMPRO TERMMSGS)" If CONSLIST = ON | COMLIST = ON | SYMLIST = ON | TRACE = ON , then Trace r "SELECT CMD(CACC1000 ACP)" Address TSO pdi = '' cwd = '' cwdrc = 0 Numeric digits 10 /* dflt of 9 not enough */ Arg OPTION OPTION = translate(OPTION,'=;','()') interpret OPTION call syscalls 'ON' say PGMNAME "syscalls" rc address syscall "getlogin lid" say PGMNAME "getlogin" lid rc RETVAL ERRNO ERRNOJR address syscall "getcwd cwd" say PGMNAME "getcwd" cwd rc RETVAL ERRNO ERRNOJR if retval = -1 or cwd = "/" then do say PGMNAME "Either" lid "has a HOME of Root (/) or the", "/u/"username "directory is not defined to Unix." set cwdrc = -1 end address syscall "getuid" say PGMNAME "getuid" rc RETVAL ERRNO ERRNOJR uid = RETVAL address syscall "getgid" say PGMNAME "getgid" rc RETVAL ERRNO ERRNOJR gid = RETVAL address syscall "geteuid" say PGMNAME "geteuid" rc RETVAL ERRNO ERRNOJR euid = RETVAL address syscall "getegid" say PGMNAME "getegid" rc RETVAL ERRNO ERRNOJR egid = RETVAL uidsu = "" gidsu = "" if uid <> 0 then do address syscall "setuid 0" say PGMNAME "setuid" rc RETVAL ERRNO ERRNOJR if retval <> -1 then do address syscall "getuid" say PGMNAME "getuid" rc RETVAL ERRNO ERRNOJR uidsu = RETVAL address syscall "getgid" say PGMNAME "getgid" rc RETVAL ERRNO ERRNOJR gidsu = RETVAL cwdsu = "" address syscall "getcwd cwdsu" say PGMNAME "getcwd" cwdsu rc RETVAL ERRNO ERRNOJR if retval = -1 or cwdsu = "/" then do say PGMNAME "Either" lid "has a HOME of Root (/) or the", "u/"username "directory is not defined to Unix." set cwdrc = -1 end end end X = LISTDSI(USSCMDS FILE) VDSNFULL = SYSDSNAME Address ISPEXEC "lminit dataid(dialog) ddname(dialog)" lminit_dialog = RC "lminit dataid(pdidd) ddname(pdidd)" lminit_pdidd = RC "lmopen dataid("dialog")" lmopen_dialog = RC "lmopen dataid("pdidd") option(output)" lmopen_pdidd = RC /*VHFSFULL = "/tmp/fso_srrmvs/usscmds_rpt/" address syscall "lstat (VHFSFULL) dir." say pgmname "lstat" dir.0 rc RETVAL ERRNO ERRNOJR say pgmname "lstat st_uid" dir.st_uid say pgmname "lstat st_type" dir.st_type if uid <> 0 & uidsu <> 0 & uid <> dir.st_uid then , VHFSPART = cwd else , VHFSPART = "/tmp"*/. if cwdrc = 0 then, VHFSPART = cwd else , VHFSPART = "/tmp/"username address syscall "opendir "VHFSPART say pgmname "opendir" rc RETVAL ERRNO ERRNOJR if RETVAL = -1 then , address syscall "mkdir (VHFSPART) 0750" address syscall "closedir "RETVAL say pgmname "closedir" rc RETVAL ERRNO ERRNOJR address syscall "lstat (VHFSPART) dir." /*say pgmname "lstat" dir.0 rc RETVAL ERRNO ERRNOJR say pgmname "lstat st_uid" dir.st_uid say pgmname "lstat st_type" dir.st_type*/ VHFSFULL = VHFSPART"/fso_srrmvs/usscmds_rpt" say pgmname "Home directory set to" VHFSPART"." say pgmname "Work information can be found in directory" VHFSFULL"." /* obtain information from VHFSFULL */ address syscall "opendir "VHFSFULL if retval = 0 then do address syscall 'readdir (VHFSFULL) dir. stem.' do a = 3 to dir.0 file = VHFSFULL"/"dir.a address syscall "unlink (file)" end address syscall "closedir "RETVAL end x = outtrap("out.") test = cacc1010('d omvs,p') x = outtrap(off) auto = "" line = "" do a = 1 to out.0 if word(out.a,1) = "AUTOMNT" then do auto = word(out.a,2) line = out.a leave end end say say pgmname test "auto:"auto "line:"line urc = BPXWUNIX('df -P',,df.,'DD:SYSERR') AUTOMNT = "NONE" do x = 1 to df.0 /*say pgmname df.x*/ if substr(df.x,1,1) = "*" then , AUTOMNT = word(df.x,6) end /* */ /* Allocate HFS file; copy script to it */ /* */ Address TSO cmd=VHFSPART'/fso_srrmvs_usscmds_ksh' /*"OCOPY INDD(MVSENV) OUTDD(STDENV) TEXT CONVERT((BPXFX111))"*/ env.0 = 0 x = outtrap("out.") listalc status x = outtrap(off) do x = 1 to out.0 if pos("MVSENV",out.x) <> 0 then do y = x - 1 DSN="'"strip(out.y)"'" leave end end if SYSDSN(DSN) = "OK" then , "execio * diskr MVSENV (FINIS STEM env." x = env.0 + 1 env.x = "HOME="VHFSPART say pgmname "HOME="VHFSPART env.0 = x x = env.0 + 1 env.x = "AUTOMNT="AUTOMNT say pgmname "AUTOMNT="AUTOMNT env.0 = x typeruns = "CSFTP CSTCP WAS" y = "Y" n = "N" do until typeruns = "" parse var typeruns TYPERUN typeruns TYPERUN = left(TYPERUN,8) rectype = "0" Call collect_rec OPTION = strip(TYPERUN)||'='||ind x = env.0 + 1 env.x = OPTION say pgmname OPTION env.0 = x interpret OPTION end /*say pgmname "CSFTP:"csftp "CSTCP:"cstcp "WAS:"was*/ DO x = 1 to env.0 env.x = strip(env.x) /*say pgmname 'env' x env.x*/ end /* */ "ALLOCATE FILE(HFS01) PATH('"VHFSPART"/fso_srrmvs_usscmds_ksh') ", "PATHDISP(KEEP,DELETE) ", "PATHOPTS(OWRONLY,OCREAT) ", "PATHMODE(SIRWXU)" say pgmname "ALLOCATE HFS01" rc "OCOPY INDD(MVS01) OUTDD(HFS01) TEXT CONVERT((BPXFX111))" say pgmname "OCOPY MVS01 to HFS01" rc "FREE FILE(HFS01)" /* */ /* Allocate Shell STDIN, STDOUT; execute script; free files */ /* */ "ALLOCATE FILE(STDIN) PATH('"VHFSPART"/fso_srrmvs_usscmds_ksh') ", "PATHDISP(DELETE,DELETE) ", "PATHOPTS(ORDONLY)" urc = BPXWUNIX('sh -L' cmd,,'DD:SYSMSG','DD:SYSERR',env.) say pgmname "BPXWUNIX" rc urc "FREE FILE(STDIN)" /* */ /* Copy HFS report files to PDS */ /* */ x = outtrap('err.') VRPT = "zssh0050" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" VRPT = "ps" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call process_ps VRPT = "eautom" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call process_eautom VRPT = "einetd" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call process_inetd VRPT = "eprof" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call Process_eprof VRPT = "erc" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" VRPT = "eserv" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" VRPT = "estepll" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" VRPT = "owdir" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" VRPT = "sdperm" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" pdi = "zuss0034" call process_permission_pdi VRPT = "sfperm" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" pdi = "zuss0035" call process_permission_pdi if CSTCP = "Y" then do VRPT = "itcp0040" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call process_permission_pdi end VRPT = "iutn0030" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" VRPT = "iutn0040" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call process_permission_pdi if CSFTP = "Y" then do VRPT = "iftp0050" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" /*call process_permission_pdi*/ VRPT = "iftp0070" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call process_permission_pdi end VRPT = "islg0030" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call process_permission_pdi VRPT = "zuss0037" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" call process_permission_pdi /* */ /* Allocate HFS file; copy script to it */ /* */ if WAS = "N" then signal bypass_was "ALLOCATE FILE(HFS01) PATH('"VHFSPART"/fso_srrmvs_usscmds_ksh') ", "PATHDISP(KEEP,DELETE) ", "PATHOPTS(OWRONLY,OCREAT) ", "PATHMODE(SIRWXU)" "OCOPY INDD(MVS02) OUTDD(HFS01) TEXT CONVERT((BPXFX111))" "FREE FILE(HFS01)" /* */ /* Allocate Shell STDIN, STDOUT; execute script; free files */ /* */ "ALLOCATE FILE(STDIN) PATH('"VHFSPART"/fso_srrmvs_usscmds_ksh') ", "PATHDISP(DELETE,DELETE) ", "PATHOPTS(ORDONLY)" urc = BPXWUNIX('sh -L' cmd,,'DD:SYSMSG','DD:SYSERR',env.) say pgmname "BPXWUNIX" rc urc "FREE FILE(STDIN)" /* */ /* Copy HFS report files to PDS */ /* */ VRPT = "ihshfsob" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" VRPT = "washfsob" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" VRPT = "ahttpd" "OGET '"VHFSFULL'/'VRPT"' '"VDSNFULL"("VRPT")' TEXT CONVERT((BPXFX111))" bypass_was: call syscalls 'OFF' Address ISPEXEC "lmclose dataid("dialog")" lmclose_dialog = RC "lmclose dataid("pdidd")" lmclose_pdidd = RC "lmfree dataid("dialog")" lmfree_dialog = RC "lmfree dataid("pdidd")" lmfree_pdidd = RC /* */ If TERMMSGS = 'ON' then do say say '===============================================================' say PGMNAME 'LMINIT_DIALOG ' lminit_dialog say PGMNAME 'LMINIT_PDIDD ' lminit_pdidd say PGMNAME 'LMOPEN_DIALOG ' lmopen_dialog say PGMNAME 'LMOPEN_PDIDD ' lmopen_pdidd say PGMNAME 'LMCLOSE_DIALOG ' lmclose_dialog say PGMNAME 'LMCLOSE_PDIDD ' lmclose_pdidd say PGMNAME 'LMFREE_DIALOG ' lmfree_dialog say PGMNAME 'LMFREE_PDIDD ' lmfree_pdidd say '===============================================================' end Exit 0 /*********************************************************************/ /* Start of sub-routines */ /*********************************************************************/ process_permission_pdi: Address ISPEXEC if pdi = "" then pdi = VRPT upper pdi pb = 0 uab = 0 f1 = "Permission bits and user audit bits is (are) inappropriate:" f2 = "Permission bits allow inappropriate access." f3 = "User audit bits provide inadequate logging." address tso "alloc fi(input) da('"VDSNFULL"("VRPT")') shr reuse" address tso "execio * diskr input (finis stem out." do a = 1 to out.0 parse var out.a ind 2 sp 5 data /*say pgmname "ind="ind "sp="sp "data="data*/ if ind = "" then iterate if ind = "0" then iterate if ind = "1" then pb = pb + 1 if ind = "2" then uab = uab + 1 if ind = "3" then do pb = pb + 1 uab = uab + 1 end end say PGMNAME 'Processing PDI' pdi'. pb='pb 'uab='uab Address TSO "newstack" if pb = 0 & uab = 0 then queue 'Not a Finding' if pb > 0 | uab > 0 then do queue f1 queue " " end if pb > 0 & uab > 0 then do nr = 1 lp = ") " end else do nr = "" lp = "" end if pb > 0 then do queue nr""lp""f2 queue " " if nr > 0 then nr = nr + 1 do a = 1 to out.0 parse var out.a ind 2 sp 5 data if ind = "1" | ind = "3" then , queue " "data end queue " " end if uab > 0 then do queue nr""lp""f3 queue " " do a = 1 to out.0 parse var out.a ind 2 sp 5 data if ind = "2" | ind = "3" then , queue " "data end queue " " end call process_queued_pdi pdi = "" Address TSO "free fi(input)" return process_eautom: pdi = "ZUSS0013" say PGMNAME 'Processing PDI' pdi'.' eprof_data = "" Address ISPEXEC address tso "alloc fi(input) da('"VDSNFULL"("VRPT")') shr reuse" if RC > 0 | auto = "" then do Address TSO "newstack" queue "Not Applicable" call process_queued_pdi return end address tso "execio * diskr input (finis stem out." maps. = "" mc = 0 mapdata = finding_rc = 0 do a = 1 to out.0 parse var out.a out.a "#" . if word(out.a,1) = "name" &, mapdata <> "" then do mc = mc + 1 maps.mc = mapdata end if word(out.a,1) = "name" then, mapdata = strip(out.a,"B")" @" if wordpos("type",out.a) = 1 |, wordpos("filesystem",out.a) = 1 |, wordpos("mode",out.a) = 1 |, wordpos("duration",out.a) = 1 |, wordpos("delay",out.a) = 1 |, wordpos("setuid",out.a) = 1 |, wordpos("security",out.a) = 1 then, mapdata = mapdata""strip(out.a,"B")" @" end if mapdata <> "" then do mc = mc + 1 maps.mc = mapdata end Address TSO "newstack" if mc = 0 then, queue "Not Applicable" else do x = 1 to mc parse upper var maps.x . "SECURITY" security . parse upper var maps.x . "SETUID" setuid . if security <> "YES" | , setuid <> "NO" then do if finding_rc = 0 then do queue "The following MapName files security parameters are not", "properly defined." queue " " finding_rc = 1 end mapdata = maps.x do until mapdata = "" parse var mapdata line "@" mapdata queue " "line end queue " " end end if finding_rc = 0 then, queue "Not a Finding" call process_queued_pdi return process_eprof: eprof_data = "" Address ISPEXEC address tso "alloc fi(input) da('"VDSNFULL"("VRPT")') shr reuse" address tso "execio * diskr input (finis stem out." do a = 1 to out.0 parse var out.a out.a "#" . if out.a = "" then iterate if wordpos("umask",out.a) > 0 then do eprof_data = eprof_data""out.a"@" iterate end if wordpos("LOGNAME",out.a) > 0 then do eprof_data = eprof_data""out.a"@" iterate end end pdi = "ZUSS0015" say PGMNAME 'Processing PDI' pdi'.' Address TSO "newstack" if eprof_data = "" then, queue "UMASK and LOGNAME are not specified in /etc/profile." else do umask = "" logname = "" do until eprof_data = "" parse var eprof_data data "@" eprof_data if pos("umask",data) > 0 then, parse var data . "umask" umask . if pos("LOGNAME",data) > 0 then, parse var data logname "LOGNAME" . end if umask = "077" &, logname = "readonly" then, queue "Not a Finding" else do queue "The /etc/profile file does not specify the following", "parameters." queue " " if umask = "" then, queue " umask 077 is not specified." else, if umask <> "077" then, queue " umask" umask "is specified." if logname = "" then, queue " readonly LOGNAME is not specified." else, if logname <> "readonly" then, queue " "logname "LOGNAME is specified." end end call process_queued_pdi return process_ps: sntpd_data = "" sshd_data = "" Address ISPEXEC address tso "alloc fi(input) da('"VDSNFULL"("VRPT")') shr reuse" address tso "execio * diskr input (finis stem out." do a = 1 to out.0 parse var out.a out.a "#" . if out.a = "" then iterate if pos("sntp",out.a) > 0 |, pos("SNTP",out.a) > 0 then do sntpd_data = sntpd_data""strip(out.a,"B")"@" end if pos("ssh",out.a) > 0 |, pos("SSH",out.a) > 0 then do sshd_data = sshd_data""strip(out.a,"B")"@" end end pdi = "ZUSS0038" say PGMNAME 'Processing PDI' pdi'.' Address TSO "newstack" if sntpd_data = "" then, queue "SNTPD daemon is not active on the system." else do queue "Not a Finding" queue " " do until sntpd_data = "" parse var sntpd_data data "@" sntpd_data queue " " data end end call process_queued_pdi Address TSO "delstack" if sshd_data = "" then do pdilist = "ZSSH0010 ZSSH0020 ZSSH0030 ZSSH0040" do x = 1 to words(pdilist) queue "Not a Finding" queue " " queue "The SSHD daemon is not active." queue " " pdi = word(pdilist,x) call process_queued_pdi end end Else do call process_sshd_pdis end Address TSO "delstack" pdi = "ZSSH0050" address tso "alloc fi(input) da('"VDSNFULL"("pdi")') shr reuse" address tso "execio * diskr input (finis stem out." if out.0 = 0 then do queue "Not a Finding" queue " " end Else do queue "There are keys or certificates identified in Unix files." queue " " do x = 1 to out.0 queue " " out.x end queue " " end call process_queued_pdi return process_sshd_pdis: zssh0010_protocol = "Protocol statement is not specified." zssh0020_ciphers = "Ciphers statement is not specified." zssh0020_macs = "Macs statement is not specified." zssh0020_fips = "FIPSMODE statement is not specified." zssh0020_cipherssrc = "CiphersSource statement is not specified." zssh0020_macssrc = "MACsSource statement is not specified." zssh0030_banner = "Banner statement is not specified." zssh0040_srvrsmf = "ServerSMF statement is not specified." testdata = sshd_data do until testdata = "" parse var testdata data "@" testdata ufile = word(data,words(data)) address syscall "readfile (ufile) test." say say pgmname ufile "usable contents:" do xx = 1 to test.0 parse var test.xx test.xx "#" . test.xx = strip(test.xx,"B") if test.xx = "" then iterate parse upper var test.xx key . say pgmname test.xx if key = "PROTOCOL" then, zssh0010_protocol = test.xx if key = "CIPHERS" then do zssh0020_ciphers = test.xx if right(zssh0020_ciphers,1) = "," then, do until right(zssh0020_ciphers,1) <> "," xx = xx + 1 zssh0020_ciphers = zssh0020_ciphers""test.xx end end if key = "MACS" then do zssh0020_macs = test.xx if right(zssh0020_macs,1) = "," then, do until right(zssh0020_macs,1) <> "," xx = xx + 1 zssh0020_macs = zssh0020_macs""test.xx end end if key = "BANNER" then, zssh0030_banner = test.xx end end ufile = "/etc/ssh/zos_sshd_config" address syscall "readfile (ufile) test." say say pgmname ufile "usable contents:" do xx = 1 to test.0 parse var test.xx test.xx "#" . test.xx = strip(test.xx,"B") if test.xx = "" then iterate if pos("=",test.xx) > 0 then, parse upper var test.xx key "=" . else, parse upper var test.xx key . say pgmname test.xx if key = "FIPSMODE" then, zssh0020_fips = test.xx if key = "CIPHERSSOURCE" then, zssh0020_cipherssrc = test.xx if key = "MACSSOURCE" then, zssh0020_macssrc = test.xx if key = "SERVERSMF" then, zssh0040_srvrsmf = test.xx end say if word(zssh0010_protocol,2) = 2 then do queue "Not a Finding" queue " " queue " " zssh0010_protocol queue " " end Else do queue "SSH daemon must be configured to only use the SSHv2 protocol." queue " " queue " " zssh0010_protocol queue " " end pdi = "ZSSH0010" call process_queued_pdi if word(zssh0020_ciphers,1) = "Ciphers" then do ciphers_data = word(zssh0020_ciphers,2) do until ciphers_data = "" parse var ciphers_data tdata "," ciphers_data if pos("aes",tdata) = 1 |, pos("3des",tdata) = 1 then nop else do queue " " zssh0020_ciphers queue " " ciphers_data = "" end end end Else do queue " " zssh0020_ciphers queue " " end if word(zssh0020_macs,1) = "Macs" then do macs_data = word(zssh0020_macs,2) do until macs_data = "" parse var macs_data tdata "," macs_data if pos("hmac-sha",tdata) <> 1 then do queue " " zssh0020_macs queue " " macs_data = "" end end end Else do queue " " zssh0020_macs queue " " end if pos("yes",zssh0020_fips) = 0 then do queue " " zssh0020_fips queue " " end if pos("ICSF",zssh0020_cipherssrc) = 0 then do queue " " zssh0020_cipherssrc queue " " end if pos("ICSF",zssh0020_macssrc) = 0 then do queue " " zssh0020_macssrc queue " " end if queued() = 0 then do queue "Not a Finding" queue " " queue " " zssh0020_ciphers queue " " zssh0020_macs queue " " zssh0020_fips queue " " zssh0020_cipherssrc queue " " zssh0020_macssrc queue " " end else do push " " push "SSH daemon must be configured to only use a FIPS 140-2", "compliant cryptographic algorithm." end pdi = "ZSSH0020" call process_queued_pdi parse upper var zssh0030_banner banner if wordpos("BANNER",banner) > 0 then do ufile = word(zssh0030_banner,words(zssh0030_banner)) address syscall "readfile (ufile) test." say pgmname "Processing" ufile"." queue "Not Reviewed" queue "The" ufile "file does not contain the required notification", "and consent information." queue " " queue " Contents of" ufile "are as follows:" queue " " do xx = 1 to test.0 queue " " test.xx end queue " " end Else do queue zssh0030_banner queue " " end pdi = "ZSSH0030" call process_queued_pdi if word(zssh0040_srvrsmf,2) = "TYPE119_U83" then do queue "Not a Finding" queue " " queue " " zssh0040_srvrsmf queue " " end Else do queue "SSH daemon must be configured to write SMF records for all", "eligible events." queue " " queue " " zssh0040_srvrsmf queue " " end pdi = "ZSSH0040" call process_queued_pdi return process_queued_pdi: say pgmname right(queued(),4) 'records written for' pdi'.' do xx = 1 to queued() parse pull ac "LMPUT DATAID("pdidd") MODE(INVAR) DATALOC(ac)", "DATALEN("length(ac)") MEMBER("pdi")" end "LMMADD DATAID("pdidd") MEMBER("pdi")" if RC = 4 then do "LMMREP DATAID("pdidd") MEMBER("pdi")" if RC <> 0 then, say PGMNAME 'LMMREP_PDIDD =' RC PDI ZERRSM end return process_inetd: inetd_data = "" Address ISPEXEC address tso "alloc fi(input) da('"VDSNFULL"("VRPT")') shr reuse" address tso "execio * diskr input (finis stem out." do a = 1 to out.0 parse var out.a out.a "#" . if out.a = "" then iterate if word(out.a,1) = "otelnet" then do inetd_data = out.a leave end end pdi = "IUTN0010" say PGMNAME 'Processing PDI' pdi'.' Address TSO "newstack" if inetd_data = "" then, queue "Not Applicable" else do if word(inetd_data,5) = "OMVS" |, word(inetd_data,5) = "OMVSKERN" then do queue "Not a Finding" queue " " queue " "word(inetd_data,5) "is specified." end else do queue "The startup user account for the z/OS UNIX Telnet Server", "does not specify OMVS or OMVSKERN." queue " " queue " "word(inetd_data,5) "is specified." end end call process_queued_pdi pdi = "IUTN0020" say PGMNAME 'Processing PDI' pdi'.' Address TSO "newstack" if inetd_data = "" then, queue "Not Applicable" else do login = "" timeout = "" x = wordindex(inetd_data,7) parse var inetd_data . =(x) inetd_parm if pos("-h",inetd_parm) = 0 then do queue "Not a Finding" queue " " queue " "inetd_parm end else do queue "Startup parameters for the z/OS UNIX Telnet Server are", "improperly specified." queue " " queue " "inetd_parm end end call process_queued_pdi pdi = "IUTN0021" say PGMNAME 'Processing PDI' pdi'.' Address TSO "newstack" if inetd_data = "" then, queue "Not Applicable" else do login = "" timeout = "" x = wordindex(inetd_data,7) parse var inetd_data . =(x) inetd_parm parse var inetd_parm . "-D" login . parse var inetd_parm . "-c" timeout . if login = "login" &, timeout <= 900 then do queue "Not a Finding" queue " " queue " "inetd_parm end else do queue "Startup parameters for the z/OS UNIX Telnet Server are", "improperly specified." queue " " queue " "inetd_parm end end call process_queued_pdi pdi = "ZUSS0014" services = "chargen daytime discard echo exec finger shell time", "login smtp timed nameserver systat uucp netstat talk qotd tftp" inetd_data = "" say PGMNAME 'Processing PDI' pdi'.' do a = 1 to out.0 parse var out.a out.a "#" . if out.a = "" then iterate service = word(out.a,1) if wordpos(service,services) > 0 then do inetd_data = inetd_data""out.a"#" leave end end Address TSO "newstack" if inetd_data = "" then, queue "Not a Finding" else do queue "The following restricted network service(s) are specified", "in /etc/inetd.conf." queue " " do until inetd_data = "" parse var inetd_data service "#" inetd_data queue " "service end end call process_queued_pdi pdi = "" Address TSO "free fi(input)" return collect_rec: Address ISPEXEC "lmmfind dataid("dialog") member(products)" lmmfind_dialog = RC TYPERUN = left(TYPERUN,8) RC = 0 recs = do until RC>0 "lmget dataid("dialog") mode(invar) dataloc(data) datalen(lrecl)", "maxlen(80)" if RC = 0 & , pos(TYPERUN' 'rectype,data) = 1 then do parse var data . "0" ind ind = strip(ind) return 0 end /* if RC = 0 & */ end /* until RC>0 */ return 0