Using RACF callable services including from a 64bit bit program

You can use RACF callable services to programatically get and set RACF information, for example to list and display digital certificates, and objects.

There is a C interface to these services. These interfaces are easy to use as long as you are careful with your data types, and get your compile JCL right. You can use 31 and 64 mode programs with these services.

JCL to compile a 64 bit program

Below is the JCL I use for compile programs which use gskit and RACF callable services.

//COLINC5    JOB 1,MSGCLASS=H,COND=(4,LE) 
//S1 JCLLIB ORDER=CBC.SCCNPRC
// SET LOADLIB=COLIN.LOAD
//*OMPILE EXEC PROC=EDCCB,
//COMPILE EXEC PROC=EDCQCB,
// LIBPRFX=CEE,
// CPARM='OPTFILE(DD:SYSOPTF),LSEARCH(/usr/include/)',
// BPARM='SIZE=(900K,124K),RENT,LIST,RMODE=ANY,AMODE=64,AC=1'
//COMPILE.SYSOPTF DD *
...
/*
//COMPILE.SYSIN DD DISP=SHR,DSN=COLIN.C.SOURCE(...)
//BIND.SYSLMOD DD DISP=SHR,DSN=COLIN.LOAD
//BIND.OBJLIB DD DISP=SHR,DSN=COLIN.OBJLIB
//BIND.GSK DD DISP=SHR,DSN=SYS1.SIEALNKE
//BIND.CSS DD DISP=SHR,DSN=SYS1.CSSLIB
//BIND.SYSIN DD *
INCLUDE GSK(GSKCMS64)
INCLUDE GSK(GSKSSL64)
INCLUDE CSS(IRRSDL64)

NAME AMSCHE64(R)

Note the 64 bit specific items

  • PROC=EDCQCB
  • RMODE=ANY,AMODE=64
  • The includes of the GSK*64 stubs
  • The include of the 64 bit RACF callable stub IRRSDL64

The 31 bit equilants are

  • PROC=EDCCB
  • RMODE=ANY,AMODE=31
  • The includes of the GSK*31 stubs: GSKCMS31,GSKSSL
  • The include of the 31 bit RACF callable stub IRRSDL00

The source is specified via //COMPILE.SYSIN

SYSOPTF

For both 64 bit and 31 bit programs

//COMPILE.SYSOPTF DD * 
LIST,SOURCE
aggregate(offsethex) xref
SEARCH(//'COLIN.C.H',//'SYS1.SIEAHDR.H')
TEST
RENT LO
OE
INFO(PAR,USE)
NOMARGINS EXPMAC SHOWINC XREF
LANGLVL(EXTENDED) sscom dll
DEFINE(_ALL_SOURCE)
DEBUG

Skeleton of C program

#pragma linkage(IRRSFA64 ,OS) 

The pragma is needed for the bind operation. It says the module is a z/OS callable service type of module (and not a C program).

#ifdef _LP64 
#include <irrpcomy.h>
#else
#include <irrpcomx.h>
#endif

You need a different copy book for the RACF constants depending on the 31/64 bit mode.

IRRPCOMY contains definitions for 64 bit programs, IRRCOMX is for 31 bit programs.

char * workarea ; 
workarea = (char *) malloc(1024);
int ALET1= 0;
int parmAlet = 0;
int numParms =11;
short function_code = 1;
int ALET2= 0;
int ALET3= 0;
int SAF_RC = 0;
int RACF_RC = 0;
int RACF_RS = 0;

The variables have to be “int”, not “long”, as they are 4 bytes long. With 64 bit program, a long is 8 bytes long. See here for a table about the types and lengths in 31 bit and 64 bit programs. A short is 2 bytes long.

Set up the parameter list 

The macro IRRPCOM? provides header files for some definitions.

For example

char * pSTC = "AZFTOTP1"; 
char area[1000];

struct fact_getf_plist pl;
pl.fact_getf_options = 0;
pl.fact_getf_factor_length = 8;
pl.fact_getf_factor_a = pSTC;
pl.irrpcomy_dummy_34 = 0;
pl.fact_getf_af_length = sizeof(area);
pl.fact_getf_af_a = & area;

where pl is used below.

Call the function

 IRRSFA64( workarea, // WORKAREA 
&ALET1 , // ALET
&SAF_RC, // SAF RC
&ALET2, // ALET
&RACF_RC,// RACF RC
&ALET3 , // ALET
&RACF_RS,// RACF Reason
&numParms,
&parmAlet, //
&function_code,
&pl );

The irrpcomx has a structure definition for the parameter list, but I could not get it to work in these programs, as it passes the address of the data, instead of the data itself.

NO? Migrating an ADCD z/OS release:RACF

This post is a very quick post in response to a question about migrating your RACF data to a different system. I will update it when I have more time.

This is one of a series of posts about migrating to a newer level of ADCD.

This covers RACF.

A typical z/OS migration is to take your existing system and upgrade it. With ADCD the operating system is replaced and you have to move to it, taking your data with you.

You need to think about your RACF definitions, and migrates your specific data into the newer RACF database. This will include userid, profiles, permissions and digital certificates.

Some of the changes are good practice and clean up. For example

Instead of a definition CICSTS55.* in class(STARTED), the profile is CICSTS.*.* in class(STARTED). Using the scripts described in this blog you can update your old system before you move to the new system. 

I have put files into a github repository.

Migrating certificates and keyrings

The JCL EXPCERT runs a rexx exec which create commands to export your certificates, imports them (on the new system), and recreates the keyrings (on the new system).

The exec issues the RACDCERT command to list all the keyrings for a userid, and processes that output.

//IBMCERT  JOB 1,MSGCLASS=H 
// EXPORT SYMLIST=(*)
//ADCDA EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//OUTPUT DD DISP=SHR,DSN=COLIN.MIG.DATA(EXPCERTD)
//IMPORT DD DISP=SHR,DSN=COLIN.MIG.DATA(IMPCERTD)
//RING DD DISP=SHR,DSN=COLIN.MIG.DATA(RINGD)
//SYSEXEC DD DISP=SHR,DSN=USER.Z24C.CLIST
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
%LRING COLIN.CERT.EXPORT START1 PASS4ME4
/*
//S2 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSIN DD DISP=SHR,DSN=COLIN.MIG.DATA(EXPCERTD)
//SYSTSPRT DD SYSOUT=*
/*  

The parameters are

  • the exported certificates high level qualifier. It will create data sets like COLIN.CERT.EXPORT.C14 . Once you have imported the certificates you need to delete these data sets.
  • the userid that owns the keyrings
  • the password for the exported certificates

The output data sets are

OUTPUT: this has data like

RACDCERT EXPORT(LABEL('AdcdShrCA')) -
CERTAUTH DSN('COLIN.CERT.EXPORT.C8')-
FORMAT(PKCS12DER) password('&PASSWORD')

IMPORT: This has data like

RACDCERT ADD('COLIN.CERT.EXPORT.C8') CERTAUTH -
TRUST withlabel('AdcdShrCA') PASSWORD('&PASSWORD')

RING: this has data like

RACDCERT ADDRING(RING) ID(START1)
RACDCERT ID(START1) CONNECT(RING(RING) –
  CERTAUTH DEFAULT usage(PERSONAL ) –
  LABEL(‘AdcdShrCA’) )

Migrating userids and profiles

RACF provides a DBSYNC rexx program to take two unloaded RACF databases and generate the RACF command statements to show the differences and help you convert from one to the other. One file will have “define resource XYZ” another file will have “delete resource XYZ”.

In theory you can just run the appropriate files and merge your old definitions into the new database. I have a lot of junk in my old database and wanted to be more selective as to what I copied across, and understand the differences.

I used the DBSYNC job to create the various files. I changed the DCB to DCB=(RECFM=VB,LRECL=600,BLKSIZE=6400)

The output of ALTFILE1 looks like

/*70:339:286*/ "altgroup PKIGRP   omvs( gid(0000990031))" 
/*75:373:315*/ "altuser ADCDA owner(IBMUSER ) dfltgrp(TEST ) noadsp n....
"noseclabel"

I use ISPF View on the data set, so I do not accidentally change the output.

I run the Rexx exec RACFONEL (in user.*.clist). This creates one line in the file for each logical line, and sorts the file alphabetically. For example

altuser ADCDA owner(IBMUSER  ) dfltgrp(TEST     ) noa..... noseclabel

Depending on what I am doing, I select a subset of the records for example, for my userid and use those records.

The Rexx exec RACSPLIT does the following

  • Cosmetic edits to make fields align – for example change ‘ group’ to ‘group’, changes revoke to resume to make it easier to compare records
  • Splits each line so it fits more into columns 1-80. Sometimes the lines are longer because the definition requires a long string.
  • It appends the records into the save file

Example output

altuser ZWESIUSR owner(IBMUSER  ) - 
dfltgrp(ZWEADMIN ) -
noadsp -
nospecial -
nooperations -
nogrpacc -
name(zzzzz) -
nodata -
noseclabel
altuser ZWESVUSR omvs( uid(0000990016 ) home('/apps/zowe/v10/home/z.....

If I am happy with the output, delete the top records in the file, and save it.

Do the same for the old and new RACF DBSYNC files and then use ISPF edit compare function to show the difference.

Once you know what the difference are you can run the updates for the changes you want to make to your new database.

z/OS health checker – understanding and configuring it

The z/OS Health Checker has many checks for the configuration of your z/OS system and it’s components. For example check for the existence of expired certificates, and z/OS parameters which are not best practice. The checks are configured into Health Checker, and you can have one or more policies which changes these checks. You can make checks inactive if they are not applicable, for example when they refer to a sysplex function, when your system is not in a sysplex.

Some checks are shipped as inactive, but most are active.

There are different sorts of check

  • local – these run in the Health Checker address space
  • remote – these run in other address spaces and report into the Health Checker
  • Rexx – these run in an address space and report to the Health Checker
  • global – these run once in a sysplex

Some of the concepts and commands are not very intuitive (for example the documentation is not very clear on how policy and checks are connected), but on the whole it is pretty easy to understand and use.

There is a policy which allows you to change the operational aspect of individual checks, for example make inactive, or change the description to it provides information specific to your configuration.

You can have multiple policies, so you could have one configuration and policies for different systems (for example different levels of z/OS), or different shifts. 

Within each policy each statement has an identifier (it defaults to a sequence number) or you can give each statement a label using the STATEMENT(…) option. Personally I would have used the term “label” to avoid description like the STATEMENT parameter is used to identify the statement. If you specify a STATEMENT then it makes it easy to find it. A check might report “changed by COLINZFS” or “changed by 17 ” it is easier to find COLINZFS than find the 17th STATEMENT.

When do checks run?

The checks are run when

  • the HSZPROC is started
  • as specified in the configuration (parameter INTERVAL=ONETIME|hhh:mm)
  • when the refresh command is issued, such as F HZSPROC,refresh,check(*,*)

What output do checks provide?

A successful check provides no information on the logs. Each exception writes a few lines to the system log. You can run a print job to get a fuller description include full message text, and operation actions etc. For example one RACF check gave a “one line” entry on syslog, but the print job listed of all digital certificates which had, or were due to expire. The output format is what you typically see in a z/OS messages manual.

You can use the SDSF CK command to display the checks, the status, including when they last ran, and take action on the checks; such as temporarily disable or delete a check.

There are various operator display commands you can issue

A summary of the Health Checker configuration

The commands are described here.

f hzsproc,display,checks

gave me

HZS0203I  16.02.33 HZS INFORMATION                          
POLICY(DEFAULT)
OUTSTANDING EXCEPTIONS: 12
(SEVERITY NONE: 0 LOW: 3 MEDIUM: 8 HIGH: 1)
ELIGIBLE CHECKS: 155 (CURRENTLY RUNNING: 0)
INELIGIBLE CHECKS: 67 DELETED CHECKS: 0
ASID: 0041 LOG STREAM: NOT DEFINED
LOG STREAM WRITES PER HOUR: 1327
LOG STREAM AVERAGE BUFFER SIZE: 2364 BYTES
HZSPDATA DSN: ADCD.S0W1.HZSPDATA
HZSPDATA RECORDS: 828
PARMLIB: AD,CP
ORIGINAL PARMLIB SOURCE: <USER>
OPTIONS: NONE

where

  • members HZSPRMAD and HZSPRMCP were used from the sys1.parmlib concatenation
  • ORIGINAL PARMLIB SOURCE: <USER> the definitions were read from the sys1.parmlib. You can specify PREV, which means use the same as last time – but the use of this is unclear to me.

Display the status of the individual checks

F HZSPROC,DISPLAY,CHECKS                                               
HZS0200I 16.03.07 CHECK SUMMARY 580
CHECK OWNER CHECK NAME STATE STATUS
IBMCS ZOSMIGV2R4PREV_CS_IWQSC_TCPIP IE INACTIVE
IBMCS CSTCP_IWQ_IPSEC_TCPIP AE SUCCESSFUL
IBMCS CSTCP_CINET_PORTRNG_RSV_TCPIP AE EXCEPTION-MED
IBMCS CSTCP_SYSPLEXMON_RECOV_TCPIP AE SUCCESSFUL
...
A - ACTIVE I - INACTIVE
E - ENABLED D - DISABLED
G - GLOBAL CHECK + - CHECK ERROR MESSAGES ISSUED

This shows

  • All of these checks came from the IBMCS (TCPIP) component
  • Check ZOSMIGV2R4PREV_CS_IWQSC_TCPIP is inactive
  • CSTCP_CINET_PORTRNG_RSV_TCPIP has detected a medium level exception
  • State: Indicates whether a check runs at the next specified interval. For example INACTIVE(ENABLED) and ACTIVE(ENABLED)
  • Status: Describes the output of the check when it last ran.
    For example INACTIVE and EXCEPTION-MED

You can display an individual or similar checks.

F HZSPROC,DISPLAY CHECKS,check=(IBMRACF,RACF_I*)
F HZSPROC,DISPLAY CHECKS,check=(IBMRACF,RACF_GRS_RNL)

F HZSPROC,DISPLAY CHECKS,CHECK=(IBMRACF,RACF_I*)                    
HZS0200I 14.41.21 CHECK SUMMARY 812
CHECK OWNER CHECK NAME STATE STATUS
IBMRACF RACF_ICHAUTAB_NONLPA AE SUCCESSFUL
IBMRACF RACF_IBMUSER_REVOKED IE INACTIVE
...

Using F HZSPROC,DISPLAY CHECKS,…DETAIL gives a lot of information about each checks, such as state, status, and last ran.

Display a policy

You can display all the items in a policy, or details about a statement in a policy. A policy is a group of changes you make to checks.  This could be to make a check inactive, or to change the description(reason) to provide more site specific information.


F HZSPROC,DISPLAY,POLICY,STATEMENT=COLINS
HZS0204I 17.29.33 POLICY SUMMARY 988
POLICY(DEFAULT)
STMT NAME TYPE CHECK OWNER CHECK NAME
COLINS UPD IBMRACF RACF_SYSPLEX_COMMUNICATION
F HZSPROC,DISPLAY,POLICY,STATEMENT=COLINS,DETAIL                 
HZS0202I 17.30.16 POLICY DETAIL 992
POLICY(DEFAULT) STATEMENT: COLINS
ORIGIN: HZSPRMUS DATE: 20240120
UPDATE CHECK(IBMRACF,RACF_SYSPLEX_COMMUNICATION)
REASON: Colins - Test/Development env
INACTIVE

Update a policy

You can use the command interface to temporarily update the checks and policy, or you can update the HZSPMxx members.

For example I updated USER.*.PARMLIB(HSZPRMUS) with

ADDREPLACE POLICY STATEMENT(COLINS) 
UPDATE CHECK(IBMRACF,RACF_SYSPLEX_COMMUNICATION)
DATE(20240120)
INACTIVE
REASON('COLIN - Test/Development env')

ADDREPLACE POLICY
UPDATE CHECK(IBMRACF,RACF_PROTECTALL_FAIL)
DATE(20240120)
INACTIVE
REASON('COLIN2- do not want in one person system')

Note:

  • Each update needs and ADDREPLACE POLICY… statement
  • If you do not provide a STATEMENT, a numerical one is generated for you
  • You need a date (see dates in policies). Each check has a default date specified. If you specify a data which is before the default date, the check is not used. I specified the date I changed it to inactive so I have an audit trail!
  • I specified a reason why I made it inactive. This reason is displayed when you display the policy details.

Then used the command

F hzsproc,ADD,PARMLIB=(US,CHECK)

To check the syntax and validity, where US is the suffix of the HZSPRM source (above). I then used

zsproc,ADD,PARMLIB=(US)

To activate the definition.

You can specify which parmlib members are used at startup in the HSZPROC JCL.

How do I check the status of the checks?

In SDSF you can use the CK option to display the checks. There are many columns. The interesting columns (to me) are

  • Name: like RACF_PROTECTALL_FAIL
  • Owner: (what I would call a component) IBMRACF
  • State: Indicates whether a check runs at the next specified interval. For example INACTIVE(ENABLED) and ACTIVE(ENABLED)
  • Status: Describes the output of the check when it last ran.
    For example INACTIVE and EXCEPTION-MEDIUM
  • Run count: such as 9
  • ModifiedBy: such as STMT(37) in the policy. This allows you to find your update statement. By specifying you STATEMENT(…) makes it easier to use SRCHFOR to find the member with the update.
  • Reason: the description from the check such as PROTECTALL(FAIL) should be enabled.
  • Update reason: any update from the policy statement, for example COLIN- do not want in one person system

In SDSF CK, you can use the DL line command to display the information in one screen. Sometimes the line command SV (display in ISPF View) works. You can use the DP line command to display the active policy (if any) for the check.

You can also use standard the SDSF commands sort, arrange and filters (such as FILTER STATUS EQ “INACTIVE”) to limit and change the data displayed.

Printing the full health check log

I used

//IBMHZSPR JOB 1,MSGCLASS=H 
//HZSPRINT EXEC PGM=HZSPRNT,TIME=1440,REGION=0M,PARMDD=SYSIN
//SYSIN DD *
CHECK(*,*)
,EXCEPTIONS
//SYSOUT DD SYSOUT=*,DCB=(LRECL=256)

After I cleaned my system I had two exception, and a total of 150 lines of output.

One minute MVS: Health checker

The z/OS Health checker is a great facility, and makes the systems programmer’s job much easier. z/OS provides a set of configuration guidelines, such as the value for … should be …. At IPL and periodically, it checks the system and reports anything which is out of line. This allows you to check your configuration is consistent with best practice, and may identify problems you were not aware of.

For example it reported

  • I had some digital certificates about to expire or had already expired – whoops.
  • Some OMVS mounts had failed (because the entries in the BPXPRM… file were not active on the system)
  • Some storage allocations were not as recommended.

When I printed out the full report, it told me what the recommended values where, and what values I had in my configuration so it was easy to change.

You can have different sorts of checks

  • local – these run in the Health Checker address space
  • remote – these run in other address spaces and report into the Health Checker
  • Rexx – these run in an address space and report to the Health Checker

You can print out the full list of problems, and this comes with comprehensive help information and instructions on what to do about the problem.

Example output in syslog

HZS0001I CHECK(IBMCS,CSVTAM_CSM_STG_LIMIT): 442                       
ISTH017E Communications storage manager (CSM) storage allocation
definitions might not be optimal
HZS0002E CHECK(IBMRACF,RACF_JESJOBS_ACTIVE): 443
IRRH229E The class JESJOBS is not active.
HZS0001I CHECK(IBMOCE,OCE_XTIOT_CHECK): 444
IECH0101E OPEN macro support for XTIOT, uncaptured UCBs and DSAB
above the line is not enabled for non-VSAM. IBM recommends setting
NON_VSAM_XTIOT=YES in the DEVSUPxx member of PARMLIB.
HZS0001I CHECK(IBMRACF,RACF_PASSWORD_CONTROLS): 445
IRRH283E The RACF_PASSWORD_CONTROLS check found an exception
with one or more password control settings.
HZS0002E CHECK(IBMXCF,XCF_TCLASS_CLASSLEN): 446
IXCH0420E The XCF transport class size segregation configuration on
system S0W1 is inconsistent with the owner specification.

You can disable health checks which you do not want, so after cleaning your system, you should aim to have no health check exceptions.

What do these mean?

You can run a print job

//IBMHZS   JOB 1,MSGCLASS=H 
//HZSPRINT EXEC PGM=HZSPRNT,TIME=1440,REGION=0M,PARMD
//SYSIN DD *
CHECK(*,*)
,EXCEPTIONS
//SYSOUT DD SYSOUT=*,DCB=(LRECL=256)

Example output of print job

Certificates Expiring within 60 Days

CHECK(IBMRACF,RACF_CERTIFICATE_EXPIRATION)                                 
SYSPLEX: ADCDPL SYSTEM: S0W1
START TIME: 01/19/2024 07:14:39.529686
CHECK DATE: 20111010 CHECK SEVERITY: MEDIUM

Certificates Expiring within 60 Days

S Cert Owner Certificate Label End Date Trust Rings
- ------------ -------------------------------- ---------- ----- -----
CERTAUTH Verisign Class 1 Individual CA 2008-05-12 No 0
E ID(START1) JES2 CLIENT EDS 2019-03-21 Yes 1
CERTAUTH GTE CyberTrust Root CA 2006-02-23 No 0
...
Only certificates that are marked as trusted result in exceptions.
Exceptions are indicated by an "E" or an "M" in the "S" (Status)
column. An "E" indicates that the certificate has expired within
time period examined by the check. An "M" indicates that the
certificate has no end date in the certificate profile. The trust
status of the certificate is shown in the "Trust" column. The number
of key rings to which the certificate is connected (other than the
virtual key ring) is shown in the "Rings" column. A value of "99999"
in the "Rings" column indicates that the certificate is connected to
99999 or more rings.
Use the RACDCERT LIST command to list complete information about any
certificate. The RACDCERT command syntax is:

RACDCERT CERTAUTH LIST(LABEL('label-name'))
or
RACDCERT SITE LIST(LABEL('label-name'))
or
RACDCERT ID(user-id) LIST(LABEL('label-name'))
...

BPXH061E One or more file systems specified in the BPXPRMxx parmlib
members are not mounted.

* High Severity Exception *      

BPXH059I The following file systems are not active:
-----------------------------------------------------------
File System: ZWE200.ZFS
Parmlib Member: BPXPRMZW
Path: /usr/lpp/zowe
Return Code: 00000099
Reason Code: EF096150

File System: ZWE200.CONFIG.ZFS
Parmlib Member: BPXPRMZW
Path: /apps/zowe/v20
Return Code: 00000099
Reason Code: EF096150

Whoops – I missed than one due to a finger problem

CSFH0042I Check for weak CCA cryptographic keys in the PKDS

CHECK(IBMICSF,ICSF_WEAK_CCA_KEYS)                                                   
SYSPLEX: ADCDPL SYSTEM: S0W1
START TIME: 01/19/2024 07:15:00.161074
CHECK DATE: 20181101 CHECK SEVERITY: LOW

CSFH0042I Check for weak CCA cryptographic keys in the PKDS

Active PKDS: CSF.CSFPKDS.NEW
---------------------------------------------------------
COLIN
COLIN2

* Low Severity Exception *

CSFH0044E Weak CCA cryptographic keys in the PKDS were found.
....

EZBH008E The port range defined for CINET use has not been reserved for
OMVS on this stack.

CHECK(IBMCS,CSTCP_CINET_PORTRNG_RSV_TCPIP)                                        
SYSPLEX: ADCDPL SYSTEM: S0W1
START TIME: 01/19/2024 07:14:59.665575
CHECK DATE: 20070901 CHECK SEVERITY: MEDIUM

* Medium Severity Exception *

EZBH008E The port range defined for CINET use has not been reserved for
OMVS on this stack.

Explanation: The port range defined for CINET use in the BPXPRMxx
parmlib member is not reserved for OMVS on this stack.
...

Should I use tar or pax to backup my Unix files?

I am running this on z/OS and want to copy Unix files from one z/OS image to another.

The tar command is very popular, and works for most people.

The pax command is similar to tar, but It can also save and restore file attributes that cannot be handled by any other format such as: files greater than 8 GB, large UID, and GID values , large time values and z/OS -specific attributes like user audit and auditor audit flags and file format.

You create a file using

pax -o saveext -wf pax_file_name files_to_add

and

pax -ppx -rf pax_file_name

to extract the files.

Thanks to Gwydion Tudur for the pointers about extended attributes.

Using a data set

You can use a data set as an output file for example you specify “//’COLIN.PAX.HTTP2′”

pax -E -f “//’COLIN.PAX.HTTP2′”

This will display the contents of the file, for example if gives

drwxrwxrwx        1 OMVSKERN SYS1           0 Aug  4 10:03 ./                                  
drwxrwxrwx 1 OMVSKERN SYS1 0 Nov 15 2021 ./images/
drwxrwxrwx 1 OMVSKERN SYS1 0 Nov 15 2021 ./images/ihs/
-rwxrwxrwx --s- 1 OMVSKERN SYS1 223 Nov 15 2021 ./images/ihs/administration.gif

-rwxrwxrwx --s- 1 COLIN SYS1 373 Jun 17 2023 ./colin.html

Using a data set makes it more portable, for example it is a data set, not a file in a Unix file system.

File owners

Within the .pax file the file owner is a name. When the file is unpacked, you can use the -p o option to preserves the user ID and group information. On my system userid OMVSKERN has uid 0, and group SYS1 has gid 0. On my newer z/OS system the file got the uid of COLIN on the new system – not from the old system.

Without the -po option, the files get the uid from the userid executing the pax command.

ISPF find using regular expressions is clever! But…

I had data like OWNER(colin) and wanted to replace the text like “colin” with some other text, regardless of the “colin” value.

I could do it in ISPF edit using

C “OWNER(COLIN)” “OWNER(REPLACE)”
C “OWNER(USER1)” “OWNER(REPLACE)” .

but this quickly got to be tedious. I found you can use regular expressions with ISPF find using regular expressions. Wikipedia says

A regular expression (shortened as regex or regexp), … is a sequence of characters that specifies a match pattern in text. Usually such patterns are used by string-searching algorithms for “find” or “find and replace” operations on strings, or for input validation.

Wikipedia

For example I could use

change rc”owner\(.*\)” “owner(replace)”

which says find the string

“owner” followed by “(” – \( is escaped and not interpreted, followed by zero or more characters, followed by ) - \) is escaped; and replace it with the string “owner(replace)”

What you can do with it

find rc”abc[0-9]” says find a string abc followed by one of the characters in the range 0 to 9 so abc9 is found, but find rc”abc[0-8]” would not find abc9.

But…

Your terminal needs to have the correct code page for square brackets.
If I use “U.S English Code page 37” it works. If I use “Bracket (CP 037 modified) Euro” it does not work.

With the “Bracket (CP 037 modified) Euro”  [ is displayed as Ý, and ] is displayed as ¨, and the ISPF code cannot find [ or ] and so cannot find the string

Old dogs, new tricks: ISPF cut and paste

I had many members with RACF commands within JCL, and wanted to rationalise them so the definitions were in a couple of files, one for userid information, one for define commands, one for permits etc.. I remembered someone once talking about ISPF cut and paste, and this proved to be very useful.

I had a member with

//S1  EXEC PGM=IKJEFT01,REGION=0M 
//* EPLIB DD DISP=SHR,DSN=SYS1.MIGLIB
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *,SYMBOLS=(JCLONLY)
SETROPTS GENERIC(MFADEF) GENCMD(MFADEF)
RDEF MFADEF FACTOR.AZFSTC OWNER(IBMUSER)
SETROPTS RACLIST(MFADEF) CLASSACT(MFADEF)

/*
/*

and wanted to copy the bold text from each file into other files.

Cut

I used the edit command cut .a .b define append with

000007 //SYSTSIN DD *,SYMBOLS=(JCLONLY) 
.a0008 SETROPTS GENERIC(MFADEF) GENCMD(MFADEF)
000009 RDEF MFADEF FACTOR.AZFSTC OWNER(IBMUSER)
.b0010 SETROPTS RACLIST(MFADEF) CLASSACT(MFADEF)
000011 /*

this copied the three lines into a clipboard called define.

You can also use the line commands cc..cc and mm..mm.

For a different file I used CUT add append

000006 //SYSTSIN DD * 
cc ADDUSER AZFSTC DFLTGRP(SYS1) OWNER(SYS1) -
000008 OMVS(AUTOUID) -
000009 NAME('MFA STC') -
000010 NOPASSWORD NOOIDCARD -
cc RESTRICTED
/*

and so on for each file.

If you use the line commands mm … mm it will delete it from the current file after the data has been copied to the clip board.

With PF12 set to retrieve it was easy to recall the cut command in each member.

Paste

After I had finished cutting the text I edited a member ADD and used the paste command. The basic syntax is paste clipboard

Command ===> paste add
A ********************************* Top of Data ***...
****** ******************************** Bottom of Data *...

This takes all the data from the “add” clipboard, and puts it >A<fter the top line. Similarly I edited the DEFS file, and used the “paste defs” command to retrieve the data in the clipboard.

One minute MVS: What is IBM Multi Factor Authentication on z/OS?

Most people are familiar with Multi Factor Authentication (MFA). For example when accessing a banking site through the internet, you have a digital code sent to your phone which you enter in the web page.

There is a phrase associated with MFA. Something you know, something you have. When using internet banking, you use a userid and password(something you know) and the 6 digit code sent to your phone (something you have). At airports, the staff use a badge to get access to secure areas. They swipe the badge (something you have) and have to enter a 4 digit code (something you know).

In-band and out-of-band

With some applications you enter two factors to logon to the application. For example, I can logon to TSO with a “password” 983211:passw0rd - where 983211 is a one time code (which changes every minute) and passw0rd is my password. This is in-band (you enter the combined password >IN<to the application).

I can use a certificate to logon to a web page, get a one time password and enter that into the TSO logon screen. This is indirect, or out-of-band authentication, you set up the password >OUT<side of the application.

What is available on z/OS?

You can set up one-time-codes, or password (or pass phrase), or one-time-code and password (or pass phrase). A password can be up to 8 characters. A pass phrase must be between 14 to 100 characters in length (inclusive).

You can get a one-time-code from several sources:

  • A small hardware device, which you can hang on your keyring
  • Generated from software. I use the IBM Security Verify application on my Android phone. There are other applications, such as Google Authenticator and Duo Mobile, but the code generated by these was not accepted by z/OS. See below.

To set up the mobile phone application you logon on the IBM MFA web browser on your z/OS and get a QR code displayed. This code contains a secret, and other information such as algorithm=SHA256, period=60 seconds, digits=6. The app on your phone reads this and stores the information. When ever you use the app, it displays a code which you enter on z/OS. The value is time limited and expires after a short interval, typically 30 or 60 seconds.

I configured MFA to use just the TOTP (One Time Password). When I logged on to TSO with userid TOTP and the code I got

ICH70008I IBM MFA Message:
AZF1105I TOTP PASSCODE ACCEPTED
ICH70001I TOTP LAST ACCESS AT 07:37:37 ON SATURDAY, JANUARY 6, 2024

When I configured MFA to require TOTP and userid, I had to enter a password like 345112:PASSW0RD, where 345112 was the one time code from the application.

You configure the MFA on a per userid basis. I set up MFA for a new userid called TOTP, and this has to logon with two factors. Another userid only has to logon with the password.

The IBM Security verify application worked out of the box.

With applications Duo Mobile, and Google Authenticator I got message

AZF5042E Preflight saw invalid account metadata

because they provided an invalid code. The applications only worked with the following system wide options

  • Digest Algorithm . . . . . 1 (SHA-1)
  • Token Code Length . .. . 1 (6-digit)
  • Token Period. . . . . . . . . 2 (30 seconds)

See this page for more information.

Yubikey

A Yubikey is a small USB device from which you can get a one time password. I found the site and what you need to order confusing, and purchased the wrong device. On one of the Yubikey pages it compares the different devices. I needed a Yubikey 5 series; I had (wrongly) purchased a Yubikey Security key Series. When the new key arrives I’ll write up how to use it.

Using a certificate

To make your certificate known to the MFA instance, you logon to a web page using TLS. The web browser port has been secured using AT-TLS. When you logon to the web page, the web browser displays the list of valid certificates for you to choose. After you have selected one, the application running in the web server can extract information from the certificate, and update the userid information in the MFA profile for the userid.

You set up an “out-of-bounds policy” saying use which authentication method (use certificates) and how long the password is valid for (60 seconds).

You configure the userid to be able to use the policy.

To be able to logon, the userid logs on to a different web page ../mfa/mypolicy using the same certificate and enters the userid. A TLS handshake is done to the server (validating the certificate), and a password is returned. You enter the password in your application.

Which of my ADCD disks should I move to my SSD device?

I’m working on moving to a newer version of ADCD, but I do not have enough space for all of the ADCD disks, on my SSD drive, so I am using an external USB device. Which of my new files should I move off the USB drive onto my SSD device for best performance?

Background

How much free space do I have on my disk?

The command

df -P /home/zPDT

gave

Filesystem   1024-blocks     Used Available Capacity Mounted on
/dev/nvme0n1p5 382985776 339351984 24105908      94% /home/zPDT

This shows there is not much free space. What is using all of the space?

ls -lSr

the -S is sort by size largest first, the -r is reverse sort, so the largest comes last.

This showed me lots of old ADCD files which I could delete. After I deleted them, df -P showed the disk was only 69% full.

zPDT “disks”

Each device as seen by zPDT is a process. For example

$ps -ef |grep 5079
colin 5079 4792 0 10:21 ? 00:00:00 awsckd --dev=0A94 --cunbr=0001

So process with pid 5079 is running a program awsckd passing in the device number 0A94

Linux statistics

You can access Linux statistics under the /proc tree.

less /proc/5079/io

gave

rchar: 251198496
wchar: 79167416
syscr: 4525
syscw: 1403
read_bytes: 78671872
write_bytes: 78655488
cancelled_write_bytes: 0

rchar: characters read

The number of bytes which this task has caused to be read from storage. This is simply the sum of bytes which this process passed to read(2) and similar system calls. It includes things such as terminal I/O and is unaffected by whether or not actual physical disk I/O was required (the read might have been satisfied from pagecache).

wchar: characters written

The number of bytes which this task has caused, or shall cause to be written to disk. Similar caveats apply here as with rchar.

read_bytes: bytes read

Attempt to count the number of bytes which this process really did cause to be fetched from the
storage layer. This is accurate for block-backed filesystems.

write_bytes: bytes written

Attempt to count the number of bytes which this process caused to be sent to the storage layer.

How to find the hot files

Use the Linux command

grep read_bytes -r /proc/*/io |sort -k2,2 -g

This finds the read_bytes for each process. It then sorts numerically (-g) and displays the output. For example

/proc/5088/io:read_bytes: 55910400
/proc/5078/io:read_bytes: 61440000
/proc/5091/io:read_bytes: 72916992
/proc/5079/io:read_bytes: 78671872
/proc/5076/io:read_bytes: 138698752
/proc/5074/io:read_bytes: 321728512

You can then display the process information

ps -ef |grep 5074

Which gave

… awsckd –dev=0A80 –cunbr=0001

From the devmap ( or z/OS) device 0A80 is C4RES1.

The disks with the most read activity were (in decreasing order) C4RES1, C4SYS1, C4PAGA, USER02, C4CFG1, C4USS1